import eclipse core compiler plugin (version 3.0.1)
authorcrawshaw <crawshaw@ibex.org>
Mon, 22 Nov 2004 19:26:03 +0000 (19:26 +0000)
committercrawshaw <crawshaw@ibex.org>
Mon, 22 Nov 2004 19:26:03 +0000 (19:26 +0000)
darcs-hash:20041122192603-2eb37-b97550ed0c0b3bef299f075cda45c2b08e013a17.gz

280 files changed:
src/java/org/eclipse/jdt/core/compiler/CharOperation.java [new file with mode: 0644]
src/java/org/eclipse/jdt/core/compiler/IProblem.java [new file with mode: 0644]
src/java/org/eclipse/jdt/core/compiler/InvalidInputException.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ASTVisitor.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ClassFile.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/CompilationResult.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/Compiler.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ConfigurableOption.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/IDebugRequestor.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/IProblemFactory.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ASTNode.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Argument.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Assignment.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Block.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/CastExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Clinit.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/DoStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Expression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/FieldReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ForStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/IfStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ImportReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Initializer.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/IntLiteralMinValue.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Javadoc.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocImportReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Literal.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/LongLiteralMinValue.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/MessageSend.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/NameReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/OperatorIds.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Reference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/Statement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/SuperReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ThisReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/TryStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/TypeReference.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/CharArrayCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/DoubleCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/FloatCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/IntegerCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/Label.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/LongCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/ObjectCache.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/Opcodes.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IBinaryField.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IBinaryNestedType.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IBinaryType.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IConstants.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IDependent.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IGenericField.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IGenericMethod.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/IGenericType.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/ISourceField.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/ISourceImport.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/ISourceType.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/FlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/CharConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/Constant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/IntConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/LongConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/impl/StringConstant.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/Binding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/InnerEmulationDependency.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemFieldBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/Scope.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticFieldBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/TagBits.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/NLSLine.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/Parser.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/Scanner.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/LexStream.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser1.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser10.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser11.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser12.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser13.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser14.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser15.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser16.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser17.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser18.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser19.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser2.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser20.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser3.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser4.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser5.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser6.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser7.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser8.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/parser9.rsc [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/parser/readableNames.properties [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/AbortType.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/problem/messages.properties [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/CompoundNameVector.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfInt.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfIntValues.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfLong.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfObject.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/ObjectVector.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/SimpleNameVector.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/Util.java [new file with mode: 0644]
src/java/org/eclipse/jdt/internal/compiler/util/messages.properties [new file with mode: 0644]

diff --git a/src/java/org/eclipse/jdt/core/compiler/CharOperation.java b/src/java/org/eclipse/jdt/core/compiler/CharOperation.java
new file mode 100644 (file)
index 0000000..07d23e3
--- /dev/null
@@ -0,0 +1,2686 @@
+/*******************************************************************************
+ * 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.core.compiler;
+
+/**
+ * This class is a collection of helper methods to manipulate char arrays.
+ * 
+ * @since 2.1
+ */
+public final class CharOperation {
+
+       /**
+        * Constant for an empty char array
+        */
+       public static final char[] NO_CHAR = new char[0];
+
+       /**
+        * Constant for an empty char array with two dimensions.
+        */
+       public static final char[][] NO_CHAR_CHAR = new char[0][];
+       
+       /**
+        * Answers a new array with appending the suffix character at the end of the array.
+        * <br>
+        * <br>
+        * For example:<br>
+        * <ol>
+        * <li><pre>
+        *    array = { 'a', 'b' }
+        *    suffix = 'c'
+        *    => result = { 'a', 'b' , 'c' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = null
+        *    suffix = 'c'
+        *    => result = { 'c' }
+        * </pre></li>
+        * </ol>
+        * 
+        * @param array the array that is concanated with the suffix character
+        * @param suffix the suffix character
+        * @return the new array
+        */
+       public static final char[] append(char[] array, char suffix) {
+               if (array == null)
+                       return new char[] { suffix };
+               int length = array.length;
+               System.arraycopy(array, 0, array = new char[length + 1], 0, length);
+               array[length] = suffix;
+               return array;
+       }
+       /**
+        * Append the given subarray to the target array starting at the given index in the target array.
+        * The start of the subarray is inclusive, the end is exclusive.
+        * Answers a new target array if it needs to grow, otherwise answers the same target array.
+        * <br>
+        * For example:<br>
+        * <ol>
+        * <li><pre>
+        *    target = { 'a', 'b', '0' }
+        *    index = 2
+        *    array = { 'c', 'd' }
+        *    start = 0
+        *    end = 1
+        *    => result = { 'a', 'b' , 'c' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    target = { 'a', 'b' }
+        *    index = 2
+        *    array = { 'c', 'd' }
+        *    start = 0
+        *    end = 1
+        *    => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
+        * </pre></li>
+        * <li><pre>
+        *    target = { 'a', 'b', 'c' }
+        *    index = 1
+        *    array = { 'c', 'd', 'e', 'f' }
+        *    start = 1
+        *    end = 4
+        *    => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
+        * </pre></li>
+        * </ol>
+        * 
+        * @param target the given target
+        * @param index the given index
+        * @param array the given array
+        * @param start the given start index
+        * @param end the given end index
+        * 
+        * @return the new array
+        * @throws NullPointerException if the target array is null
+        */
+       public static final char[] append(char[] target, int index, char[] array, int start, int end) {
+               int targetLength = target.length;
+               int subLength = end-start;
+               int newTargetLength = subLength+index;
+               if (newTargetLength > targetLength) {
+                       System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
+               }
+               System.arraycopy(array, start, target, index, subLength);
+               return target;
+       }
+
+       /**
+        * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
+        * If the first array is null, then the second array is returned.
+        * If the second array is null, then the first array is returned.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = null
+        *    => result = null
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { ' a' } }
+        *    second = null
+        *    => result = { { ' a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = null
+        *    second = { { ' a' } }
+        *    => result = { { ' a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { ' b' } }
+        *    second = { { ' a' } }
+        *    => result = { { ' b' }, { ' a' } }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array to concatenate
+        * @param second the second array to concatenate
+        * @return the concatenation of the two arrays, or null if the two arrays are null.
+        */
+       public static final char[][] arrayConcat(char[][] first, char[][] second) {
+               if (first == null)
+                       return second;
+               if (second == null)
+                       return first;
+
+               int length1 = first.length;
+               int length2 = second.length;
+               char[][] result = new char[length1 + length2][];
+               System.arraycopy(first, 0, result, 0, length1);
+               System.arraycopy(second, 0, result, length1, length2);
+               return result;
+       }
+       /**
+        * Returns the char arrays as an array of Strings
+        * 
+        * @param charArrays the char array to convert
+        * @return the char arrays as an array of Strings or null if the given char arrays is null.
+        * @since 3.0
+        */
+       public static String[] charArrayToStringArray(char[][] charArrays) {
+               if (charArrays == null) {
+                       return null;
+               }
+               String[] strings= new String[charArrays.length];
+               for (int i= 0; i < charArrays.length; i++) {
+                       strings[i]= new String(charArrays[i]);
+               }
+               return strings;
+       }
+       /**
+        * Returns the char array as a String
+
+        * @param charArray the char array to convert
+        * @return the char array as a String or null if the given char array is null.
+        * @since 3.0
+        */
+       public static String charToString(char[] charArray) {
+               if (charArray == null) return null;
+               return new String(charArray);
+       }
+
+       /**
+        * Answers a new array adding the second array at the end of first array.
+        * It answers null if the first and second are null.
+        * If the first array is null, then a new array char[][] is created with second.
+        * If the second array is null, then the first array is returned.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = { 'a' }
+        *    => result = { { ' a' } }
+        * </pre>
+        * <li><pre>
+        *    first = { { ' a' } }
+        *    second = null
+        *    => result = { { ' a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { ' a' } }
+        *    second = { ' b' }
+        *    => result = { { ' a' } , { ' b' } }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array to concatenate
+        * @param second the array to add at the end of the first array
+        * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
+        */
+       public static final char[][] arrayConcat(char[][] first, char[] second) {
+               if (second == null)
+                       return first;
+               if (first == null)
+                       return new char[][] { second };
+
+               int length = first.length;
+               char[][] result = new char[length + 1][];
+               System.arraycopy(first, 0, result, 0, length);
+               result[length] = second;
+               return result;
+       }
+
+       /**
+        * Compares the contents of the two arrays array and prefix. Returns
+        * <ul>
+        * <li>zero if the array starts with the prefix contents</li>
+        * <li>the difference between the first two characters that are not equal </li>
+        * <li>one if array length is lower than the prefix length and that the prefix starts with the 
+        * array contents.</li>
+        * </ul>
+        * <p>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    array = null
+        *    prefix = null
+        *    => result = NullPointerException
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a', 'b', 'c', 'd', 'e' }
+        *    prefix = { 'a', 'b', 'c'}
+        *    => result = 0
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a', 'b', 'c', 'd', 'e' }
+        *    prefix = { 'a', 'B', 'c'}
+        *    => result = 32
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'd', 'b', 'c', 'd', 'e' }
+        *    prefix = { 'a', 'b', 'c'}
+        *    => result = 3
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a', 'b', 'c', 'd', 'e' }
+        *    prefix = { 'd', 'b', 'c'}
+        *    => result = -3
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a', 'a', 'c', 'd', 'e' }
+        *    prefix = { 'a', 'e', 'c'}
+        *    => result = -4
+        * </pre>
+        * </li>
+        * </ol>
+        * </p>
+        * 
+        * @param array the given array
+        * @param prefix the given prefix
+        * @return the result of the comparison (>=0 if array>prefix)
+        * @throws NullPointerException if either array or prefix is null
+        */
+       public static final int compareWith(char[] array, char[] prefix) {
+               int arrayLength = array.length;
+               int prefixLength = prefix.length;
+               int min = Math.min(arrayLength, prefixLength);
+               int i = 0;
+               while (min-- != 0) {
+                       char c1 = array[i];
+                       char c2 = prefix[i++];
+                       if (c1 != c2)
+                               return c1 - c2;
+               }
+               if (prefixLength == i)
+                       return 0;
+               return -1;      // array is shorter than prefix (e.g. array:'ab' < prefix:'abc').
+       }
+
+       /**
+        * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
+        * If the first array is null, then the second array is returned.
+        * If the second array is null, then the first array is returned.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = { 'a' }
+        *    => result = { ' a' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { ' a' }
+        *    second = null
+        *    => result = { ' a' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { ' a' }
+        *    second = { ' b' }
+        *    => result = { ' a' , ' b' }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array to concatenate
+        * @param second the second array to concatenate
+        * @return the concatenation of the two arrays, or null if the two arrays are null.
+        */
+       public static final char[] concat(char[] first, char[] second) {
+               if (first == null)
+                       return second;
+               if (second == null)
+                       return first;
+
+               int length1 = first.length;
+               int length2 = second.length;
+               char[] result = new char[length1 + length2];
+               System.arraycopy(first, 0, result, 0, length1);
+               System.arraycopy(second, 0, result, length1, length2);
+               return result;
+       }
+
+       /**
+        * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
+        * If first is null, it answers the concatenation of second and third.
+        * If second is null, it answers the concatenation of first and third.
+        * If third is null, it answers the concatenation of first and second.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = { 'a' }
+        *    third = { 'b' }
+        *    => result = { ' a', 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    second = null
+        *    third = { 'b' }
+        *    => result = { ' a', 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    second = { 'b' }
+        *    third = null
+        *    => result = { ' a', 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = null
+        *    second = null
+        *    third = null
+        *    => result = null
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    second = { 'b' }
+        *    third = { 'c' }
+        *    => result = { 'a', 'b', 'c' }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array to concatenate
+        * @param second the second array to concatenate
+        * @param third the third array to concatenate
+        * 
+        * @return the concatenation of the three arrays, or null if the three arrays are null.
+        */
+       public static final char[] concat(
+               char[] first,
+               char[] second,
+               char[] third) {
+               if (first == null)
+                       return concat(second, third);
+               if (second == null)
+                       return concat(first, third);
+               if (third == null)
+                       return concat(first, second);
+
+               int length1 = first.length;
+               int length2 = second.length;
+               int length3 = third.length;
+               char[] result = new char[length1 + length2 + length3];
+               System.arraycopy(first, 0, result, 0, length1);
+               System.arraycopy(second, 0, result, length1, length2);
+               System.arraycopy(third, 0, result, length1 + length2, length3);
+               return result;
+       }
+
+       /**
+        * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
+        * It answers null if the two arrays are null.
+        * If the first array is null, then the second array is returned.
+        * If the second array is null, then the first array is returned.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = { 'a' }
+        *    separator = '/'
+        *    => result = { ' a' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { ' a' }
+        *    second = null
+        *    separator = '/'
+        *    => result = { ' a' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { ' a' }
+        *    second = { ' b' }
+        *    separator = '/'
+        *    => result = { ' a' , '/', 'b' }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array to concatenate
+        * @param second the second array to concatenate
+        * @param separator the character to insert
+        * @return the concatenation of the two arrays inserting the separator character 
+        * between the two arrays , or null if the two arrays are null.
+        */
+       public static final char[] concat(
+               char[] first,
+               char[] second,
+               char separator) {
+               if (first == null)
+                       return second;
+               if (second == null)
+                       return first;
+
+               int length1 = first.length;
+               if (length1 == 0)
+                       return second;
+               int length2 = second.length;
+               if (length2 == 0)
+                       return first;
+
+               char[] result = new char[length1 + length2 + 1];
+               System.arraycopy(first, 0, result, 0, length1);
+               result[length1] = separator;
+               System.arraycopy(second, 0, result, length1 + 1, length2);
+               return result;
+       }
+
+       /**
+        * Answers the concatenation of the three arrays inserting the sep1 character between the 
+        * 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.
+        * If the second array is null, then it answers the concatenation of first and third inserting
+        * the sep1 character between them.
+        * If the third array is null, then it answers the concatenation of first and second inserting
+        * the sep1 character between them.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    sep1 = '/'
+        *    second = { 'a' }
+        *    sep2 = ':'
+        *    third = { 'b' }
+        *    => result = { ' a' , ':', 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    sep1 = '/'
+        *    second = null
+        *    sep2 = ':'
+        *    third = { 'b' }
+        *    => result = { ' a' , '/', 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    sep1 = '/'
+        *    second = { 'b' }
+        *    sep2 = ':'
+        *    third = null
+        *    => result = { ' a' , '/', 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    sep1 = '/'
+        *    second = { 'b' }
+        *    sep2 = ':'
+        *    third = { 'c' }
+        *    => result = { ' a' , '/', 'b' , ':', 'c' }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array to concatenate
+        * @param sep1 the character to insert
+        * @param second the second array to concatenate
+        * @param sep2 the character to insert
+        * @param third the second array to concatenate
+        * @return the concatenation of the three arrays inserting the sep1 character between the 
+        * two arrays and sep2 between the last two.
+        */
+       public static final char[] concat(
+               char[] first,
+               char sep1,
+               char[] second,
+               char sep2,
+               char[] third) {
+               if (first == null)
+                       return concat(second, third, sep2);
+               if (second == null)
+                       return concat(first, third, sep1);
+               if (third == null)
+                       return concat(first, second, sep1);
+
+               int length1 = first.length;
+               int length2 = second.length;
+               int length3 = third.length;
+               char[] result = new char[length1 + length2 + length3 + 2];
+               System.arraycopy(first, 0, result, 0, length1);
+               result[length1] = sep1;
+               System.arraycopy(second, 0, result, length1 + 1, length2);
+               result[length1 + length2 + 1] = sep2;
+               System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
+               return result;
+       }
+
+       /**
+        * Answers a new array with prepending the prefix character and appending the suffix 
+        * character at the end of the array. If array is null, it answers a new array containing the 
+        * prefix and the suffix characters.
+        * <br>
+        * <br>
+        * For example:<br>
+        * <ol>
+        * <li><pre>
+        *    prefix = 'a'
+        *    array = { 'b' }
+        *    suffix = 'c'
+        *    => result = { 'a', 'b' , 'c' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    prefix = 'a'
+        *    array = null
+        *    suffix = 'c'
+        *    => result = { 'a', 'c' }
+        * </pre></li>
+        * </ol>
+        * 
+        * @param prefix the prefix character
+        * @param array the array that is concanated with the prefix and suffix characters
+        * @param suffix the suffix character
+        * @return the new array
+        */
+       public static final char[] concat(char prefix, char[] array, char suffix) {
+               if (array == null)
+                       return new char[] { prefix, suffix };
+
+               int length = array.length;
+               char[] result = new char[length + 2];
+               result[0] = prefix;
+               System.arraycopy(array, 0, result, 1, length);
+               result[length + 1] = suffix;
+               return result;
+       }
+       
+       /**
+        * Answers the concatenation of the given array parts using the given separator between each
+        * part and appending the given name at the end.
+        * <br>
+        * <br>
+        * For example:<br>
+        * <ol>
+        * <li><pre>
+        *    name = { 'c' }
+        *    array = { { 'a' }, { 'b' } }
+        *    separator = '.'
+        *    => result = { 'a', '.', 'b' , '.', 'c' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    name = null
+        *    array = { { 'a' }, { 'b' } }
+        *    separator = '.'
+        *    => result = { 'a', '.', 'b' }
+        * </pre></li>
+        * <li><pre>
+        *    name = { ' c' }
+        *    array = null
+        *    separator = '.'
+        *    => result = { 'c' }
+        * </pre></li>
+        * </ol>
+        * 
+        * @param name the given name
+        * @param array the given array
+        * @param separator the given separator
+        * @return the concatenation of the given array parts using the given separator between each
+        * part and appending the given name at the end
+        */
+       public static final char[] concatWith(
+               char[] name,
+               char[][] array,
+               char separator) {
+               int nameLength = name == null ? 0 : name.length;
+               if (nameLength == 0)
+                       return concatWith(array, separator);
+
+               int length = array == null ? 0 : array.length;
+               if (length == 0)
+                       return name;
+
+               int size = nameLength;
+               int index = length;
+               while (--index >= 0)
+                       if (array[index].length > 0)
+                               size += array[index].length + 1;
+               char[] result = new char[size];
+               index = size;
+               for (int i = length - 1; i >= 0; i--) {
+                       int subLength = array[i].length;
+                       if (subLength > 0) {
+                               index -= subLength;
+                               System.arraycopy(array[i], 0, result, index, subLength);
+                               result[--index] = separator;
+                       }
+               }
+               System.arraycopy(name, 0, result, 0, nameLength);
+               return result;
+       }
+
+       /**
+        * Answers the concatenation of the given array parts using the given separator between each
+        * part and appending the given name at the end.
+        * <br>
+        * <br>
+        * For example:<br>
+        * <ol>
+        * <li><pre>
+        *    name = { 'c' }
+        *    array = { { 'a' }, { 'b' } }
+        *    separator = '.'
+        *    => result = { 'a', '.', 'b' , '.', 'c' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    name = null
+        *    array = { { 'a' }, { 'b' } }
+        *    separator = '.'
+        *    => result = { 'a', '.', 'b' }
+        * </pre></li>
+        * <li><pre>
+        *    name = { ' c' }
+        *    array = null
+        *    separator = '.'
+        *    => result = { 'c' }
+        * </pre></li>
+        * </ol>
+        * 
+        * @param array the given array
+        * @param name the given name
+        * @param separator the given separator
+        * @return the concatenation of the given array parts using the given separator between each
+        * part and appending the given name at the end
+        */
+       public static final char[] concatWith(
+               char[][] array,
+               char[] name,
+               char separator) {
+               int nameLength = name == null ? 0 : name.length;
+               if (nameLength == 0)
+                       return concatWith(array, separator);
+
+               int length = array == null ? 0 : array.length;
+               if (length == 0)
+                       return name;
+
+               int size = nameLength;
+               int index = length;
+               while (--index >= 0)
+                       if (array[index].length > 0)
+                               size += array[index].length + 1;
+               char[] result = new char[size];
+               index = 0;
+               for (int i = 0; i < length; i++) {
+                       int subLength = array[i].length;
+                       if (subLength > 0) {
+                               System.arraycopy(array[i], 0, result, index, subLength);
+                               index += subLength;
+                               result[index++] = separator;
+                       }
+               }
+               System.arraycopy(name, 0, result, index, nameLength);
+               return result;
+       }
+
+       /**
+        * Answers the concatenation of the given array parts using the given separator between each part.
+        * <br>
+        * <br>
+        * For example:<br>
+        * <ol>
+        * <li><pre>
+        *    array = { { 'a' }, { 'b' } }
+        *    separator = '.'
+        *    => result = { 'a', '.', 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = null
+        *    separator = '.'
+        *    => result = { }
+        * </pre></li>
+        * </ol>
+        * 
+        * @param array the given array
+        * @param separator the given separator
+        * @return the concatenation of the given array parts using the given separator between each part
+        */
+       public static final char[] concatWith(char[][] array, char separator) {
+               int length = array == null ? 0 : array.length;
+               if (length == 0)
+                       return CharOperation.NO_CHAR;
+
+               int size = length - 1;
+               int index = length;
+               while (--index >= 0) {
+                       if (array[index].length == 0)
+                               size--;
+                       else
+                               size += array[index].length;
+               }
+               if (size <= 0)
+                       return CharOperation.NO_CHAR;
+               char[] result = new char[size];
+               index = length;
+               while (--index >= 0) {
+                       length = array[index].length;
+                       if (length > 0) {
+                               System.arraycopy(
+                                       array[index],
+                                       0,
+                                       result,
+                                       (size -= length),
+                                       length);
+                               if (--size >= 0)
+                                       result[size] = separator;
+                       }
+               }
+               return result;
+       }
+       
+       /**
+        * Answers true if the array contains an occurrence of character, false otherwise.
+        * 
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    character = 'c'
+        *    array = { { ' a' }, { ' b' } }
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    character = 'a'
+        *    array = { { ' a' }, { ' b' } }
+        *    result => true
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param character the character to search
+        * @param array the array in which the search is done
+        * @return true if the array contains an occurrence of character, false otherwise.
+        * @throws NullPointerException if array is null.
+        */
+       public static final boolean contains(char character, char[][] array) {
+               for (int i = array.length; --i >= 0;) {
+                       char[] subarray = array[i];
+                       for (int j = subarray.length; --j >= 0;)
+                               if (subarray[j] == character)
+                                       return true;
+               }
+               return false;
+       }
+
+       /**
+        * Answers true if the array contains an occurrence of character, false otherwise.
+        * 
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    character = 'c'
+        *    array = { ' b'  }
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    character = 'a'
+        *    array = { ' a' , ' b' }
+        *    result => true
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param character the character to search
+        * @param array the array in which the search is done
+        * @return true if the array contains an occurrence of character, false otherwise.
+        * @throws NullPointerException if array is null.
+        */
+       public static final boolean contains(char character, char[] array) {
+               for (int i = array.length; --i >= 0;)
+                       if (array[i] == character)
+                               return true;
+               return false;
+       }
+       
+       /**
+        * Answers a deep copy of the toCopy array.
+        * 
+        * @param toCopy the array to copy
+        * @return a deep copy of the toCopy array.
+        */
+       public static final char[][] deepCopy(char[][] toCopy) {
+               int toCopyLength = toCopy.length;
+               char[][] result = new char[toCopyLength][];
+               for (int i = 0; i < toCopyLength; i++) {
+                       char[] toElement = toCopy[i];
+                       int toElementLength = toElement.length;
+                       char[] resultElement = new char[toElementLength];
+                       System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
+                       result[i] = resultElement;
+               }
+               return result;
+       }
+
+       /**
+        * Return true if array ends with the sequence of characters contained in toBeFound, 
+        * otherwise false.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    array = { 'a', 'b', 'c', 'd' }
+        *    toBeFound = { 'b', 'c' }
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a', 'b', 'c' }
+        *    toBeFound = { 'b', 'c' }
+        *    result => true
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param array the array to check
+        * @param toBeFound the array to find
+        * @return true if array ends with the sequence of characters contained in toBeFound, 
+        * otherwise false.
+        * @throws NullPointerException if array is null or toBeFound is null
+        */
+       public static final boolean endsWith(char[] array, char[] toBeFound) {
+               int i = toBeFound.length;
+               int j = array.length - i;
+
+               if (j < 0)
+                       return false;
+               while (--i >= 0)
+                       if (toBeFound[i] != array[i + j])
+                               return false;
+               return true;
+       }
+
+       /**
+        * Answers true if the two arrays are identical character by character, otherwise false.
+        * The equality is case sensitive.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = null
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { } }
+        *    second = null
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { 'a' } }
+        *    second = { { 'a' } }
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { 'A' } }
+        *    second = { { 'a' } }
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * @param first the first array
+        * @param second the second array
+        * @return true if the two arrays are identical character by character, otherwise false
+        */
+       public static final boolean equals(char[][] first, char[][] second) {
+               if (first == second)
+                       return true;
+               if (first == null || second == null)
+                       return false;
+               if (first.length != second.length)
+                       return false;
+
+               for (int i = first.length; --i >= 0;)
+                       if (!equals(first[i], second[i]))
+                               return false;
+               return true;
+       }
+
+       /**
+        * If isCaseSensite is true, answers true if the two arrays are identical character
+        * by character, otherwise false.
+        * If it is false, answers true if the two arrays are identical character by 
+        * character without checking the case, otherwise false.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = null
+        *    isCaseSensitive = true
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { } }
+        *    second = null
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { 'A' } }
+        *    second = { { 'a' } }
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { { 'A' } }
+        *    second = { { 'a' } }
+        *    isCaseSensitive = false
+        *    result => true
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array
+        * @param second the second array
+        * @param isCaseSensitive check whether or not the equality should be case sensitive
+        * @return true if the two arrays are identical character by character according to the value
+        * of isCaseSensitive, otherwise false
+        */
+       public static final boolean equals(
+               char[][] first,
+               char[][] second,
+               boolean isCaseSensitive) {
+
+               if (isCaseSensitive) {
+                       return equals(first, second);
+               }
+               if (first == second)
+                       return true;
+               if (first == null || second == null)
+                       return false;
+               if (first.length != second.length)
+                       return false;
+
+               for (int i = first.length; --i >= 0;)
+                       if (!equals(first[i], second[i], false))
+                               return false;
+               return true;
+       }
+
+       /**
+        * Answers true if the two arrays are identical character by character, otherwise false.
+        * The equality is case sensitive.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = null
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { }
+        *    second = null
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    second = { 'a' }
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    second = { 'A' }
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * @param first the first array
+        * @param second the second array
+        * @return true if the two arrays are identical character by character, otherwise false
+        */
+       public static final boolean equals(char[] first, char[] second) {
+               if (first == second)
+                       return true;
+               if (first == null || second == null)
+                       return false;
+               if (first.length != second.length)
+                       return false;
+
+               for (int i = first.length; --i >= 0;)
+                       if (first[i] != second[i])
+                               return false;
+               return true;
+       }
+       
+       /**
+        * Answers true if the first array is identical character by character to a portion of the second array
+        * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
+        * The equality is case sensitive.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = null
+        *    secondStart = 0
+        *    secondEnd = 0
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { }
+        *    second = null
+        *    secondStart = 0
+        *    secondEnd = 0
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    second = { 'a' }
+        *    secondStart = 0
+        *    secondEnd = 1
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'a' }
+        *    second = { 'A' }
+        *    secondStart = 0
+        *    secondEnd = 1
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * @param first the first array
+        * @param second the second array
+        * @param secondStart inclusive start position in the second array to compare
+        * @param secondEnd exclusive end position in the second array to compare
+        * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
+        * @since 3.0
+        */
+       public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) {
+               if (first == second)
+                       return true;
+               if (first == null || second == null)
+                       return false;
+               if (first.length != secondEnd - secondStart)
+                       return false;
+
+               for (int i = first.length; --i >= 0;)
+                       if (first[i] != second[i+secondStart])
+                               return false;
+               return true;
+       }
+
+       /**
+        * If isCaseSensite is true, answers true if the two arrays are identical character
+        * by character, otherwise false.
+        * If it is false, answers true if the two arrays are identical character by 
+        * character without checking the case, otherwise false.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    first = null
+        *    second = null
+        *    isCaseSensitive = true
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { }
+        *    second = null
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'A' }
+        *    second = { 'a' }
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    first = { 'A' }
+        *    second = { 'a' }
+        *    isCaseSensitive = false
+        *    result => true
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param first the first array
+        * @param second the second array
+        * @param isCaseSensitive check whether or not the equality should be case sensitive
+        * @return true if the two arrays are identical character by character according to the value
+        * of isCaseSensitive, otherwise false
+        */
+       public static final boolean equals(
+               char[] first,
+               char[] second,
+               boolean isCaseSensitive) {
+
+               if (isCaseSensitive) {
+                       return equals(first, second);
+               }
+               if (first == second)
+                       return true;
+               if (first == null || second == null)
+                       return false;
+               if (first.length != second.length)
+                       return false;
+
+               for (int i = first.length; --i >= 0;)
+                       if (Character.toLowerCase(first[i])
+                               != Character.toLowerCase(second[i]))
+                               return false;
+               return true;
+       }
+       /**
+        * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
+        * 
+        * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    fragment = { 'b', 'c' , 'd' }
+        *    name = { 'a', 'b', 'c' , 'd' }
+        *    startIndex = 1
+        *    isCaseSensitive = true
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    fragment = { 'b', 'c' , 'd' }
+        *    name = { 'a', 'b', 'C' , 'd' }
+        *    startIndex = 1
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    fragment = { 'b', 'c' , 'd' }
+        *    name = { 'a', 'b', 'C' , 'd' }
+        *    startIndex = 0
+        *    isCaseSensitive = false
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    fragment = { 'b', 'c' , 'd' }
+        *    name = { 'a', 'b'}
+        *    startIndex = 0
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param fragment the fragment to check
+        * @param name the array to check
+        * @param startIndex the starting index
+        * @param isCaseSensitive check whether or not the equality should be case sensitive
+        * @return true if the name contains the fragment at the starting index startIndex according to the 
+        * value of isCaseSensitive, otherwise false.
+        * @throws NullPointerException if fragment or name is null.
+        */
+       public static final boolean fragmentEquals(
+               char[] fragment,
+               char[] name,
+               int startIndex,
+               boolean isCaseSensitive) {
+
+               int max = fragment.length;
+               if (name.length < max + startIndex)
+                       return false;
+               if (isCaseSensitive) {
+                       for (int i = max;
+                               --i >= 0;
+                               ) // assumes the prefix is not larger than the name
+                               if (fragment[i] != name[i + startIndex])
+                                       return false;
+                       return true;
+               }
+               for (int i = max;
+                       --i >= 0;
+                       ) // assumes the prefix is not larger than the name
+                       if (Character.toLowerCase(fragment[i])
+                               != Character.toLowerCase(name[i + startIndex]))
+                               return false;
+               return true;
+       }
+
+       /**
+        * Answers a hashcode for the array
+        * 
+        * @param array the array for which a hashcode is required
+        * @return the hashcode
+        * @throws NullPointerException if array is null
+        */
+       public static final int hashCode(char[] array) {
+               int hash = 0;
+               int offset = 0;
+               int length = array.length;
+               if (length < 16) {
+                       for (int i = length; i > 0; i--)
+                               hash = (hash * 37) + array[offset++];
+               } else {
+                       // only sample some characters
+                       int skip = length / 8;
+                       for (int i = length; i > 0; i -= skip, offset += skip)
+                               hash = (hash * 39) + array[offset];
+               }
+               return hash & 0x7FFFFFFF;
+       }
+       /**
+        * Answers true if c is a whitespace according to the JLS (&#92;u000a, &#92;u000c, &#92;u000d, &#92;u0009), otherwise false.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    c = ' '
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    c = '&#92;u3000'
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param c the character to check
+        * @return true if c is a whitespace according to the JLS, otherwise false.
+        */
+       public static boolean isWhitespace(char c) {
+               switch (c) {
+                       case 10 : /* \ u000a: LINE FEED               */
+                       case 12 : /* \ u000c: FORM FEED               */
+                       case 13 : /* \ u000d: CARRIAGE RETURN         */
+                       case 32 : /* \ u0020: SPACE                   */
+                       case 9 : /* \ u0009: HORIZONTAL TABULATION   */
+                               return true;
+                       default :
+                               return false;
+               }
+       }
+       
+       /**
+        * Answers the first index in the array for which the corresponding character is
+        * equal to toBeFound. Answers -1 if no occurrence of this character is found.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    result => 2
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'e'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    result => -1
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param toBeFound the character to search
+        * @param array the array to be searched
+        * @return the first index in the array for which the corresponding character is
+        * equal to toBeFound, -1 otherwise
+        * @throws NullPointerException if array is null
+        */
+       public static final int indexOf(char toBeFound, char[] array) {
+               for (int i = 0; i < array.length; i++)
+                       if (toBeFound == array[i])
+                               return i;
+               return -1;
+       }
+
+       /**
+        * Answers the first index in the array for which the corresponding character is
+        * equal to toBeFound starting the search at index start.
+        * Answers -1 if no occurrence of this character is found.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    start = 2
+        *    result => 2
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    start = 3
+        *    result => -1
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'e'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    start = 1
+        *    result => -1
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param toBeFound the character to search
+        * @param array the array to be searched
+        * @param start the starting index
+        * @return the first index in the array for which the corresponding character is
+        * equal to toBeFound, -1 otherwise
+        * @throws NullPointerException if array is null
+        * @throws ArrayIndexOutOfBoundsException if  start is lower than 0
+        */
+       public static final int indexOf(char toBeFound, char[] array, int start) {
+               for (int i = start; i < array.length; i++)
+                       if (toBeFound == array[i])
+                               return i;
+               return -1;
+       }
+
+       /**
+        * Answers the last index in the array for which the corresponding character is
+        * equal to toBeFound starting from the end of the array.
+        * Answers -1 if no occurrence of this character is found.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
+        *    result => 4
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'e'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    result => -1
+        * </pre>
+        * </li>
+        * </ol>
+        *
+        * @param toBeFound the character to search
+        * @param array the array to be searched
+        * @return the last index in the array for which the corresponding character is
+        * equal to toBeFound starting from the end of the array, -1 otherwise
+        * @throws NullPointerException if array is null
+        */
+       public static final int lastIndexOf(char toBeFound, char[] array) {
+               for (int i = array.length; --i >= 0;)
+                       if (toBeFound == array[i])
+                               return i;
+               return -1;
+       }
+
+       /**
+        * Answers the last index in the array for which the corresponding character is
+        * equal to toBeFound stopping at the index startIndex.
+        * Answers -1 if no occurrence of this character is found.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    startIndex = 2
+        *    result => 2
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd', 'e' }
+        *    startIndex = 3
+        *    result => -1
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'e'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    startIndex = 0
+        *    result => -1
+        * </pre>
+        * </li>
+        * </ol>
+        *
+        * @param toBeFound the character to search
+        * @param array the array to be searched
+        * @param startIndex the stopping index
+        * @return the last index in the array for which the corresponding character is
+        * equal to toBeFound stopping at the index startIndex, -1 otherwise
+        * @throws NullPointerException if array is null
+        * @throws ArrayIndexOutOfBoundsException if startIndex is lower than 0
+        */
+       public static final int lastIndexOf(
+               char toBeFound,
+               char[] array,
+               int startIndex) {
+               for (int i = array.length; --i >= startIndex;)
+                       if (toBeFound == array[i])
+                               return i;
+               return -1;
+       }
+
+       /**
+        * Answers the last index in the array for which the corresponding character is
+        * equal to toBeFound starting from endIndex to startIndex.
+        * Answers -1 if no occurrence of this character is found.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    startIndex = 2
+        *    endIndex = 2
+        *    result => 2
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { ' a', 'b', 'c', 'd', 'e' }
+        *    startIndex = 3
+        *    endIndex = 4
+        *    result => -1
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'e'
+        *    array = { ' a', 'b', 'c', 'd' }
+        *    startIndex = 0
+        *    endIndex = 3
+        *    result => -1
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param toBeFound the character to search
+        * @param array the array to be searched
+        * @param startIndex the stopping index
+        * @param endIndex the starting index
+        * @return the last index in the array for which the corresponding character is
+        * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
+        * @throws NullPointerException if array is null
+        * @throws ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
+        */
+       public static final int lastIndexOf(
+               char toBeFound,
+               char[] array,
+               int startIndex,
+               int endIndex) {
+               for (int i = endIndex; --i >= startIndex;)
+                       if (toBeFound == array[i])
+                               return i;
+               return -1;
+       }
+       
+       /**
+        * Answers the last portion of a name given a separator.
+        * <br>
+        * <br>
+        * For example,
+        * <pre>
+        *      lastSegment("java.lang.Object".toCharArray(),'.') --> Object
+        * </pre>
+        * 
+        * @param array the array
+        * @param separator the given separator
+        * @return the last portion of a name given a separator
+        * @throws NullPointerException if array is null
+        */
+       final static public char[] lastSegment(char[] array, char separator) {
+               int pos = lastIndexOf(separator, array);
+               if (pos < 0)
+                       return array;
+               return subarray(array, pos + 1, array.length);
+       }
+
+       /**
+        * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
+        * accepts wild-cards '*' and '?'.
+        *
+        * When not case sensitive, the pattern is assumed to already be lowercased, the
+        * name will be lowercased character per character as comparing.
+        * If name is null, the answer is false.
+        * If pattern is null, the answer is true if name is not null.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    pattern = { '?', 'b', '*' }
+        *    name = { 'a', 'b', 'c' , 'd' }
+        *    isCaseSensitive = true
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    pattern = { '?', 'b', '?' }
+        *    name = { 'a', 'b', 'c' , 'd' }
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    pattern = { 'b', '*' }
+        *    name = { 'a', 'b', 'c' , 'd' }
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param pattern the given pattern
+        * @param name the given name
+        * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
+        * @return true if the pattern matches the given name, false otherwise
+        */
+       public static final boolean match(
+               char[] pattern,
+               char[] name,
+               boolean isCaseSensitive) {
+
+               if (name == null)
+                       return false; // null name cannot match
+               if (pattern == null)
+                       return true; // null pattern is equivalent to '*'
+
+               return match(
+                       pattern,
+                       0,
+                       pattern.length,
+                       name,
+                       0,
+                       name.length,
+                       isCaseSensitive);
+       }
+
+       /**
+        * Answers true if the a sub-pattern matches the subpart of the given name, false otherwise.
+        * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
+        * end positions are non-inclusive.
+        * The subpattern is defined by the patternStart and pattternEnd positions.
+        * When not case sensitive, the pattern is assumed to already be lowercased, the
+        * name will be lowercased character per character as comparing.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    pattern = { '?', 'b', '*' }
+        *    patternStart = 1
+        *    patternEnd = 3
+        *    name = { 'a', 'b', 'c' , 'd' }
+        *    nameStart = 1
+        *    nameEnd = 4
+        *    isCaseSensitive = true
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    pattern = { '?', 'b', '*' }
+        *    patternStart = 1
+        *    patternEnd = 2
+        *    name = { 'a', 'b', 'c' , 'd' }
+        *    nameStart = 1
+        *    nameEnd = 2
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param pattern the given pattern
+        * @param patternStart the given pattern start
+        * @param patternEnd the given pattern end
+        * @param name the given name
+        * @param nameStart the given name start
+        * @param nameEnd the given name end
+        * @param isCaseSensitive flag to know if the matching should be case sensitive
+        * @return true if the a sub-pattern matches the subpart of the given name, false otherwise
+        */
+       public static final boolean match(
+               char[] pattern,
+               int patternStart,
+               int patternEnd,
+               char[] name,
+               int nameStart,
+               int nameEnd,
+               boolean isCaseSensitive) {
+
+               if (name == null)
+                       return false; // null name cannot match
+               if (pattern == null)
+                       return true; // null pattern is equivalent to '*'
+               int iPattern = patternStart;
+               int iName = nameStart;
+
+               if (patternEnd < 0)
+                       patternEnd = pattern.length;
+               if (nameEnd < 0)
+                       nameEnd = name.length;
+
+               /* check first segment */
+               char patternChar = 0;
+               while ((iPattern < patternEnd)
+                       && (patternChar = pattern[iPattern]) != '*') {
+                       if (iName == nameEnd)
+                               return false;
+                       if (patternChar
+                               != (isCaseSensitive
+                                       ? name[iName]
+                                       : Character.toLowerCase(name[iName]))
+                               && patternChar != '?') {
+                               return false;
+                       }
+                       iName++;
+                       iPattern++;
+               }
+               /* check sequence of star+segment */
+               int segmentStart;
+               if (patternChar == '*') {
+                       segmentStart = ++iPattern; // skip star
+               } else {
+                       segmentStart = 0; // force iName check
+               }
+               int prefixStart = iName;
+               checkSegment : while (iName < nameEnd) {
+                       if (iPattern == patternEnd) {
+                               iPattern = segmentStart; // mismatch - restart current segment
+                               iName = ++prefixStart;
+                               continue checkSegment;
+                       }
+                       /* segment is ending */
+                       if ((patternChar = pattern[iPattern]) == '*') {
+                               segmentStart = ++iPattern; // skip start
+                               if (segmentStart == patternEnd) {
+                                       return true;
+                               }
+                               prefixStart = iName;
+                               continue checkSegment;
+                       }
+                       /* check current name character */
+                       if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName]))
+                                               != patternChar
+                                       && patternChar != '?') {
+                               iPattern = segmentStart; // mismatch - restart current segment
+                               iName = ++prefixStart;
+                               continue checkSegment;
+                       }
+                       iName++;
+                       iPattern++;
+               }
+
+               return (segmentStart == patternEnd)
+                       || (iName == nameEnd && iPattern == patternEnd)
+                       || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
+       }
+
+       /**
+        * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
+        * 
+        * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
+        * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
+        * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
+        * any folder combination.
+        * Special rule: 
+        * - foo\  is equivalent to foo\**   
+        * When not case sensitive, the pattern is assumed to already be lowercased, the
+        * name will be lowercased character per character as comparing.
+        * 
+        * @param pattern the given pattern
+        * @param filepath the given path 
+        * @param isCaseSensitive to find out whether or not the matching should be case sensitive
+        * @param pathSeparator the given path separator
+        * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
+        */
+       public static final boolean pathMatch(
+               char[] pattern,
+               char[] filepath,
+               boolean isCaseSensitive,
+               char pathSeparator) {
+
+               if (filepath == null)
+                       return false; // null name cannot match
+               if (pattern == null)
+                       return true; // null pattern is equivalent to '*'
+
+               // offsets inside pattern
+               int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
+               int pLength = pattern.length;
+               int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
+               if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+               // special case: pattern foo\ is equivalent to foo\**
+               boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
+
+               // offsets inside filepath
+               int fSegmentStart, fLength = filepath.length;
+               if (filepath[0] != pathSeparator){
+                       fSegmentStart = 0;
+               } else {
+                       fSegmentStart = 1;
+               }
+               if (fSegmentStart != pSegmentStart) {
+                       return false; // both must start with a separator or none.
+               }
+               int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
+               if (fSegmentEnd < 0) fSegmentEnd = fLength;
+
+               // first segments
+               while (pSegmentStart < pLength
+                       && !(pSegmentEnd == pLength && freeTrailingDoubleStar
+                                       || (pSegmentEnd == pSegmentStart + 2
+                                                       && pattern[pSegmentStart] == '*'
+                                                       && pattern[pSegmentStart + 1] == '*'))) {
+
+                       if (fSegmentStart >= fLength)
+                               return false;
+                       if (!CharOperation
+                               .match(
+                                       pattern,
+                                       pSegmentStart,
+                                       pSegmentEnd,
+                                       filepath,
+                                       fSegmentStart,
+                                       fSegmentEnd,
+                                       isCaseSensitive)) {
+                               return false;
+                       }
+
+                       // jump to next segment         
+                       pSegmentEnd =
+                               CharOperation.indexOf(
+                                       pathSeparator,
+                                       pattern,
+                                       pSegmentStart = pSegmentEnd + 1);
+                       // skip separator
+                       if (pSegmentEnd < 0)
+                               pSegmentEnd = pLength;
+
+                       fSegmentEnd =
+                               CharOperation.indexOf(
+                                       pathSeparator,
+                                       filepath,
+                                       fSegmentStart = fSegmentEnd + 1);
+                       // skip separator
+                       if (fSegmentEnd < 0) fSegmentEnd = fLength;
+               }
+
+               /* check sequence of doubleStar+segment */
+               int pSegmentRestart;
+               if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
+                               || (pSegmentEnd == pSegmentStart + 2
+                                       && pattern[pSegmentStart] == '*'
+                                       && pattern[pSegmentStart + 1] == '*')) {
+                       pSegmentEnd =
+                               CharOperation.indexOf(
+                                       pathSeparator,
+                                       pattern,
+                                       pSegmentStart = pSegmentEnd + 1);
+                       // skip separator
+                       if (pSegmentEnd < 0) pSegmentEnd = pLength;
+                       pSegmentRestart = pSegmentStart;
+               } else {
+                       if (pSegmentStart >= pLength) return fSegmentStart >= fLength; // true if filepath is done too.
+                       pSegmentRestart = 0; // force fSegmentStart check
+               }
+               int fSegmentRestart = fSegmentStart;
+               checkSegment : while (fSegmentStart < fLength) {
+                               
+                       if (pSegmentStart >= pLength) {
+                               if (freeTrailingDoubleStar) return true;
+                               // mismatch - restart current path segment
+                               pSegmentEnd =
+                                       CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
+                               if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+                               fSegmentRestart = 
+                                       CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
+                               // skip separator
+                               if (fSegmentRestart < 0) {
+                                       fSegmentRestart = fLength;
+                               } else {
+                                       fSegmentRestart++;
+                               }
+                               fSegmentEnd =
+                                       CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
+                               if (fSegmentEnd < 0) fSegmentEnd = fLength;
+                               continue checkSegment;
+                       }
+                       
+                       /* path segment is ending */
+                       if (pSegmentEnd == pSegmentStart + 2
+                               && pattern[pSegmentStart] == '*'
+                               && pattern[pSegmentStart + 1] == '*') {
+                               pSegmentEnd =
+                                       CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
+                               // skip separator
+                               if (pSegmentEnd < 0) pSegmentEnd = pLength;
+                               pSegmentRestart = pSegmentStart;
+                               fSegmentRestart = fSegmentStart;
+                               if (pSegmentStart >= pLength) return true;
+                               continue checkSegment;
+                       }
+                       /* chech current path segment */
+                       if (!CharOperation.match(
+                                                               pattern,
+                                                               pSegmentStart,
+                                                               pSegmentEnd,
+                                                               filepath,
+                                                               fSegmentStart,
+                                                               fSegmentEnd,
+                                                               isCaseSensitive)) {
+                               // mismatch - restart current path segment
+                               pSegmentEnd =
+                                       CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
+                               if (pSegmentEnd < 0) pSegmentEnd = pLength;
+
+                               fSegmentRestart = 
+                                       CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
+                               // skip separator
+                               if (fSegmentRestart < 0) {
+                                       fSegmentRestart = fLength;
+                               } else {
+                                       fSegmentRestart++;
+                               }
+                               fSegmentEnd =
+                                       CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
+                               if (fSegmentEnd < 0) fSegmentEnd = fLength;
+                               continue checkSegment;
+                       }
+                       // jump to next segment         
+                       pSegmentEnd =
+                               CharOperation.indexOf(
+                                       pathSeparator,
+                                       pattern,
+                                       pSegmentStart = pSegmentEnd + 1);
+                       // skip separator
+                       if (pSegmentEnd < 0)
+                               pSegmentEnd = pLength;
+
+                       fSegmentEnd =
+                               CharOperation.indexOf(
+                                       pathSeparator,
+                                       filepath,
+                                       fSegmentStart = fSegmentEnd + 1);
+                       // skip separator
+                       if (fSegmentEnd < 0)
+                               fSegmentEnd = fLength;
+               }
+
+               return (pSegmentRestart >= pSegmentEnd)
+                       || (fSegmentStart >= fLength && pSegmentStart >= pLength)
+                       || (pSegmentStart == pLength - 2
+                               && pattern[pSegmentStart] == '*'
+                               && pattern[pSegmentStart + 1] == '*')
+                       || (pSegmentStart == pLength && freeTrailingDoubleStar);
+       }
+
+       /**
+        * Answers the number of occurrences of the given character in the given array, 0 if any.
+        * 
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    toBeFound = 'b'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => 3
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => 0
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param toBeFound the given character
+        * @param array the given array
+        * @return the number of occurrences of the given character in the given array, 0 if any
+        * @throws NullPointerException if array is null
+        */
+       public static final int occurencesOf(char toBeFound, char[] array) {
+               int count = 0;
+               for (int i = 0; i < array.length; i++)
+                       if (toBeFound == array[i])
+                               count++;
+               return count;
+       }
+
+       /**
+        * Answers the number of occurrences of the given character in the given array starting
+        * at the given index, 0 if any.
+        * 
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    toBeFound = 'b'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    start = 2
+        *    result => 2
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    toBeFound = 'c'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    start = 0
+        *    result => 0
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param toBeFound the given character
+        * @param array the given array
+        * @param start the given index
+        * @return the number of occurrences of the given character in the given array, 0 if any
+        * @throws NullPointerException if array is null
+        * @throws ArrayIndexOutOfBoundsException if start is lower than 0
+        */
+       public static final int occurencesOf(
+               char toBeFound,
+               char[] array,
+               int start) {
+               int count = 0;
+               for (int i = start; i < array.length; i++)
+                       if (toBeFound == array[i])
+                               count++;
+               return count;
+       }
+
+       /**
+        * Answers true if the given name starts with the given prefix, false otherwise.
+        * The comparison is case sensitive.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    prefix = { 'a' , 'b' }
+        *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    prefix = { 'a' , 'c' }
+        *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param prefix the given prefix
+        * @param name the given name
+        * @return true if the given name starts with the given prefix, false otherwise
+        * @throws NullPointerException if the given name is null or if the given prefix is null
+        */
+       public static final boolean prefixEquals(char[] prefix, char[] name) {
+
+               int max = prefix.length;
+               if (name.length < max)
+                       return false;
+               for (int i = max;
+                       --i >= 0;
+                       ) // assumes the prefix is not larger than the name
+                       if (prefix[i] != name[i])
+                               return false;
+               return true;
+       }
+
+       /**
+        * Answers true if the given name starts with the given prefix, false otherwise.
+        * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    prefix = { 'a' , 'B' }
+        *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    isCaseSensitive = false
+        *    result => true
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    prefix = { 'a' , 'B' }
+        *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    isCaseSensitive = true
+        *    result => false
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param prefix the given prefix
+        * @param name the given name
+        * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
+        * @return true if the given name starts with the given prefix, false otherwise
+        * @throws NullPointerException if the given name is null or if the given prefix is null
+        */
+       public static final boolean prefixEquals(
+               char[] prefix,
+               char[] name,
+               boolean isCaseSensitive) {
+
+               int max = prefix.length;
+               if (name.length < max)
+                       return false;
+               if (isCaseSensitive) {
+                       for (int i = max;
+                               --i >= 0;
+                               ) // assumes the prefix is not larger than the name
+                               if (prefix[i] != name[i])
+                                       return false;
+                       return true;
+               }
+
+               for (int i = max;
+                       --i >= 0;
+                       ) // assumes the prefix is not larger than the name
+                       if (Character.toLowerCase(prefix[i])
+                               != Character.toLowerCase(name[i]))
+                               return false;
+               return true;
+       }
+
+       /**
+        * Replace all occurrence of the character to be replaced with the remplacement character in the
+        * given array.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    toBeReplaced = 'b'
+        *    replacementChar = 'a'
+        *    result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    toBeReplaced = 'c'
+        *    replacementChar = 'a'
+        *    result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        * </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
+        */
+       public static final void replace(
+               char[] array,
+               char toBeReplaced,
+               char replacementChar) {
+               if (toBeReplaced != replacementChar) {
+                       for (int i = 0, max = array.length; i < max; i++) {
+                               if (array[i] == toBeReplaced)
+                                       array[i] = replacementChar;
+                       }
+               }
+       }
+
+       /**
+        * Answers a new array of characters with substitutions. No side-effect is operated on the original
+        * array, in case no substitution happened, then the result is the same as the
+        * original one.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    toBeReplaced = { 'b' }
+        *    replacementChar = { 'a', 'a' }
+        *    result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    toBeReplaced = { 'c' }
+        *    replacementChar = { 'a' }
+        *    result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param array the given array
+        * @param toBeReplaced characters to be replaced
+        * @param replacementChars the replacement characters
+        * @return a new array of characters with substitutions or the given array if none
+        * @throws NullPointerException if the given array is null
+        */
+       public static final char[] replace(
+               char[] array,
+               char[] toBeReplaced,
+               char[] replacementChars) {
+
+               int max = array.length;
+               int replacedLength = toBeReplaced.length;
+               int replacementLength = replacementChars.length;
+
+               int[] starts = new int[5];
+               int occurrenceCount = 0;
+
+               if (!equals(toBeReplaced, replacementChars)) {
+
+                       next : for (int i = 0; i < max; i++) {
+                               int j = 0;
+                               while (j < replacedLength) {
+                                       if (i + j == max)
+                                               continue next;
+                                       if (array[i + j] != toBeReplaced[j++])
+                                               continue next;
+                               }
+                               if (occurrenceCount == starts.length) {
+                                       System.arraycopy(
+                                               starts,
+                                               0,
+                                               starts = new int[occurrenceCount * 2],
+                                               0,
+                                               occurrenceCount);
+                               }
+                               starts[occurrenceCount++] = i;
+                       }
+               }
+               if (occurrenceCount == 0)
+                       return array;
+               char[] result =
+                       new char[max
+                               + occurrenceCount * (replacementLength - replacedLength)];
+               int inStart = 0, outStart = 0;
+               for (int i = 0; i < occurrenceCount; i++) {
+                       int offset = starts[i] - inStart;
+                       System.arraycopy(array, inStart, result, outStart, offset);
+                       inStart += offset;
+                       outStart += offset;
+                       System.arraycopy(
+                               replacementChars,
+                               0,
+                               result,
+                               outStart,
+                               replacementLength);
+                       inStart += replacedLength;
+                       outStart += replacementLength;
+               }
+               System.arraycopy(array, inStart, result, outStart, max - inStart);
+               return result;
+       }
+
+       /**
+        * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
+        * whitespaces equals to ' '.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    divider = 'b'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    divider = 'c'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    divider = 'b'
+        *    array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
+        *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    divider = 'c'
+        *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+        *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param divider the given divider
+        * @param array the given array
+        * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
+        * whitespaces equals to ' '
+        */
+       public static final char[][] splitAndTrimOn(char divider, char[] array) {
+               int length = array == null ? 0 : array.length;
+               if (length == 0)
+                       return NO_CHAR_CHAR;
+
+               int wordCount = 1;
+               for (int i = 0; i < length; i++)
+                       if (array[i] == divider)
+                               wordCount++;
+               char[][] split = new char[wordCount][];
+               int last = 0, currentWord = 0;
+               for (int i = 0; i < length; i++) {
+                       if (array[i] == divider) {
+                               int start = last, end = i - 1;
+                               while (start < i && array[start] == ' ')
+                                       start++;
+                               while (end > start && array[end] == ' ')
+                                       end--;
+                               split[currentWord] = new char[end - start + 1];
+                               System.arraycopy(
+                                       array,
+                                       start,
+                                       split[currentWord++],
+                                       0,
+                                       end - start + 1);
+                               last = i + 1;
+                       }
+               }
+               int start = last, end = length - 1;
+               while (start < length && array[start] == ' ')
+                       start++;
+               while (end > start && array[end] == ' ')
+                       end--;
+               split[currentWord] = new char[end - start + 1];
+               System.arraycopy(
+                       array,
+                       start,
+                       split[currentWord++],
+                       0,
+                       end - start + 1);
+               return split;
+       }
+
+       /**
+        * Return a new array which is the split of the given array using the given divider.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    divider = 'b'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    divider = 'c'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    divider = 'c'
+        *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
+        *    result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param divider the given divider
+        * @param array the given array
+        * @return a new array which is the split of the given array using the given divider
+        */
+       public static final char[][] splitOn(char divider, char[] array) {
+               int length = array == null ? 0 : array.length;
+               if (length == 0)
+                       return NO_CHAR_CHAR;
+
+               int wordCount = 1;
+               for (int i = 0; i < length; i++)
+                       if (array[i] == divider)
+                               wordCount++;
+               char[][] split = new char[wordCount][];
+               int last = 0, currentWord = 0;
+               for (int i = 0; i < length; i++) {
+                       if (array[i] == divider) {
+                               split[currentWord] = new char[i - last];
+                               System.arraycopy(
+                                       array,
+                                       last,
+                                       split[currentWord++],
+                                       0,
+                                       i - last);
+                               last = i + 1;
+                       }
+               }
+               split[currentWord] = new char[length - last];
+               System.arraycopy(array, last, split[currentWord], 0, length - last);
+               return split;
+       }
+
+       /**
+        * Return a new array which is the split of the given array using the given divider. The given end 
+        * is exclusive and the given start is inclusive.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    divider = 'b'
+        *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
+        *    start = 2
+        *    end = 5
+        *    result => { {  }, { 'a' }, {  } }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param divider the given divider
+        * @param array the given array
+        * @param start the given starting index
+        * @param end the given ending index
+        * @return a new array which is the split of the given array using the given divider
+        * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
+        */
+       public static final char[][] splitOn(
+               char divider,
+               char[] array,
+               int start,
+               int end) {
+               int length = array == null ? 0 : array.length;
+               if (length == 0 || start > end)
+                       return NO_CHAR_CHAR;
+
+               int wordCount = 1;
+               for (int i = start; i < end; i++)
+                       if (array[i] == divider)
+                               wordCount++;
+               char[][] split = new char[wordCount][];
+               int last = start, currentWord = 0;
+               for (int i = start; i < end; i++) {
+                       if (array[i] == divider) {
+                               split[currentWord] = new char[i - last];
+                               System.arraycopy(
+                                       array,
+                                       last,
+                                       split[currentWord++],
+                                       0,
+                                       i - last);
+                               last = i + 1;
+                       }
+               }
+               split[currentWord] = new char[end - last];
+               System.arraycopy(array, last, split[currentWord], 0, end - last);
+               return split;
+       }
+
+       /**
+        * Answers a new array which is a copy of the given array starting at the given start and 
+        * ending at the given end. The given start is inclusive and the given end is exclusive.
+        * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
+        * than the length of the given array. If end  equals -1, it is converted to the array length.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    array = { { 'a' } , { 'b' } }
+        *    start = 0
+        *    end = 1
+        *    result => { { 'a' } }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { { 'a' } , { 'b' } }
+        *    start = 0
+        *    end = -1
+        *    result => { { 'a' }, { 'b' } }
+        * </pre>
+        * </li>
+        * </ol>
+        *  
+        * @param array the given array
+        * @param start the given starting index
+        * @param end the given ending index
+        * @return a new array which is a copy of the given array starting at the given start and 
+        * ending at the given end
+        * @throws NullPointerException if the given array is null
+        */
+       public static final char[][] subarray(char[][] array, int start, int end) {
+               if (end == -1)
+                       end = array.length;
+               if (start > end)
+                       return null;
+               if (start < 0)
+                       return null;
+               if (end > array.length)
+                       return null;
+
+               char[][] result = new char[end - start][];
+               System.arraycopy(array, start, result, 0, end - start);
+               return result;
+       }
+
+       /**
+        * Answers a new array which is a copy of the given array starting at the given start and 
+        * ending at the given end. The given start is inclusive and the given end is exclusive.
+        * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
+        * than the length of the given array. If end  equals -1, it is converted to the array length.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    array = { 'a' , 'b' }
+        *    start = 0
+        *    end = 1
+        *    result => { 'a' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'a', 'b' }
+        *    start = 0
+        *    end = -1
+        *    result => { 'a' , 'b' }
+        * </pre>
+        * </li>
+        * </ol>
+        *  
+        * @param array the given array
+        * @param start the given starting index
+        * @param end the given ending index
+        * @return a new array which is a copy of the given array starting at the given start and 
+        * ending at the given end
+        * @throws NullPointerException if the given array is null
+        */
+       public static final char[] subarray(char[] array, int start, int end) {
+               if (end == -1)
+                       end = array.length;
+               if (start > end)
+                       return null;
+               if (start < 0)
+                       return null;
+               if (end > array.length)
+                       return null;
+
+               char[] result = new char[end - start];
+               System.arraycopy(array, start, result, 0, end - start);
+               return result;
+       }
+       /**
+        * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
+        * <br>
+        * NOTE: If no conversion was necessary, then answers back the argument one.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    chars = { 'a' , 'b' }
+        *    result => { 'a' , 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'A', 'b' }
+        *    result => { 'a' , 'b' }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param chars the chars to convert
+        * @return the result of a char[] conversion to lowercase
+        */
+       final static public char[] toLowerCase(char[] chars) {
+               if (chars == null)
+                       return null;
+               int length = chars.length;
+               char[] lowerChars = null;
+               for (int i = 0; i < length; i++) {
+                       char c = chars[i];
+                       char lc = Character.toLowerCase(c);
+                       if ((c != lc) || (lowerChars != null)) {
+                               if (lowerChars == null) {
+                                       System.arraycopy(
+                                               chars,
+                                               0,
+                                               lowerChars = new char[length],
+                                               0,
+                                               i);
+                               }
+                               lowerChars[i] = lc;
+                       }
+               }
+               return lowerChars == null ? chars : lowerChars;
+       }
+
+       /**
+        * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
+        * space characters to remove.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    chars = { ' ', 'a' , 'b', ' ',  ' ' }
+        *    result => { 'a' , 'b' }
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { 'A', 'b' }
+        *    result => { 'A' , 'b' }
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param chars the given array
+        * @return a new array removing leading and trailing spaces (' ')
+        */
+       final static public char[] trim(char[] chars) {
+
+               if (chars == null)
+                       return null;
+
+               int start = 0, length = chars.length, end = length - 1;
+               while (start < length && chars[start] == ' ') {
+                       start++;
+               }
+               while (end > start && chars[end] == ' ') {
+                       end--;
+               }
+               if (start != 0 || end != length - 1) {
+                       return subarray(chars, start, end + 1);
+               }
+               return chars;
+       }
+
+       /**
+        * Answers a string which is the concatenation of the given array using the '.' as a separator.
+        * <br>
+        * <br>
+        * For example:
+        * <ol>
+        * <li><pre>
+        *    array = { { 'a' } , { 'b' } }
+        *    result => "a.b"
+        * </pre>
+        * </li>
+        * <li><pre>
+        *    array = { { ' ',  'a' } , { 'b' } }
+        *    result => " a.b"
+        * </pre>
+        * </li>
+        * </ol>
+        * 
+        * @param array the given array
+        * @return a string which is the concatenation of the given array using the '.' as a separator
+        */
+       final static public String toString(char[][] array) {
+               char[] result = concatWith(array, '.');
+               return new String(result);
+       }
+       /**
+        * Answers an array of strings from the given array of char array.
+        * 
+        * @param array the given array
+        * @return an array of strings
+        * @since 3.0
+        */
+       final static public String[] toStrings(char[][] array) {
+               int length = array.length;
+               String[] result = new String[length];
+               for (int i = 0; i < length; i++)
+                       result[i] = new String(array[i]);
+               return result;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/core/compiler/IProblem.java b/src/java/org/eclipse/jdt/core/compiler/IProblem.java
new file mode 100644 (file)
index 0000000..7be59f1
--- /dev/null
@@ -0,0 +1,800 @@
+/*******************************************************************************
+ * 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 the following constants
+ *                                                                NonStaticAccessToStaticField
+ *                                                                NonStaticAccessToStaticMethod
+ *                                                                Task
+ *                                                                ExpressionShouldBeAVariable
+ *                                                                AssignmentHasNoEffect
+ *     IBM Corporation - added the following constants
+ *                                                                TooManySyntheticArgumentSlots
+ *                                                                TooManyArrayDimensions
+ *                                                                TooManyBytesForStringConstant
+ *                                                                TooManyMethods
+ *                                                                TooManyFields
+ *                                                                NonBlankFinalLocalAssignment
+ *                                                                ObjectCannotHaveSuperTypes
+ *                                                                MissingSemiColon
+ *                                                                InvalidParenthesizedExpression
+ *                                                                EnclosingInstanceInConstructorCall
+ *                                                                BytecodeExceeds64KLimitForConstructor
+ *                                                                IncompatibleReturnTypeForNonInheritedInterfaceMethod
+ *                                                                UnusedPrivateMethod
+ *                                                                UnusedPrivateConstructor
+ *                                                                UnusedPrivateType
+ *                                                                UnusedPrivateField
+ *                                                                IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod
+ *                                                                InvalidExplicitConstructorCall
+ *     IBM Corporation - added the following constants
+ *                                                                PossibleAccidentalBooleanAssignment
+ *                                                                SuperfluousSemicolon
+ *                                                                IndirectAccessToStaticField
+ *                                                                IndirectAccessToStaticMethod
+ *                                                                IndirectAccessToStaticType
+ *                                                                BooleanMethodThrowingException
+ *                                                                UnnecessaryCast
+ *                                                                UnnecessaryArgumentCast
+ *                                                                UnnecessaryInstanceof
+ *                                                                FinallyMustCompleteNormally
+ *                                                                UnusedMethodDeclaredThrownException
+ *                                                                UnusedConstructorDeclaredThrownException
+ *                                                                InvalidCatchBlockSequence
+ *                                                                UnqualifiedFieldAccess
+ *     IBM Corporation - added the following constants
+ *                                                                Javadoc
+ *                                                                JavadocUnexpectedTag
+ *                                                                JavadocMissingParamTag
+ *                                                                JavadocMissingParamName
+ *                                                                JavadocDuplicateParamName
+ *                                                                JavadocInvalidParamName
+ *                                                                JavadocMissingReturnTag
+ *                                                                JavadocDuplicateReturnTag
+ *                                                                JavadocMissingThrowsTag
+ *                                                                JavadocMissingThrowsClassName
+ *                                                                JavadocInvalidThrowsClass
+ *                                                                JavadocDuplicateThrowsClassName
+ *                                                                JavadocInvalidThrowsClassName
+ *                                                                JavadocMissingSeeReference
+ *                                                                JavadocInvalidSeeReference
+ *                                                                JavadocInvalidSeeHref
+ *                                                                JavadocInvalidSeeArgs
+ *                                                                JavadocMissing
+ *                                                                JavadocInvalidTag
+ *                                                                JavadocMessagePrefix
+ *                                                                EmptyControlFlowStatement
+ ****************************************************************************/
+package org.eclipse.jdt.core.compiler;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
+
+/**
+ * Description of a Java problem, as detected by the compiler or some of the underlying
+ * technology reusing the compiler. 
+ * A problem provides access to:
+ * <ul>
+ * <li> its location (originating source file name, source position, line number), </li>
+ * <li> its message description and a predicate to check its severity (warning or error). </li>
+ * <li> its ID : an number identifying the very nature of this problem. All possible IDs are listed
+ * as constants on this interface. </li>
+ * </ul>
+ * 
+ * Note: the compiler produces IProblems internally, which are turned into markers by the JavaBuilder
+ * so as to persist problem descriptions. This explains why there is no API allowing to reach IProblem detected
+ * when compiling. However, the Java problem markers carry equivalent information to IProblem, in particular
+ * their ID (attribute "id") is set to one of the IDs defined on this interface.
+ * 
+ * @since 2.0
+ */
+public interface IProblem { 
+       
+       /**
+        * Answer back the original arguments recorded into the problem.
+        * @return the original arguments recorded into the problem
+        */
+       String[] getArguments();
+
+       /**
+        * Returns the problem id
+        * 
+        * @return the problem id
+        */
+       int getID();
+
+       /**
+        * Answer a localized, human-readable message string which describes the problem.
+        * 
+        * @return a localized, human-readable message string which describes the problem
+        */
+       String getMessage();
+
+       /**
+        * Answer the file name in which the problem was found.
+        * 
+        * @return the file name in which the problem was found
+        */
+       char[] getOriginatingFileName();
+       
+       /**
+        * Answer the end position of the problem (inclusive), or -1 if unknown.
+        * 
+        * @return the end position of the problem (inclusive), or -1 if unknown
+        */
+       int getSourceEnd();
+
+       /**
+        * Answer the line number in source where the problem begins.
+        * 
+        * @return the line number in source where the problem begins
+        */
+       int getSourceLineNumber();
+
+       /**
+        * Answer the start position of the problem (inclusive), or -1 if unknown.
+        * 
+        * @return the start position of the problem (inclusive), or -1 if unknown
+        */
+       int getSourceStart();
+
+       /**
+        * Checks the severity to see if the Error bit is set.
+        * 
+        * @return true if the Error bit is set for the severity, false otherwise
+        */
+       boolean isError();
+
+       /**
+        * Checks the severity to see if the Error bit is not set.
+        * 
+        * @return true if the Error bit is not set for the severity, false otherwise
+        */
+       boolean isWarning();
+
+       /**
+        * Set the end position of the problem (inclusive), or -1 if unknown.
+        * Used for shifting problem positions.
+        * 
+        * @param sourceEnd the given end position
+        */
+       void setSourceEnd(int sourceEnd);
+
+       /**
+        * Set the line number in source where the problem begins.
+        * 
+        * @param lineNumber the given line number
+        */
+       void setSourceLineNumber(int lineNumber);
+
+       /**
+        * Set the start position of the problem (inclusive), or -1 if unknown.
+        * Used for shifting problem positions.
+        * 
+        * @param sourceStart the given start position
+        */
+       void setSourceStart(int sourceStart);
+       
+       /**
+        * Problem Categories
+        * The high bits of a problem ID contains information about the category of a problem. 
+        * For example, (problemID & TypeRelated) != 0, indicates that this problem is type related.
+        * 
+        * A problem category can help to implement custom problem filters. Indeed, when numerous problems
+        * are listed, focusing on import related problems first might be relevant.
+        * 
+        * When a problem is tagged as Internal, it means that no change other than a local source code change
+        * can  fix the corresponding problem.
+        */
+       int TypeRelated = 0x01000000;
+       int FieldRelated = 0x02000000;
+       int MethodRelated = 0x04000000;
+       int ConstructorRelated = 0x08000000;
+       int ImportRelated = 0x10000000;
+       int Internal = 0x20000000;
+       int Syntax = 0x40000000;
+       /**
+        * @since 3.0
+        */
+       int Javadoc = 0x80000000;
+       
+       /**
+        * Mask to use in order to filter out the category portion of the problem ID.
+        */
+       int IgnoreCategoriesMask = 0xFFFFFF;
+
+       /**
+        * Below are listed all available problem IDs. Note that this list could be augmented in the future, 
+        * as new features are added to the Java core implementation.
+        */
+
+       /**
+        * ID reserved for referencing an internal error inside the JavaCore implementation which
+        * may be surfaced as a problem associated with the compilation unit which caused it to occur.
+        */
+       int Unclassified = 0;
+
+       /**
+        * General type related problems
+        */
+       int ObjectHasNoSuperclass = TypeRelated + 1;
+       int UndefinedType = TypeRelated + 2;
+       int NotVisibleType = TypeRelated + 3;
+       int AmbiguousType = TypeRelated + 4;
+       int UsingDeprecatedType = TypeRelated + 5;
+       int InternalTypeNameProvided = TypeRelated + 6;
+       /** @since 2.1 */
+       int UnusedPrivateType = Internal + TypeRelated + 7;
+       
+       int IncompatibleTypesInEqualityOperator = TypeRelated + 15;
+       int IncompatibleTypesInConditionalOperator = TypeRelated + 16;
+       int TypeMismatch = TypeRelated + 17;
+       /** @since 3.0 */
+       int IndirectAccessToStaticType = Internal + TypeRelated + 18;
+       
+       /**
+        * Inner types related problems
+        */
+       int MissingEnclosingInstanceForConstructorCall = TypeRelated + 20;
+       int MissingEnclosingInstance = TypeRelated + 21;
+       int IncorrectEnclosingInstanceReference = TypeRelated + 22;
+       int IllegalEnclosingInstanceSpecification = TypeRelated + 23; 
+       int CannotDefineStaticInitializerInLocalType = Internal + 24;
+       int OuterLocalMustBeFinal = Internal + 25;
+       int CannotDefineInterfaceInLocalType = Internal + 26;
+       int IllegalPrimitiveOrArrayTypeForEnclosingInstance = TypeRelated + 27;
+       /** @since 2.1 */
+       int EnclosingInstanceInConstructorCall = Internal + 28;
+       int AnonymousClassCannotExtendFinalClass = TypeRelated + 29;
+
+       // variables
+       int UndefinedName = 50;
+       int UninitializedLocalVariable = Internal + 51;
+       int VariableTypeCannotBeVoid = Internal + 52;
+       int VariableTypeCannotBeVoidArray = Internal + 53;
+       int CannotAllocateVoidArray = Internal + 54;
+       // local variables
+       int RedefinedLocal = Internal + 55;
+       int RedefinedArgument = Internal + 56;
+       // final local variables
+       int DuplicateFinalLocalInitialization = Internal + 57;
+       /** @since 2.1 */
+       int NonBlankFinalLocalAssignment = Internal + 58;
+       
+       int FinalOuterLocalAssignment = Internal + 60;
+       int LocalVariableIsNeverUsed = Internal + 61;
+       int ArgumentIsNeverUsed = Internal + 62;
+       int BytecodeExceeds64KLimit = Internal + 63;
+       int BytecodeExceeds64KLimitForClinit = Internal + 64;
+       int TooManyArgumentSlots = Internal + 65;
+       int TooManyLocalVariableSlots = Internal + 66;
+       /** @since 2.1 */
+       int TooManySyntheticArgumentSlots = Internal + 67;
+       /** @since 2.1 */
+       int TooManyArrayDimensions = Internal + 68;
+       /** @since 2.1 */
+       int BytecodeExceeds64KLimitForConstructor = Internal + 69;
+
+       // fields
+       int UndefinedField = FieldRelated + 70;
+       int NotVisibleField = FieldRelated + 71;
+       int AmbiguousField = FieldRelated + 72;
+       int UsingDeprecatedField = FieldRelated + 73;
+       int NonStaticFieldFromStaticInvocation = FieldRelated + 74;
+       int ReferenceToForwardField = FieldRelated + Internal + 75;
+       /** @since 2.1 */
+       int NonStaticAccessToStaticField = Internal + FieldRelated + 76;
+       /** @since 2.1 */
+       int UnusedPrivateField = Internal + FieldRelated + 77;
+       /** @since 3.0 */
+       int IndirectAccessToStaticField = Internal + FieldRelated + 78;
+       /** @since 3.0 */
+       int UnqualifiedFieldAccess = Internal + FieldRelated + 79;
+       
+       // blank final fields
+       int FinalFieldAssignment = FieldRelated + 80;
+       int UninitializedBlankFinalField = FieldRelated + 81;
+       int DuplicateBlankFinalFieldInitialization = FieldRelated + 82;
+
+       // variable hiding
+       /**
+        * The local variable {0} is hiding another local variable defined in an enclosing type scope 
+        * @since 3.0
+        */
+       int LocalVariableHidingLocalVariable = Internal + 90;           
+
+       /**
+        * The local variable {0} is hiding the field {1}.{2} 
+        * @since 3.0
+        */
+       int LocalVariableHidingField = Internal + FieldRelated + 91;            
+        
+       /**
+        * The field {0}.{1} is hiding another local variable defined in an enclosing type scope
+        * @since 3.0 
+        */
+       int FieldHidingLocalVariable = Internal + FieldRelated + 92;            
+
+       /**
+        * The field {0}.{1} is hiding the field {2}.{3}
+        * @since 3.0 
+        */
+       int FieldHidingField = Internal + FieldRelated + 93;            
+
+       /**
+        * The argument {0} is hiding another local variable defined in an enclosing type scope
+        * @since 3.0 
+        */
+       int ArgumentHidingLocalVariable = Internal + 94;                
+
+       /**
+        * The argument {0} is hiding the field {2}.{3}
+        * @since 3.0 
+        */
+       int ArgumentHidingField = Internal + 95;                
+
+       // methods
+       int UndefinedMethod = MethodRelated + 100;
+       int NotVisibleMethod = MethodRelated + 101;
+       int AmbiguousMethod = MethodRelated + 102;
+       int UsingDeprecatedMethod = MethodRelated + 103;
+       int DirectInvocationOfAbstractMethod = MethodRelated + 104;
+       int VoidMethodReturnsValue = MethodRelated + 105;
+       int MethodReturnsVoid = MethodRelated + 106;
+       int MethodRequiresBody = Internal + MethodRelated + 107;
+       int ShouldReturnValue = Internal + MethodRelated + 108;
+       int MethodButWithConstructorName = MethodRelated + 110;
+       int MissingReturnType = TypeRelated + 111;
+       int BodyForNativeMethod = Internal + MethodRelated + 112;
+       int BodyForAbstractMethod = Internal + MethodRelated + 113;
+       int NoMessageSendOnBaseType = MethodRelated + 114;
+       int ParameterMismatch = MethodRelated + 115;
+       int NoMessageSendOnArrayType = MethodRelated + 116;
+       /** @since 2.1 */
+    int NonStaticAccessToStaticMethod = Internal + MethodRelated + 117;
+       /** @since 2.1 */
+       int UnusedPrivateMethod = Internal + MethodRelated + 118;
+       /** @since 3.0 */
+       int IndirectAccessToStaticMethod = Internal + MethodRelated + 119;
+
+           
+       // constructors
+       int UndefinedConstructor = ConstructorRelated + 130;
+       int NotVisibleConstructor = ConstructorRelated + 131;
+       int AmbiguousConstructor = ConstructorRelated + 132;
+       int UsingDeprecatedConstructor = ConstructorRelated + 133;
+       /** @since 2.1 */
+       int UnusedPrivateConstructor = Internal + MethodRelated + 134;
+       // explicit constructor calls
+       int InstanceFieldDuringConstructorInvocation = ConstructorRelated + 135;
+       int InstanceMethodDuringConstructorInvocation = ConstructorRelated + 136;
+       int RecursiveConstructorInvocation = ConstructorRelated + 137;
+       int ThisSuperDuringConstructorInvocation = ConstructorRelated + 138;
+       /** @since 3.0 */
+       int InvalidExplicitConstructorCall = ConstructorRelated + Syntax + 139;
+       // implicit constructor calls
+       int UndefinedConstructorInDefaultConstructor = ConstructorRelated + 140;
+       int NotVisibleConstructorInDefaultConstructor = ConstructorRelated + 141;
+       int AmbiguousConstructorInDefaultConstructor = ConstructorRelated + 142;
+       int UndefinedConstructorInImplicitConstructorCall = ConstructorRelated + 143;
+       int NotVisibleConstructorInImplicitConstructorCall = ConstructorRelated + 144;
+       int AmbiguousConstructorInImplicitConstructorCall = ConstructorRelated + 145;
+       int UnhandledExceptionInDefaultConstructor = TypeRelated + 146;
+       int UnhandledExceptionInImplicitConstructorCall = TypeRelated + 147;
+                               
+       // expressions
+       int ArrayReferenceRequired = Internal + 150;
+       int NoImplicitStringConversionForCharArrayExpression = Internal + 151;
+       // constant expressions
+       int StringConstantIsExceedingUtf8Limit = Internal + 152;
+       int NonConstantExpression = 153;
+       int NumericValueOutOfRange = Internal + 154;
+       // cast expressions
+       int IllegalCast = TypeRelated + 156;
+       // allocations
+       int InvalidClassInstantiation = TypeRelated + 157;
+       int CannotDefineDimensionExpressionsWithInit = Internal + 158;
+       int MustDefineEitherDimensionExpressionsOrInitializer = Internal + 159;
+       // operators
+       int InvalidOperator = Internal + 160;
+       // statements
+       int CodeCannotBeReached = Internal + 161;
+       int CannotReturnInInitializer = Internal + 162;
+       int InitializerMustCompleteNormally = Internal + 163;
+       // assert
+       int InvalidVoidExpression = Internal + 164;
+       // try
+       int MaskedCatch = TypeRelated + 165;
+       int DuplicateDefaultCase = 166;
+       int UnreachableCatch = TypeRelated + MethodRelated + 167;
+       int UnhandledException = TypeRelated + 168;
+       // switch       
+       int IncorrectSwitchType = TypeRelated + 169;
+       int DuplicateCase = FieldRelated + 170;
+       // labelled
+       int DuplicateLabel = Internal + 171;
+       int InvalidBreak = Internal + 172;
+       int InvalidContinue = Internal + 173;
+       int UndefinedLabel = Internal + 174;
+       //synchronized
+       int InvalidTypeToSynchronized = Internal + 175;
+       int InvalidNullToSynchronized = Internal + 176;
+       // throw
+       int CannotThrowNull = Internal + 177;
+       // assignment
+       /** @since 2.1 */
+       int AssignmentHasNoEffect = Internal + 178;
+       /** @since 3.0 */
+       int PossibleAccidentalBooleanAssignment = Internal + 179;
+       /** @since 3.0 */
+       int SuperfluousSemicolon = Internal + 180;
+       /** @since 3.0 */
+       int UnnecessaryCast = Internal + TypeRelated + 181;
+       /** @since 3.0 */
+       int UnnecessaryArgumentCast = Internal + TypeRelated + 182;
+       /** @since 3.0 */
+       int UnnecessaryInstanceof = Internal + TypeRelated + 183;       
+       /** @since 3.0 */
+       int FinallyMustCompleteNormally = Internal + 184;       
+       /** @since 3.0 */
+       int UnusedMethodDeclaredThrownException = Internal + 185;       
+       /** @since 3.0 */
+       int UnusedConstructorDeclaredThrownException = Internal + 186;  
+       /** @since 3.0 */
+       int InvalidCatchBlockSequence = Internal + TypeRelated + 187;   
+       /** @since 3.0 */
+       int EmptyControlFlowStatement = Internal + TypeRelated + 188;   
+       /** @since 3.0 */
+       int UnnecessaryElse = Internal + 189;   
+
+       // inner emulation
+       int NeedToEmulateFieldReadAccess = FieldRelated + 190;
+       int NeedToEmulateFieldWriteAccess = FieldRelated + 191;
+       int NeedToEmulateMethodAccess = MethodRelated + 192;
+       int NeedToEmulateConstructorAccess = MethodRelated + 193;
+
+       //inherited name hides enclosing name (sort of ambiguous)
+       int InheritedMethodHidesEnclosingName = MethodRelated + 195;
+       int InheritedFieldHidesEnclosingName = FieldRelated + 196;
+       int InheritedTypeHidesEnclosingName = TypeRelated + 197;
+
+       // miscellaneous
+       int ThisInStaticContext = Internal + 200;
+       int StaticMethodRequested = Internal + MethodRelated + 201;
+       int IllegalDimension = Internal + 202;
+       int InvalidTypeExpression = Internal + 203;
+       int ParsingError = Syntax + Internal + 204;
+       int ParsingErrorNoSuggestion = Syntax + Internal + 205;
+       int InvalidUnaryExpression = Syntax + Internal + 206;
+
+       // syntax errors
+       int InterfaceCannotHaveConstructors = Syntax + Internal + 207;
+       int ArrayConstantsOnlyInArrayInitializers = Syntax + Internal + 208;
+       int ParsingErrorOnKeyword = Syntax + Internal + 209;    
+       int ParsingErrorOnKeywordNoSuggestion = Syntax + Internal + 210;
+
+       int UnmatchedBracket = Syntax + Internal + 220;
+       int NoFieldOnBaseType = FieldRelated + 221;
+       int InvalidExpressionAsStatement = Syntax + Internal + 222;
+       /** @since 2.1 */
+       int ExpressionShouldBeAVariable = Syntax + Internal + 223;
+       /** @since 2.1 */
+       int MissingSemiColon = Syntax + Internal + 224;
+       /** @since 2.1 */
+       int InvalidParenthesizedExpression = Syntax + Internal + 225;
+       
+       /** @since 3.0 */
+       int ParsingErrorInsertTokenBefore = Syntax + Internal + 230;
+       /** @since 3.0 */
+       int ParsingErrorInsertTokenAfter = Syntax + Internal + 231;
+       /** @since 3.0 */
+    int ParsingErrorDeleteToken = Syntax + Internal + 232;
+    /** @since 3.0 */
+    int ParsingErrorDeleteTokens = Syntax + Internal + 233;
+    /** @since 3.0 */
+    int ParsingErrorMergeTokens = Syntax + Internal + 234;
+    /** @since 3.0 */
+    int ParsingErrorInvalidToken = Syntax + Internal + 235;
+    /** @since 3.0 */
+    int ParsingErrorMisplacedConstruct = Syntax + Internal + 236;
+    /** @since 3.0 */
+    int ParsingErrorReplaceTokens = Syntax + Internal + 237;
+    /** @since 3.0 */
+    int ParsingErrorNoSuggestionForTokens = Syntax + Internal + 238;
+    /** @since 3.0 */
+    int ParsingErrorUnexpectedEOF = Syntax + Internal + 239;
+    /** @since 3.0 */
+    int ParsingErrorInsertToComplete = Syntax + Internal + 240;
+    /** @since 3.0 */
+    int ParsingErrorInsertToCompleteScope = Syntax + Internal + 241;
+    /** @since 3.0 */
+    int ParsingErrorInsertToCompletePhrase = Syntax + Internal + 242;
+    
+       // scanner errors
+       int EndOfSource = Syntax + Internal + 250;
+       int InvalidHexa = Syntax + Internal + 251;
+       int InvalidOctal = Syntax + Internal + 252;
+       int InvalidCharacterConstant = Syntax + Internal + 253;
+       int InvalidEscape = Syntax + Internal + 254;
+       int InvalidInput = Syntax + Internal + 255;
+       int InvalidUnicodeEscape = Syntax + Internal + 256;
+       int InvalidFloat = Syntax + Internal + 257;
+       int NullSourceString = Syntax + Internal + 258;
+       int UnterminatedString = Syntax + Internal + 259;
+       int UnterminatedComment = Syntax + Internal + 260;
+
+       // type related problems
+       int InterfaceCannotHaveInitializers = TypeRelated + 300;
+       int DuplicateModifierForType = TypeRelated + 301;
+       int IllegalModifierForClass = TypeRelated + 302;
+       int IllegalModifierForInterface = TypeRelated + 303;
+       int IllegalModifierForMemberClass = TypeRelated + 304;
+       int IllegalModifierForMemberInterface = TypeRelated + 305;
+       int IllegalModifierForLocalClass = TypeRelated + 306;
+
+       int IllegalModifierCombinationFinalAbstractForClass = TypeRelated + 308;
+       int IllegalVisibilityModifierForInterfaceMemberType = TypeRelated + 309;
+       int IllegalVisibilityModifierCombinationForMemberType = TypeRelated + 310;
+       int IllegalStaticModifierForMemberType = TypeRelated + 311;
+       int SuperclassMustBeAClass = TypeRelated + 312;
+       int ClassExtendFinalClass = TypeRelated + 313;
+       int DuplicateSuperInterface = TypeRelated + 314;
+       int SuperInterfaceMustBeAnInterface = TypeRelated + 315;
+       int HierarchyCircularitySelfReference = TypeRelated + 316;
+       int HierarchyCircularity = TypeRelated + 317;
+       int HidingEnclosingType = TypeRelated + 318;
+       int DuplicateNestedType = TypeRelated + 319;
+       int CannotThrowType = TypeRelated + 320;
+       int PackageCollidesWithType = TypeRelated + 321;
+       int TypeCollidesWithPackage = TypeRelated + 322;
+       int DuplicateTypes = TypeRelated + 323;
+       int IsClassPathCorrect = TypeRelated + 324;
+       int PublicClassMustMatchFileName = TypeRelated + 325;
+       int MustSpecifyPackage = 326;
+       int HierarchyHasProblems = TypeRelated + 327;
+       int PackageIsNotExpectedPackage = 328;
+       /** @since 2.1 */
+       int ObjectCannotHaveSuperTypes = 329;
+
+       // int InvalidSuperclassBase = TypeRelated + 329; // reserved to 334 included
+       int SuperclassNotFound =  TypeRelated + 329 + ProblemReasons.NotFound; // TypeRelated + 330
+       int SuperclassNotVisible =  TypeRelated + 329 + ProblemReasons.NotVisible; // TypeRelated + 331
+       int SuperclassAmbiguous =  TypeRelated + 329 + ProblemReasons.Ambiguous; // TypeRelated + 332
+       int SuperclassInternalNameProvided =  TypeRelated + 329 + ProblemReasons.InternalNameProvided; // TypeRelated + 333
+       int SuperclassInheritedNameHidesEnclosingName =  TypeRelated + 329 + ProblemReasons.InheritedNameHidesEnclosingName; // TypeRelated + 334
+
+       // int InvalidInterfaceBase = TypeRelated + 334; // reserved to 339 included
+       int InterfaceNotFound =  TypeRelated + 334 + ProblemReasons.NotFound; // TypeRelated + 335
+       int InterfaceNotVisible =  TypeRelated + 334 + ProblemReasons.NotVisible; // TypeRelated + 336
+       int InterfaceAmbiguous =  TypeRelated + 334 + ProblemReasons.Ambiguous; // TypeRelated + 337
+       int InterfaceInternalNameProvided =  TypeRelated + 334 + ProblemReasons.InternalNameProvided; // TypeRelated + 338
+       int InterfaceInheritedNameHidesEnclosingName =  TypeRelated + 334 + ProblemReasons.InheritedNameHidesEnclosingName; // TypeRelated + 339
+
+       // field related problems
+       int DuplicateField = FieldRelated + 340;
+       int DuplicateModifierForField = FieldRelated + 341;
+       int IllegalModifierForField = FieldRelated + 342;
+       int IllegalModifierForInterfaceField = FieldRelated + 343;
+       int IllegalVisibilityModifierCombinationForField = FieldRelated + 344;
+       int IllegalModifierCombinationFinalVolatileForField = FieldRelated + 345;
+       int UnexpectedStaticModifierForField = FieldRelated + 346;
+
+       // int FieldTypeProblemBase = FieldRelated + 349; //reserved to 354
+       int FieldTypeNotFound =  FieldRelated + 349 + ProblemReasons.NotFound; // FieldRelated + 350
+       int FieldTypeNotVisible =  FieldRelated + 349 + ProblemReasons.NotVisible; // FieldRelated + 351
+       int FieldTypeAmbiguous =  FieldRelated + 349 + ProblemReasons.Ambiguous; // FieldRelated + 352
+       int FieldTypeInternalNameProvided =  FieldRelated + 349 + ProblemReasons.InternalNameProvided; // FieldRelated + 353
+       int FieldTypeInheritedNameHidesEnclosingName =  FieldRelated + 349 + ProblemReasons.InheritedNameHidesEnclosingName; // FieldRelated + 354
+       
+       // method related problems
+       int DuplicateMethod = MethodRelated + 355;
+       int IllegalModifierForArgument = MethodRelated + 356;
+       int DuplicateModifierForMethod = MethodRelated + 357;
+       int IllegalModifierForMethod = MethodRelated + 358;
+       int IllegalModifierForInterfaceMethod = MethodRelated + 359;
+       int IllegalVisibilityModifierCombinationForMethod = MethodRelated + 360;
+       int UnexpectedStaticModifierForMethod = MethodRelated + 361;
+       int IllegalAbstractModifierCombinationForMethod = MethodRelated + 362;
+       int AbstractMethodInAbstractClass = MethodRelated + 363;
+       int ArgumentTypeCannotBeVoid = MethodRelated + 364;
+       int ArgumentTypeCannotBeVoidArray = MethodRelated + 365;
+       int ReturnTypeCannotBeVoidArray = MethodRelated + 366;
+       int NativeMethodsCannotBeStrictfp = MethodRelated + 367;
+       int DuplicateModifierForArgument = MethodRelated + 368;
+
+       //      int ArgumentProblemBase = MethodRelated + 369; // reserved to 374 included.
+       int ArgumentTypeNotFound =  MethodRelated + 369 + ProblemReasons.NotFound; // MethodRelated + 370
+       int ArgumentTypeNotVisible =  MethodRelated + 369 + ProblemReasons.NotVisible; // MethodRelated + 371
+       int ArgumentTypeAmbiguous =  MethodRelated + 369 + ProblemReasons.Ambiguous; // MethodRelated + 372
+       int ArgumentTypeInternalNameProvided =  MethodRelated + 369 + ProblemReasons.InternalNameProvided; // MethodRelated + 373
+       int ArgumentTypeInheritedNameHidesEnclosingName =  MethodRelated + 369 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 374
+
+       //      int ExceptionTypeProblemBase = MethodRelated + 374; // reserved to 379 included.
+       int ExceptionTypeNotFound =  MethodRelated + 374 + ProblemReasons.NotFound; // MethodRelated + 375
+       int ExceptionTypeNotVisible =  MethodRelated + 374 + ProblemReasons.NotVisible; // MethodRelated + 376
+       int ExceptionTypeAmbiguous =  MethodRelated + 374 + ProblemReasons.Ambiguous; // MethodRelated + 377
+       int ExceptionTypeInternalNameProvided =  MethodRelated + 374 + ProblemReasons.InternalNameProvided; // MethodRelated + 378
+       int ExceptionTypeInheritedNameHidesEnclosingName =  MethodRelated + 374 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 379
+
+       //      int ReturnTypeProblemBase = MethodRelated + 379;
+       int ReturnTypeNotFound =  MethodRelated + 379 + ProblemReasons.NotFound; // MethodRelated + 380
+       int ReturnTypeNotVisible =  MethodRelated + 379 + ProblemReasons.NotVisible; // MethodRelated + 381
+       int ReturnTypeAmbiguous =  MethodRelated + 379 + ProblemReasons.Ambiguous; // MethodRelated + 382
+       int ReturnTypeInternalNameProvided =  MethodRelated + 379 + ProblemReasons.InternalNameProvided; // MethodRelated + 383
+       int ReturnTypeInheritedNameHidesEnclosingName =  MethodRelated + 379 + ProblemReasons.InheritedNameHidesEnclosingName; // MethodRelated + 384
+
+       // import related problems
+       int ConflictingImport = ImportRelated + 385;
+       int DuplicateImport = ImportRelated + 386;
+       int CannotImportPackage = ImportRelated + 387;
+       int UnusedImport = ImportRelated + 388;
+
+       //      int ImportProblemBase = ImportRelated + 389;
+       int ImportNotFound =  ImportRelated + 389 + ProblemReasons.NotFound; // ImportRelated + 390
+       int ImportNotVisible =  ImportRelated + 389 + ProblemReasons.NotVisible; // ImportRelated + 391
+       int ImportAmbiguous =  ImportRelated + 389 + ProblemReasons.Ambiguous; // ImportRelated + 392
+       int ImportInternalNameProvided =  ImportRelated + 389 + ProblemReasons.InternalNameProvided; // ImportRelated + 393
+       int ImportInheritedNameHidesEnclosingName =  ImportRelated + 389 + ProblemReasons.InheritedNameHidesEnclosingName; // ImportRelated + 394
+
+       // local variable related problems
+       int DuplicateModifierForVariable = MethodRelated + 395;
+       int IllegalModifierForVariable = MethodRelated + 396;
+
+       // method verifier problems
+       int AbstractMethodMustBeImplemented = MethodRelated + 400;
+       int FinalMethodCannotBeOverridden = MethodRelated + 401;
+       int IncompatibleExceptionInThrowsClause = MethodRelated + 402;
+       int IncompatibleExceptionInInheritedMethodThrowsClause = MethodRelated + 403;
+       int IncompatibleReturnType = MethodRelated + 404;
+       int InheritedMethodReducesVisibility = MethodRelated + 405;
+       int CannotOverrideAStaticMethodWithAnInstanceMethod = MethodRelated + 406;
+       int CannotHideAnInstanceMethodWithAStaticMethod = MethodRelated + 407;
+       int StaticInheritedMethodConflicts = MethodRelated + 408;
+       int MethodReducesVisibility = MethodRelated + 409;
+       int OverridingNonVisibleMethod = MethodRelated + 410;
+       int AbstractMethodCannotBeOverridden = MethodRelated + 411;
+       int OverridingDeprecatedMethod = MethodRelated + 412;
+       /** @since 2.1 */
+       int IncompatibleReturnTypeForNonInheritedInterfaceMethod = MethodRelated + 413;
+       /** @since 2.1 */
+       int IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod = MethodRelated + 414;
+       
+       // code snippet support
+       int CodeSnippetMissingClass = Internal + 420;
+       int CodeSnippetMissingMethod = Internal + 421;
+       int NonExternalizedStringLiteral = Internal + 261;
+       int CannotUseSuperInCodeSnippet = Internal + 422;
+       
+       //constant pool
+       int TooManyConstantsInConstantPool = Internal + 430;
+       /** @since 2.1 */
+       int TooManyBytesForStringConstant = Internal + 431;
+
+       // static constraints
+       /** @since 2.1 */
+       int TooManyFields = Internal + 432;
+       /** @since 2.1 */
+       int TooManyMethods = Internal + 433; 
+               
+       // 1.4 features
+       // assertion warning
+       int UseAssertAsAnIdentifier = Internal + 440;
+       
+       // detected task
+       /** @since 2.1 */
+       int Task = Internal + 450;
+       
+       // block
+       /** @since 3.0 */
+       int UndocumentedEmptyBlock = Internal + 460;
+               
+       /*
+        * Javadoc comments
+        */
+       /** @since 3.0 */
+       int JavadocUnexpectedTag = Javadoc + Internal + 470;
+       /** @since 3.0 */
+       int JavadocMissingParamTag = Javadoc + Internal + 471;
+       /** @since 3.0 */
+       int JavadocMissingParamName = Javadoc + Internal + 472;
+       /** @since 3.0 */
+       int JavadocDuplicateParamName = Javadoc + Internal + 473;
+       /** @since 3.0 */
+       int JavadocInvalidParamName = Javadoc + Internal + 474;
+       /** @since 3.0 */
+       int JavadocMissingReturnTag = Javadoc + Internal + 475;
+       /** @since 3.0 */
+       int JavadocDuplicateReturnTag = Javadoc + Internal + 476;
+       /** @since 3.0 */
+       int JavadocMissingThrowsTag = Javadoc + Internal + 477;
+       /** @since 3.0 */
+       int JavadocMissingThrowsClassName = Javadoc + Internal + 478;
+       /** @since 3.0 */
+       int JavadocInvalidThrowsClass = Javadoc + Internal + 479;
+       /** @since 3.0 */
+       int JavadocDuplicateThrowsClassName = Javadoc + Internal + 480;
+       /** @since 3.0 */
+       int JavadocInvalidThrowsClassName = Javadoc + Internal + 481;
+       /** @since 3.0 */
+       int JavadocMissingSeeReference = Javadoc + Internal + 482;
+       /** @since 3.0 */
+       int JavadocInvalidSeeReference = Javadoc + Internal + 483;
+       /** @since 3.0 */
+       int JavadocInvalidSeeHref = Javadoc + Internal + 484;
+       /** @since 3.0 */
+       int JavadocInvalidSeeArgs = Javadoc + Internal + 485;
+       /** @since 3.0 */
+       int JavadocMissing = Javadoc + Internal + 486;
+       /** @since 3.0 */
+       int JavadocInvalidTag = Javadoc + Internal + 487;
+       /*
+        * ID for field errors in Javadoc
+        */
+       /** @since 3.0 */
+       int JavadocUndefinedField = Javadoc + Internal + 488;
+       /** @since 3.0 */
+       int JavadocNotVisibleField = Javadoc + Internal + 489;
+       /** @since 3.0 */
+       int JavadocAmbiguousField = Javadoc + Internal + 490;
+       /** @since 3.0 */
+       int JavadocUsingDeprecatedField = Javadoc + Internal + 491;
+       /*
+        * IDs for constructor errors in Javadoc
+        */
+       /** @since 3.0 */
+       int JavadocUndefinedConstructor = Javadoc + Internal + 492;
+       /** @since 3.0 */
+       int JavadocNotVisibleConstructor = Javadoc + Internal + 493;
+       /** @since 3.0 */
+       int JavadocAmbiguousConstructor = Javadoc + Internal + 494;
+       /** @since 3.0 */
+       int JavadocUsingDeprecatedConstructor = Javadoc + Internal + 495;
+       /*
+        * IDs for method errors in Javadoc
+        */
+       /** @since 3.0 */
+       int JavadocUndefinedMethod = Javadoc + Internal + 496;
+       /** @since 3.0 */
+       int JavadocNotVisibleMethod = Javadoc + Internal + 497;
+       /** @since 3.0 */
+       int JavadocAmbiguousMethod = Javadoc + Internal + 498;
+       /** @since 3.0 */
+       int JavadocUsingDeprecatedMethod = Javadoc + Internal + 499;
+       /** @since 3.0 */
+       int JavadocNoMessageSendOnBaseType = Javadoc + Internal + 500;
+       /** @since 3.0 */
+       int JavadocParameterMismatch = Javadoc + Internal + 501;
+       /** @since 3.0 */
+       int JavadocNoMessageSendOnArrayType = Javadoc + Internal + 502;
+       /*
+        * IDs for type errors in Javadoc
+        */
+       /** @since 3.0 */
+       int JavadocUndefinedType = Javadoc + Internal + 503;
+       /** @since 3.0 */
+       int JavadocNotVisibleType = Javadoc + Internal + 504;
+       /** @since 3.0 */
+       int JavadocAmbiguousType = Javadoc + Internal + 505;
+       /** @since 3.0 */
+       int JavadocUsingDeprecatedType = Javadoc + Internal + 506;
+       /** @since 3.0 */
+       int JavadocInternalTypeNameProvided = Javadoc + Internal + 507;
+       /** @since 3.0 */
+       int JavadocInheritedMethodHidesEnclosingName = Javadoc + Internal + 508;
+       /** @since 3.0 */
+       int JavadocInheritedFieldHidesEnclosingName = Javadoc + Internal + 509;
+       /** @since 3.0 */
+       int JavadocInheritedNameHidesEnclosingTypeName = Javadoc + Internal + 510;
+       /** @since 3.0 */
+       int JavadocAmbiguousMethodReference = Javadoc + Internal + 511;
+       /** @since 3.0 */
+       int JavadocUnterminatedInlineTag = Javadoc + Internal + 512;
+       /** @since 3.0 */
+       int JavadocMalformedSeeReference = Javadoc + Internal + 513;
+       /** @since 3.0 */
+       int JavadocMessagePrefix = Internal + 515;
+}
diff --git a/src/java/org/eclipse/jdt/core/compiler/InvalidInputException.java b/src/java/org/eclipse/jdt/core/compiler/InvalidInputException.java
new file mode 100644 (file)
index 0000000..7055b43
--- /dev/null
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.core.compiler;
+
+/**
+ * Exception thrown by a scanner when encountering lexical errors.
+ */
+public class InvalidInputException extends Exception {
+
+       private static final long serialVersionUID = 2909732853499731592L; // backward compatible
+
+       /**
+        * Creates a new exception with no detail message.
+        */
+       public InvalidInputException() {
+               super();
+       }
+       /**
+        * Creates a new exception with the given detail message.
+        * @param message the detail message
+        */
+       public InvalidInputException(String message) {
+               super(message);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ASTVisitor.java b/src/java/org/eclipse/jdt/internal/compiler/ASTVisitor.java
new file mode 100644 (file)
index 0000000..9e1166d
--- /dev/null
@@ -0,0 +1,618 @@
+/*******************************************************************************
+ * 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;
+
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.*; 
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/** 
+ * A visitor for iterating through the parse tree.
+ */
+public abstract class ASTVisitor {
+
+       public void acceptProblem(IProblem problem) {
+               // do nothing by default
+       }
+       public void endVisit(
+               AllocationExpression allocationExpression,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocArgumentExpression expression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocFieldReference fieldRef, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocMessageSend messageSend, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocReturnStatement statement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocSingleNameReference argument, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(Argument argument, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               ArrayAllocationExpression arrayAllocationExpression,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ArrayInitializer arrayInitializer, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+               ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ArrayReference arrayReference, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(Assignment assignment, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(AssertStatement assertStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(Block block, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(BreakStatement breakStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(CaseStatement caseStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(CastExpression castExpression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(CharLiteral charLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ClassLiteralAccess classLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(Clinit clinit, ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               CompilationUnitDeclaration compilationUnitDeclaration,
+               CompilationUnitScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(CompoundAssignment compoundAssignment, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               ConditionalExpression conditionalExpression,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               ConstructorDeclaration constructorDeclaration,
+               ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ContinueStatement continueStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(DoStatement doStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(EqualExpression equalExpression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               ExplicitConstructorCall explicitConstructor,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               ExtendedStringLiteral extendedStringLiteral,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(FalseLiteral falseLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(FieldReference fieldReference, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(FloatLiteral floatLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ForStatement forStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(IfStatement ifStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(Initializer initializer, MethodScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               InstanceOfExpression instanceOfExpression,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(IntLiteral intLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(LocalDeclaration localDeclaration, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(LongLiteral longLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(MessageSend messageSend, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(StringLiteralConcatenation literal, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(PrefixExpression prefixExpression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               QualifiedAllocationExpression qualifiedAllocationExpression,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               QualifiedNameReference qualifiedNameReference,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               QualifiedSuperReference qualifiedSuperReference,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               QualifiedThisReference qualifiedThisReference,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               QualifiedTypeReference qualifiedTypeReference,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               QualifiedTypeReference qualifiedTypeReference,
+               ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               SingleNameReference singleNameReference,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               SingleTypeReference singleTypeReference,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               SingleTypeReference singleTypeReference,
+               ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(StringLiteral stringLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(SuperReference superReference, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(SwitchStatement switchStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               SynchronizedStatement synchronizedStatement,
+               BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ThisReference thisReference, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(ThrowStatement throwStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(TrueLiteral trueLiteral, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(TryStatement tryStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               TypeDeclaration localTypeDeclaration,
+               BlockScope scope) {
+               // do nothing by default
+       }       
+       public void endVisit(
+               TypeDeclaration memberTypeDeclaration,
+               ClassScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(
+               TypeDeclaration typeDeclaration,
+               CompilationUnitScope scope) {
+               // do nothing by default
+       }       
+       public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
+               // do nothing by default
+       }
+       public void endVisit(WhileStatement whileStatement, BlockScope scope) {
+               // do nothing by default
+       }
+       public boolean visit(
+               AllocationExpression allocationExpression,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+               // do nothing by default
+       }
+       public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocArrayQualifiedTypeReference typeRef, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocArraySingleTypeReference typeRef, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocArgumentExpression expression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocFieldReference fieldRef, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocMessageSend messageSend, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocQualifiedTypeReference typeRef, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocReturnStatement statement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocSingleNameReference argument, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(JavadocSingleTypeReference typeRef, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(Argument argument, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               ArrayAllocationExpression arrayAllocationExpression,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+               ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ArrayReference arrayReference, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(Assignment assignment, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(AssertStatement assertStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(Block block, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(BreakStatement breakStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(CaseStatement caseStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(CastExpression castExpression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(CharLiteral charLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(Clinit clinit, ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               CompilationUnitDeclaration compilationUnitDeclaration,
+               CompilationUnitScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               ConditionalExpression conditionalExpression,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               ConstructorDeclaration constructorDeclaration,
+               ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ContinueStatement continueStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(DoStatement doStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               ExplicitConstructorCall explicitConstructor,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               ExtendedStringLiteral extendedStringLiteral,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(FieldReference fieldReference, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ForStatement forStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(IfStatement ifStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(Initializer initializer, MethodScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               InstanceOfExpression instanceOfExpression,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(IntLiteral intLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(LongLiteral longLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(MessageSend messageSend, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+                       StringLiteralConcatenation literal,
+                       BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               QualifiedAllocationExpression qualifiedAllocationExpression,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               QualifiedNameReference qualifiedNameReference,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               QualifiedSuperReference qualifiedSuperReference,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               QualifiedThisReference qualifiedThisReference,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               QualifiedTypeReference qualifiedTypeReference,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               QualifiedTypeReference qualifiedTypeReference,
+               ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               SingleNameReference singleNameReference,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               SingleTypeReference singleTypeReference,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               SingleTypeReference singleTypeReference,
+               ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(SuperReference superReference, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               SynchronizedStatement synchronizedStatement,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ThisReference thisReference, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(TryStatement tryStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               TypeDeclaration localTypeDeclaration,
+               BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(
+               TypeDeclaration memberTypeDeclaration,
+               ClassScope scope) {
+               return true; // do nothing by default, keep traversing
+       }       
+       public boolean visit(
+               TypeDeclaration typeDeclaration,
+               CompilationUnitScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+       public boolean visit(WhileStatement whileStatement, BlockScope scope) {
+               return true; // do nothing by default, keep traversing
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ClassFile.java b/src/java/org/eclipse/jdt/internal/compiler/ClassFile.java
new file mode 100644 (file)
index 0000000..e575af5
--- /dev/null
@@ -0,0 +1,2621 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.*;
+import java.util.StringTokenizer;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.StringConstant;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+/**
+ * Represents a class file wrapper on bytes, it is aware of its actual
+ * type name.
+ *
+ * Public APIs are listed below:
+ *
+ * byte[] getBytes();
+ *             Answer the actual bytes of the class file
+ *
+ * char[][] getCompoundName();
+ *             Answer the compound name of the class file.
+ *             For example, {{java}, {util}, {Hashtable}}.
+ *
+ * byte[] getReducedBytes();
+ *             Answer a smaller byte format, which is only contains some structural 
+ *      information. Those bytes are decodable with a regular class file reader, 
+ *      such as DietClassFileReader
+ */
+public class ClassFile
+       implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
+       public SourceTypeBinding referenceBinding;
+       public ConstantPool constantPool;
+       public ClassFile enclosingClassFile;
+       // used to generate private access methods
+       public int produceDebugAttributes;
+       public ReferenceBinding[] innerClassesBindings;
+       public int numberOfInnerClasses;
+       public byte[] header;
+       // the header contains all the bytes till the end of the constant pool
+       public byte[] contents;
+       // that collection contains all the remaining bytes of the .class file
+       public int headerOffset;
+       public int contentsOffset;
+       public int constantPoolOffset;
+       public int methodCountOffset;
+       public int methodCount;
+       protected boolean creatingProblemType;
+       public static final int INITIAL_CONTENTS_SIZE = 400;
+       public static final int INITIAL_HEADER_SIZE = 1500;
+       public boolean ownSharedArrays = false; // flag set when header/contents are set to shared arrays
+       public static final int INNER_CLASSES_SIZE = 5;
+       public CodeStream codeStream;
+       protected int problemLine;      // used to create line number attributes for problem methods
+       public long targetJDK;
+       
+       /**
+        * INTERNAL USE-ONLY
+        * This methods creates a new instance of the receiver.
+        */
+       public ClassFile() {
+               // default constructor for subclasses
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods creates a new instance of the receiver.
+        *
+        * @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
+        * @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
+        * @param creatingProblemType <CODE>boolean</CODE>
+        */
+       public ClassFile(
+               SourceTypeBinding aType,
+               ClassFile enclosingClassFile,
+               boolean creatingProblemType) {
+           
+               referenceBinding = aType;
+               initByteArrays();
+
+               // generate the magic numbers inside the header
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+               
+               this.targetJDK = referenceBinding.scope.environment().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
+               header[headerOffset++] = (byte) (this.targetJDK >> 16); // major low
+
+               constantPoolOffset = headerOffset;
+               headerOffset += 2;
+               constantPool = new ConstantPool(this);
+               
+               // Modifier manipulations for classfile
+               int accessFlags = aType.getAccessFlags();
+               if (aType.isPrivate()) { // rewrite private to non-public
+                       accessFlags &= ~AccPublic;
+               }
+               if (aType.isProtected()) { // rewrite protected into public
+                       accessFlags |= AccPublic;
+               }
+               // clear all bits that are illegal for a class or an interface
+               accessFlags
+                       &= ~(
+                               AccStrictfp
+                                       | AccProtected
+                                       | AccPrivate
+                                       | AccStatic
+                                       | AccSynchronized
+                                       | AccNative);
+                                       
+               // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
+               if (aType.isClass()) {
+                       accessFlags |= AccSuper;
+               }
+               
+               this.enclosingClassFile = enclosingClassFile;
+               // innerclasses get their names computed at code gen time
+
+               // now we continue to generate the bytes inside the contents array
+               contents[contentsOffset++] = (byte) (accessFlags >> 8);
+               contents[contentsOffset++] = (byte) accessFlags;
+               int classNameIndex = constantPool.literalIndex(aType);
+               contents[contentsOffset++] = (byte) (classNameIndex >> 8);
+               contents[contentsOffset++] = (byte) classNameIndex;
+               int superclassNameIndex;
+               if (aType.isInterface()) {
+                       superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+               } else {
+                       superclassNameIndex =
+                               (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+               }
+               contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
+               contents[contentsOffset++] = (byte) superclassNameIndex;
+               ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
+               int interfacesCount = superInterfacesBinding.length;
+               contents[contentsOffset++] = (byte) (interfacesCount >> 8);
+               contents[contentsOffset++] = (byte) interfacesCount;
+               for (int i = 0; i < interfacesCount; i++) {
+                       int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+                       contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
+                       contents[contentsOffset++] = (byte) interfaceIndex;
+               }
+               produceDebugAttributes = referenceBinding.scope.environment().options.produceDebugAttributes;
+               innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
+               this.creatingProblemType = creatingProblemType;
+               codeStream = new CodeStream(this);
+
+               // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
+               // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
+               ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
+               if (this == outermostClassFile) {
+                       codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
+               } else {
+                       codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        */
+       public void addAbstractMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding) {
+
+               // force the modifiers to be public and abstract
+               methodBinding.modifiers = AccPublic | AccAbstract;
+
+               this.generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
+               this.completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the attributes for the receiver.
+        * For a class they could be:
+        * - source file attribute
+        * - inner classes attribute
+        * - deprecated attribute
+        */
+       public void addAttributes() {
+               // update the method count
+               contents[methodCountOffset++] = (byte) (methodCount >> 8);
+               contents[methodCountOffset] = (byte) methodCount;
+
+               int attributeNumber = 0;
+               // leave two bytes for the number of attributes and store the current offset
+               int attributeOffset = contentsOffset;
+               contentsOffset += 2;
+
+               // source attribute
+               if ((produceDebugAttributes & CompilerOptions.Source) != 0) {
+                       String fullFileName =
+                               new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
+                       fullFileName = fullFileName.replace('\\', '/');
+                       int lastIndex = fullFileName.lastIndexOf('/');
+                       if (lastIndex != -1) {
+                               fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
+                       }
+                       // 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 sourceAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.SourceName);
+                       contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
+                       // The length of a source file attribute is 2. This is a fixed-length
+                       // attribute
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 2;
+                       // write the source file name
+                       int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
+                       contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) fileNameIndex;
+                       attributeNumber++;
+               }
+               // Deprecated attribute
+               if (referenceBinding.isDeprecated()) {
+                       // check that there is enough space to write all the bytes for the field info corresponding
+                       // to the @fieldBinding
+                       if (contentsOffset + 6 >= contents.length) {
+                               resizeContents(6);
+                       }
+                       int deprecatedAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+                       contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+                       // the length of a deprecated attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       attributeNumber++;
+               }
+               // Inner class attribute
+               if (numberOfInnerClasses != 0) {
+                       // Generate the inner class attribute
+                       int exSize = 8 * numberOfInnerClasses + 8;
+                       if (exSize + contentsOffset >= this.contents.length) {
+                               resizeContents(exSize);
+                       }
+                       // Now we now the size of the attribute and the number of entries
+                       // attribute name
+                       int attributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
+                       contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) attributeNameIndex;
+                       int value = (numberOfInnerClasses << 3) + 2;
+                       contents[contentsOffset++] = (byte) (value >> 24);
+                       contents[contentsOffset++] = (byte) (value >> 16);
+                       contents[contentsOffset++] = (byte) (value >> 8);
+                       contents[contentsOffset++] = (byte) value;
+                       contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
+                       contents[contentsOffset++] = (byte) numberOfInnerClasses;
+                       for (int i = 0; i < numberOfInnerClasses; i++) {
+                               ReferenceBinding innerClass = innerClassesBindings[i];
+                               int accessFlags = innerClass.getAccessFlags();
+                               int innerClassIndex = constantPool.literalIndex(innerClass);
+                               // 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());
+                                       contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
+                                       contents[contentsOffset++] = (byte) outerClassIndex;
+                               } else {
+                                       // equals to 0 if the innerClass is not a member type
+                                       contents[contentsOffset++] = 0;
+                                       contents[contentsOffset++] = 0;
+                               }
+                               // name index
+                               if (!innerClass.isAnonymousType()) {
+                                       int nameIndex = constantPool.literalIndex(innerClass.sourceName());
+                                       contents[contentsOffset++] = (byte) (nameIndex >> 8);
+                                       contents[contentsOffset++] = (byte) nameIndex;
+                               } else {
+                                       // equals to 0 if the innerClass is an anonymous type
+                                       contents[contentsOffset++] = 0;
+                                       contents[contentsOffset++] = 0;
+                               }
+                               // access flag
+                               if (innerClass.isAnonymousType()) {
+                                       accessFlags |= AccPrivate;
+                               } else
+                                       if (innerClass.isLocalType() && !innerClass.isMemberType()) {
+                                               accessFlags |= AccPrivate;
+                                       }
+                               contents[contentsOffset++] = (byte) (accessFlags >> 8);
+                               contents[contentsOffset++] = (byte) accessFlags;
+                       }
+                       attributeNumber++;
+               }
+               // update the number of attributes
+               if (attributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[attributeOffset] = (byte) attributeNumber;
+
+               // resynchronize all offsets of the classfile
+               header = constantPool.poolContent;
+               headerOffset = constantPool.currentOffset;
+               int constantPoolCount = constantPool.currentIndex;
+               header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
+               header[constantPoolOffset] = (byte) constantPoolCount;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the default abstract method infos that correpond to
+        * the abstract methods inherited from superinterfaces.
+        */
+       public void addDefaultAbstractMethods() { // default abstract methods
+               MethodBinding[] defaultAbstractMethods =
+                       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);
+               }
+       }
+
+       /**
+        * 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;
+               // 4.7.2 only static constant fields get a ConstantAttribute
+               if (fieldBinding.constant != Constant.NotAConstant){
+                       // Now we generate the constant attribute corresponding to the fieldBinding
+                       int constantValueNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
+                       contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) constantValueNameIndex;
+                       // The attribute length = 2 in case of a constantValue attribute
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 2;
+                       attributeNumber++;
+                       // Need to add the constant_value_index
+                       switch (fieldBinding.constant.typeID()) {
+                               case T_boolean :
+                                       int booleanValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
+                                       contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) booleanValueIndex;
+                                       break;
+                               case T_byte :
+                               case T_char :
+                               case T_int :
+                               case T_short :
+                                       int integerValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.intValue());
+                                       contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) integerValueIndex;
+                                       break;
+                               case T_float :
+                                       int floatValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.floatValue());
+                                       contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) floatValueIndex;
+                                       break;
+                               case T_double :
+                                       int doubleValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.doubleValue());
+                                       contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) doubleValueIndex;
+                                       break;
+                               case T_long :
+                                       int longValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.longValue());
+                                       contents[contentsOffset++] = (byte) (longValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) longValueIndex;
+                                       break;
+                               case T_String :
+                                       int stringValueIndex =
+                                               constantPool.literalIndex(
+                                                       ((StringConstant) fieldBinding.constant).stringValue());
+                                       if (stringValueIndex == -1) {
+                                               if (!creatingProblemType) {
+                                                       // report an error and abort: will lead to a problem type classfile creation
+                                                       TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+                                                       FieldDeclaration[] fieldDecls = typeDeclaration.fields;
+                                                       for (int i = 0, max = fieldDecls.length; i < max; i++) {
+                                                               if (fieldDecls[i].binding == fieldBinding) {
+                                                                       // problem should abort
+                                                                       typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(
+                                                                               fieldDecls[i]);
+                                                               }
+                                                       }
+                                               } 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--;
+                                               }
+                                       } else {
+                                               contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
+                                               contents[contentsOffset++] = (byte) stringValueIndex;
+                                       }
+                       }
+               }
+               if (fieldBinding.isSynthetic()) {
+                       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;
+                       attributeNumber++;
+               }
+               if (fieldBinding.isDeprecated()) {
+                       int deprecatedAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+                       contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+                       // the length of a deprecated attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       attributeNumber++;
+               }
+               contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[fieldAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * 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();
+               int fieldCount =
+                       currentBinding.fieldCount()
+                               + (syntheticFields == null ? 0 : syntheticFields.length);
+
+               // write the number of fields
+               if (fieldCount > 0xFFFF) {
+                       referenceBinding.scope.problemReporter().tooManyFields(referenceBinding.scope.referenceType());
+               }
+               contents[contentsOffset++] = (byte) (fieldCount >> 8);
+               contents[contentsOffset++] = (byte) fieldCount;
+
+               FieldBinding[] fieldBindings = currentBinding.fields();
+               for (int i = 0, max = fieldBindings.length; i < max; i++) {
+                       addFieldInfo(fieldBindings[i]);
+               }
+               if (syntheticFields != null) {
+                       for (int i = 0, max = syntheticFields.length; i < max; i++) {
+                               addFieldInfo(syntheticFields[i]);
+                       }
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods stores the bindings for each inner class. They will be used to know which entries
+        * have to be generated for the inner classes attributes.
+        * @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
+        */
+       public void addInnerClasses(ReferenceBinding refBinding) {
+               // check first if that reference binding is there
+               for (int i = 0; i < numberOfInnerClasses; i++) {
+                       if (innerClassesBindings[i] == refBinding)
+                               return;
+               }
+               int length = innerClassesBindings.length;
+               if (numberOfInnerClasses == length) {
+                       System.arraycopy(
+                               innerClassesBindings,
+                               0,
+                               innerClassesBindings = new ReferenceBinding[length * 2],
+                               0,
+                               length);
+               }
+               innerClassesBindings[numberOfInnerClasses++] = refBinding;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem clinit method info that correspond to a boggus method.
+        *
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemClinit(IProblem[] problems) {
+               generateMethodInfoHeaderForClinit();
+               // leave two spaces for the number of attributes
+               contentsOffset -= 2;
+               int attributeOffset = contentsOffset;
+               contentsOffset += 2;
+               int attributeNumber = 0;
+
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.resetForProblemClinit(this);
+               String problemString = "" ; //$NON-NLS-1$
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               IProblem problem = problems[i];
+                               if ((problem != null) && (problem.isError())) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                                       problems[i] = null;
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
+                       } else {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+               attributeNumber++; // code attribute
+               completeCodeAttributeForClinit(
+                       codeAttributeOffset,
+                       referenceBinding
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[attributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus constructor.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemConstructor(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems) {
+
+               // 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();
+               codeStream.reset(method, this);
+               String problemString = "" ; //$NON-NLS-1$
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               IProblem problem = problems[i];
+                               if ((problem != null) && (problem.isError())) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
+                       } else {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+               completeCodeAttributeForProblemMethod(
+                       method,
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus constructor.
+        * Reset the position inside the contents byte array to the savedOffset.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        * @param savedOffset <CODE>int</CODE>
+        */
+       public void addProblemConstructor(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems,
+               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
+               addProblemConstructor(method, methodBinding, problems);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems) {
+               if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
+                       method.abort(ProblemSeverities.AbortType, null);
+               }
+               // 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();
+               codeStream.reset(method, this);
+               String problemString = "" ; //$NON-NLS-1$
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               IProblem problem = problems[i];
+                               if ((problem != null)
+                                       && (problem.isError())
+                                       && (problem.getSourceStart() >= method.declarationSourceStart)
+                                       && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                                       problems[i] = null;
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
+                       } else {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+               completeCodeAttributeForProblemMethod(
+                       method,
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        * Reset the position inside the contents byte array to the savedOffset.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        * @param savedOffset <CODE>int</CODE>
+        */
+       public void addProblemMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems,
+               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);
+       }
+
+       /**
+        * 
+        */
+       public void completeCodeAttributeForMissingAbstractProblemMethod(
+               MethodBinding binding,
+               int codeAttributeOffset,
+               int[] startLineIndexes) {
+               // reinitialize the localContents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+               int max_stack = codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = codeStream.position;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+               // write the exception table
+               if (localContentsOffset + 50 >= this.contents.length) {
+                       resizeContents(50);
+               }
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributeNumber = 0; // leave two bytes for the attribute_length
+               localContentsOffset += 2; // first we handle the linenumber attribute
+
+               if (codeStream.generateLineNumberAttributes) {
+                       /* Create and add the line number attribute (used for debugging) 
+                           * Build the pairs of:
+                           * (bytecodePC lineNumber)
+                           * according to the table of start line indexes and the pcToSourceMap table
+                           * contained into the codestream
+                           */
+                       int lineNumberNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                       this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 6;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 1;
+                       if (problemLine == 0) {
+                               problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+                       }
+                       // first entry at pc = 0
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
+                       this.contents[localContentsOffset++] = (byte) problemLine;
+                       // now we change the size of the line number attribute
+                       attributeNumber++;
+               }
+               
+               // then we do the local variable attribute
+               // update the number of attributes// ensure first that there is enough space available inside the localContents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a synthetic method that
+        * generate an access to a private constructor.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       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) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       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 write access to a private field.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       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 access to a private method.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       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
+        * 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
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttribute(int codeAttributeOffset) {
+               // 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 code_length = codeStream.position;
+               if (code_length > 65535) {
+                       codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               codeStream.methodDeclaration);
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               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;
+               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
+               int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+               ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+               int exSize = exceptionHandlersNumber * 8 + 2;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move 
+               // on the attribute generation
+               this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+               this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+               for (int i = 0; i < exceptionHandlersNumber; 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();
+                               } else {
+                                       nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                       }
+               }
+               // 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[] pcToSourceMapTable;
+                       if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
+                               && (codeStream.pcToSourceMapSize != 0)) {
+                               int lineNumberNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                               int lineNumberTableOffset = localContentsOffset;
+                               localContentsOffset += 6;
+                               // leave space for attribute_length and line_number_table_length
+                               int numberOfEntries = 0;
+                               int length = codeStream.pcToSourceMapSize;
+                               for (int i = 0; i < length;) {
+                                       // write the entry
+                                       if (localContentsOffset + 4 >= this.contents.length) {
+                                               resizeContents(4);
+                                       }
+                                       int pc = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (pc >> 8);
+                                       this.contents[localContentsOffset++] = (byte) pc;
+                                       int lineNumber = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
+                                       this.contents[localContentsOffset++] = (byte) lineNumber;
+                                       numberOfEntries++;
+                               }
+                               // now we change the size of the line number attribute
+                               int lineNumberAttr_length = numberOfEntries * 4 + 2;
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+                               this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
+                               attributeNumber++;
+                       }
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       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;
+                       if (!codeStream.methodDeclaration.isStatic()) {
+                               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);
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                               descriptorIndex =
+                                       constantPool.literalIndex(
+                                               codeStream.methodDeclaration.binding.declaringClass.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++) {
+                               LocalVariableBinding localVariable = codeStream.locals[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
+                                               if (endPC == -1) {
+                                                       localVariable.declaringScope.problemReporter().abortDueToInternalError(
+                                                               Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
+                                                               (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
+                                               }
+                                               if (localContentsOffset + 10 >= this.contents.length) {
+                                                       resizeContents(10);
+                                               }
+                                               // now we can safely add the local entry
+                                               numberOfEntries++;
+                                               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.signature());
+                                               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;
+                                       }
+                               }
+                       }
+                       int value = numberOfEntries * 10 + 2;
+                       localVariableTableOffset += 2;
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 24);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 16);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 8);
+                       this.contents[localVariableTableOffset++] = (byte) value;
+                       this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                       this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+                       attributeNumber++;
+               }
+               // 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
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForClinit(int codeAttributeOffset) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents 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 code_length = codeStream.position;
+               if (code_length > 65535) {
+                       codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               codeStream.methodDeclaration.scope.referenceType());
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               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;
+               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
+               int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+               ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+               int exSize = exceptionHandlersNumber * 8 + 2;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move 
+               // on the attribute generation
+               this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+               this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+               for (int i = 0; i < exceptionHandlersNumber; 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();
+                               } else {
+                                       nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                       }
+               }
+               // 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[] pcToSourceMapTable;
+                       if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
+                               && (codeStream.pcToSourceMapSize != 0)) {
+                               int lineNumberNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                               int lineNumberTableOffset = localContentsOffset;
+                               localContentsOffset += 6;
+                               // leave space for attribute_length and line_number_table_length
+                               int numberOfEntries = 0;
+                               int length = codeStream.pcToSourceMapSize;
+                               for (int i = 0; i < length;) {
+                                       // write the entry
+                                       if (localContentsOffset + 4 >= this.contents.length) {
+                                               resizeContents(4);
+                                       }
+                                       int pc = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (pc >> 8);
+                                       this.contents[localContentsOffset++] = (byte) pc;
+                                       int lineNumber = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
+                                       this.contents[localContentsOffset++] = (byte) lineNumber;
+                                       numberOfEntries++;
+                               }
+                               // now we change the size of the line number attribute
+                               int lineNumberAttr_length = numberOfEntries * 4 + 2;
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+                               this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
+                               attributeNumber++;
+                       }
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       //              codeAttribute.addLocalVariableTableAttribute(this);
+                       if ((codeStream.pcToSourceMap != null)
+                               && (codeStream.pcToSourceMapSize != 0)) {
+                               int localVariableNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               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++) {
+                                       LocalVariableBinding localVariable = codeStream.locals[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
+                                                       if (endPC == -1) {
+                                                               localVariable.declaringScope.problemReporter().abortDueToInternalError(
+                                                                       Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
+                                                                       (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
+                                                       }
+                                                       if (localContentsOffset + 10 >= this.contents.length) {
+                                                               resizeContents(10);
+                                                       }
+                                                       // now we can safely add the local entry
+                                                       numberOfEntries++;
+                                                       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.signature());
+                                                       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;
+                                               }
+                                       }
+                               }
+                               int value = numberOfEntries * 10 + 2;
+                               localVariableTableOffset += 2;
+                               this.contents[localVariableTableOffset++] = (byte) (value >> 24);
+                               this.contents[localVariableTableOffset++] = (byte) (value >> 16);
+                               this.contents[localVariableTableOffset++] = (byte) (value >> 8);
+                               this.contents[localVariableTableOffset++] = (byte) value;
+                               this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+                               attributeNumber++;
+                       }
+               }
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents 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
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        * @param startLineIndexes int[]
+        */
+       public void completeCodeAttributeForClinit(
+               int codeAttributeOffset,
+               int[] startLineIndexes) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents 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 code_length = codeStream.position;
+               if (code_length > 65535) {
+                       codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               codeStream.methodDeclaration.scope.referenceType());
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               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;
+               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
+               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
+
+               // first we handle the linenumber attribute
+               if (codeStream.generateLineNumberAttributes) {
+                       if (localContentsOffset + 20 >= this.contents.length) {
+                               resizeContents(20);
+                       }                       
+                       /* 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;
+                       // 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
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 2;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       attributeNumber++;
+               }
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents 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
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForProblemMethod(
+               AbstractMethodDeclaration method,
+               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);
+               }
+
+               // write the exception table
+               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) {
+                       if (localContentsOffset + 20 >= this.contents.length) {
+                               resizeContents(20);
+                       }
+                       /* 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
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       // compute the resolved position for the arguments of the method
+                       int argSize;
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       //              codeAttribute.addLocalVariableTableAttribute(this);
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                       localContentsOffset += 6;
+                       // leave space for attribute_length and local_variable_table_length
+                       int descriptorIndex;
+                       if (!codeStream.methodDeclaration.isStatic()) {
+                               numberOfEntries++;
+                               if (localContentsOffset + 10 >= this.contents.length) {
+                                       resizeContents(10);
+                               }
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                               this.contents[localContentsOffset++] = (byte) code_length;
+                               int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                               descriptorIndex =
+                                       constantPool.literalIndex(
+                                               codeStream.methodDeclaration.binding.declaringClass.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;
+                       }
+                       if (binding.isConstructor()) {
+                               ReferenceBinding declaringClass = binding.declaringClass;
+                               if (declaringClass.isNestedType()) {
+                                       NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
+                                       argSize = methodDeclaringClass.enclosingInstancesSlotSize;
+                                       SyntheticArgumentBinding[] syntheticArguments;
+                                       if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances())
+                                               != null) {
+                                               for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+                                                       LocalVariableBinding localVariable = syntheticArguments[i];
+                                                       if (localContentsOffset + 10 >= this.contents.length) {
+                                                               resizeContents(10);
+                                                       }
+                                                       // now we can safely add the local entry
+                                                       numberOfEntries++;
+                                                       this.contents[localContentsOffset++] = 0;
+                                                       this.contents[localContentsOffset++] = 0;
+                                                       this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) code_length;
+                                                       int nameIndex = constantPool.literalIndex(localVariable.name);
+                                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                                       descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                                       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;
+                                               }
+                                       }
+                               } else {
+                                       argSize = 1;
+                               }
+                       } else {
+                               argSize = binding.isStatic() ? 0 : 1;
+                       }
+                       if (method.binding != null) {
+                               TypeBinding[] parameters = method.binding.parameters;
+                               Argument[] arguments = method.arguments;
+                               if ((parameters != null) && (arguments != null)) {
+                                       for (int i = 0, max = parameters.length; i < max; i++) {
+                                               TypeBinding argumentBinding = parameters[i];
+                                               if (localContentsOffset + 10 >= this.contents.length) {
+                                                       resizeContents(10);
+                                               }
+                                               // now we can safely add the local entry
+                                               numberOfEntries++;
+                                               this.contents[localContentsOffset++] = 0;
+                                               this.contents[localContentsOffset++] = 0;
+                                               this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                                               this.contents[localContentsOffset++] = (byte) code_length;
+                                               int nameIndex = constantPool.literalIndex(arguments[i].name);
+                                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                                               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;
+                                               else
+                                                       argSize++;
+                                               this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                               this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                                       }
+                               }
+                       }
+                       int value = numberOfEntries * 10 + 2;
+                       localVariableTableOffset += 2;
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 24);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 16);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 8);
+                       this.contents[localVariableTableOffset++] = (byte) value;
+                       this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                       this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+                       attributeNumber++;
+               }
+               // 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
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForSyntheticAccessMethod(
+               SyntheticAccessMethodBinding binding,
+               int codeAttributeOffset,
+               int[] startLineIndexes) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents 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;
+               contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = codeStream.position;
+               contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               contents[codeAttributeOffset + 13] = (byte) code_length;
+               if ((localContentsOffset + 40) >= this.contents.length) {
+                       resizeContents(40);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move 
+               // on the attribute generation
+               contents[localContentsOffset++] = 0;
+               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) {
+                       int index = 0;
+                       int lineNumberNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                       contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                       contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                       int lineNumberTableOffset = localContentsOffset;
+                       localContentsOffset += 6;
+                       // leave space for attribute_length and line_number_table_length
+                       // Seems like do would be better, but this preserves the existing behavior.
+                       index = searchLineNumber(startLineIndexes, binding.sourceStart);
+                       contents[localContentsOffset++] = 0;
+                       contents[localContentsOffset++] = 0;
+                       contents[localContentsOffset++] = (byte) (index >> 8);
+                       contents[localContentsOffset++] = (byte) index;
+                       // now we change the size of the line number attribute
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 6;
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 1;
+                       attributeNumber++;
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 > this.contents.length) {
+                               resizeContents(8);
+                       }
+                       contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       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++) {
+                               LocalVariableBinding localVariable = codeStream.locals[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
+                                               if (endPC == -1) {
+                                                       localVariable.declaringScope.problemReporter().abortDueToInternalError(
+                                                               Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
+                                                               (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
+                                               }
+                                               if (localContentsOffset + 10 > this.contents.length) {
+                                                       resizeContents(10);
+                                               }
+                                               // now we can safely add the local entry
+                                               numberOfEntries++;
+                                               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.signature());
+                                               contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                               contents[localContentsOffset++] = (byte) descriptorIndex;
+                                               int resolvedPosition = localVariable.resolvedPosition;
+                                               contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                               contents[localContentsOffset++] = (byte) resolvedPosition;
+                                       }
+                               }
+                       }
+                       int value = numberOfEntries * 10 + 2;
+                       localVariableTableOffset += 2;
+                       contents[localVariableTableOffset++] = (byte) (value >> 24);
+                       contents[localVariableTableOffset++] = (byte) (value >> 16);
+                       contents[localVariableTableOffset++] = (byte) (value >> 8);
+                       contents[localVariableTableOffset++] = (byte) value;
+                       contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                       contents[localVariableTableOffset] = (byte) numberOfEntries;
+                       attributeNumber++;
+               }
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Complete the creation of a method info by setting up the number of attributes at the right offset.
+        *
+        * @param methodAttributeOffset <CODE>int</CODE>
+        * @param attributeNumber <CODE>int</CODE> 
+        */
+       public void completeMethodInfo(
+               int methodAttributeOffset,
+               int attributeNumber) {
+               // update the number of attributes
+               contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Request the creation of a ClassFile compatible representation of a problematic type
+        *
+        * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
+        * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+        */
+       public static void createProblemType(
+               TypeDeclaration typeDeclaration,
+               CompilationResult unitResult) {
+               SourceTypeBinding typeBinding = typeDeclaration.binding;
+               ClassFile classFile = new ClassFile(typeBinding, null, true);
+
+               // TODO (olivier) handle cases where a field cannot be generated (name too long)
+               // TODO (olivier) handle too many methods
+               // inner attributes
+               if (typeBinding.isMemberType())
+                       classFile.recordEnclosingTypeAttributes(typeBinding);
+
+               // add its fields
+               FieldBinding[] fields = typeBinding.fields;
+               if ((fields != null) && (fields != NoFields)) {
+                       for (int i = 0, max = fields.length; i < max; i++) {
+                               if (fields[i].constant == null) {
+                                       FieldReference.getConstantFor(fields[i], null, false, null);
+                               }
+                       }
+                       classFile.addFieldInfos();
+               } else {
+                       // we have to set the number of fields to be equals to 0
+                       classFile.contents[classFile.contentsOffset++] = 0;
+                       classFile.contents[classFile.contentsOffset++] = 0;
+               }
+               // leave some space for the methodCount
+               classFile.setForMethodInfos();
+               // add its user defined methods
+               MethodBinding[] methods = typeBinding.methods;
+               AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
+               int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
+               int problemsLength;
+               IProblem[] problems = unitResult.getErrors();
+               if (problems == null) {
+                       problems = new IProblem[0];
+               }
+               IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+               System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+               if (methods != null) {
+                       if (typeBinding.isInterface()) {
+                               // we cannot create problem methods for an interface. So we have to generate a clinit
+                               // which should contain all the problem
+                               classFile.addProblemClinit(problemsCopy);
+                               for (int i = 0, max = methods.length; i < max; i++) {
+                                       MethodBinding methodBinding;
+                                       if ((methodBinding = methods[i]) != null) {
+                                               // find the corresponding method declaration
+                                               for (int j = 0; j < maxMethodDecl; j++) {
+                                                       if ((methodDeclarations[j] != null)
+                                                               && (methodDeclarations[j].binding == methods[i])) {
+                                                               if (!methodBinding.isConstructor()) {
+                                                                       classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               for (int i = 0, max = methods.length; i < max; i++) {
+                                       MethodBinding methodBinding;
+                                       if ((methodBinding = methods[i]) != null) {
+                                               // find the corresponding method declaration
+                                               for (int j = 0; j < maxMethodDecl; j++) {
+                                                       if ((methodDeclarations[j] != null)
+                                                               && (methodDeclarations[j].binding == methods[i])) {
+                                                               AbstractMethodDeclaration methodDecl;
+                                                               if ((methodDecl = methodDeclarations[j]).isConstructor()) {
+                                                                       classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
+                                                               } else {
+                                                                       classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       // add abstract methods
+                       classFile.addDefaultAbstractMethods();
+               }
+               // propagate generation of (problem) member types
+               if (typeDeclaration.memberTypes != null) {
+                       for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
+                               TypeDeclaration memberType = typeDeclaration.memberTypes[i];
+                               if (memberType.binding != null) {
+                                       classFile.recordNestedMemberAttribute(memberType.binding);
+                                       ClassFile.createProblemType(memberType, unitResult);
+                               }
+                       }
+               }
+               classFile.addAttributes();
+               unitResult.record(typeBinding.constantPoolName(), classFile);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods returns a char[] representing the file name of the receiver
+        *
+        * @return char[]
+        */
+       public char[] fileName() {
+               return constantPool.UTF8Cache.returnKeyFor(1);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a code attribute.
+        * - the index inside the constant pool for the attribute name ("Code")
+        * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
+        */
+       public void generateCodeAttributeHeader() {
+               if (contentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int constantValueNameIndex =
+                       constantPool.literalIndex(AttributeNamesConstants.CodeName);
+               contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+               contents[contentsOffset++] = (byte) constantValueNameIndex;
+               // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
+               contentsOffset += 12;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the attributes of a code attribute.
+        * They could be:
+        * - an exception attribute for each try/catch found inside the method
+        * - a deprecated attribute
+        * - a synthetic attribute for synthetic access methods
+        *
+        * It returns the number of attributes created for the code attribute.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        * @return <CODE>int</CODE>
+        */
+       public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+               // leave two bytes for the attribute_number
+               contentsOffset += 2;
+               // now we can handle all the attribute for that method info:
+               // it could be:
+               // - a CodeAttribute
+               // - a ExceptionAttribute
+               // - a DeprecatedAttribute
+               // - a SyntheticAttribute
+
+               // Exception attribute
+               ReferenceBinding[] thrownsExceptions;
+               int attributeNumber = 0;
+               if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
+                       // The method has a throw clause. So we need to add an exception attribute
+                       // check that there is enough space to write all the bytes for the exception attribute
+                       int length = thrownsExceptions.length;
+                       int exSize = 8 + length * 2;
+                       if (exSize + contentsOffset >= this.contents.length) {
+                               resizeContents(exSize);
+                       }
+                       int exceptionNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
+                       contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) exceptionNameIndex;
+                       // The attribute length = length * 2 + 2 in case of a exception attribute
+                       int attributeLength = length * 2 + 2;
+                       contents[contentsOffset++] = (byte) (attributeLength >> 24);
+                       contents[contentsOffset++] = (byte) (attributeLength >> 16);
+                       contents[contentsOffset++] = (byte) (attributeLength >> 8);
+                       contents[contentsOffset++] = (byte) attributeLength;
+                       contents[contentsOffset++] = (byte) (length >> 8);
+                       contents[contentsOffset++] = (byte) length;
+                       for (int i = 0; i < length; i++) {
+                               int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+                               contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
+                               contents[contentsOffset++] = (byte) exceptionIndex;
+                       }
+                       attributeNumber++;
+               }
+               if (methodBinding.isDeprecated()) {
+                       // Deprecated attribute
+                       // Check that there is enough space to write the deprecated attribute
+                       if (contentsOffset + 6 >= this.contents.length) {
+                               resizeContents(6);
+                       }
+                       int deprecatedAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+                       contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+                       // the length of a deprecated attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+
+                       attributeNumber++;
+               }
+               if (this.targetJDK < ClassFileConstants.JDK1_5 && methodBinding.isSynthetic()) {
+                       // Synthetic attribute
+                       // Check that there is enough space to write the deprecated attribute
+                       if (contentsOffset + 6 >= this.contents.length) {
+                               resizeContents(6);
+                       }
+                       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;
+
+                       attributeNumber++;
+               }
+               return attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a method info:
+        * The header consists in:
+        * - the access flags
+        * - the name index of the method name inside the constant pool
+        * - the descriptor index of the signature of the method inside the constant pool.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        */
+       public void generateMethodInfoHeader(MethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers);
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a method info:
+        * The header consists in:
+        * - the access flags
+        * - the name index of the method name inside the constant pool
+        * - the descriptor index of the signature of the method inside the constant pool.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        * @param accessFlags the access flags
+        */
+       public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) {
+               // check that there is enough space to write all the bytes for the method info corresponding
+               // to the @methodBinding
+               methodCount++; // add one more method
+               if (contentsOffset + 10 >= this.contents.length) {
+                       resizeContents(10);
+               }
+               if (targetJDK < ClassFileConstants.JDK1_5) {
+                   // pre 1.5, synthetic was an attribute, not a modifier
+                   accessFlags &= ~AccSynthetic;
+               }
+               if (methodBinding.isRequiredToClearPrivateModifier()) {
+                       accessFlags &= ~AccPrivate;
+               }
+               contents[contentsOffset++] = (byte) (accessFlags >> 8);
+               contents[contentsOffset++] = (byte) accessFlags;
+               int nameIndex = constantPool.literalIndex(methodBinding.selector);
+               contents[contentsOffset++] = (byte) (nameIndex >> 8);
+               contents[contentsOffset++] = (byte) nameIndex;
+               int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
+               contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+               contents[contentsOffset++] = (byte) descriptorIndex;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the method info header of a clinit:
+        * The header consists in:
+        * - the access flags (always default access + static)
+        * - the name index of the method name (always <clinit>) inside the constant pool 
+        * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
+        */
+       public void generateMethodInfoHeaderForClinit() {
+               // check that there is enough space to write all the bytes for the method info corresponding
+               // to the @methodBinding
+               methodCount++; // add one more method
+               if (contentsOffset + 10 >= this.contents.length) {
+                       resizeContents(10);
+               }
+               contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
+               contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
+               int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
+               contents[contentsOffset++] = (byte) (nameIndex >> 8);
+               contents[contentsOffset++] = (byte) nameIndex;
+               int descriptorIndex =
+                       constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
+               contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+               contents[contentsOffset++] = (byte) descriptorIndex;
+               // We know that we won't get more than 1 attribute: the code attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 1;
+       }
+
+       /**
+        * EXTERNAL API
+        * Answer the actual bytes of the class file
+        *
+        * This method encodes the receiver structure into a byte array which is the content of the classfile.
+        * Returns the byte array that represents the encoded structure of the receiver.
+        *
+        * @return byte[]
+        */
+       public byte[] getBytes() {
+               byte[] fullContents = new byte[headerOffset + contentsOffset];
+               System.arraycopy(header, 0, fullContents, 0, headerOffset);
+               System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
+               return fullContents;
+       }
+
+       /**
+        * EXTERNAL API
+        * Answer the compound name of the class file.
+        * @return char[][]
+        * e.g. {{java}, {util}, {Hashtable}}.
+        */
+       public char[][] getCompoundName() {
+               return CharOperation.splitOn('/', fileName());
+       }
+
+       protected void initByteArrays() {
+               LookupEnvironment env = this.referenceBinding.scope.environment();
+               synchronized (env) {
+                       if (env.sharedArraysUsed) {
+                               this.ownSharedArrays = false;
+                               int members = referenceBinding.methods().length + referenceBinding.fields().length;
+                               this.header = new byte[INITIAL_HEADER_SIZE];
+                               this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE];
+                       } else {
+                               this.ownSharedArrays = env.sharedArraysUsed = true;
+                               this.header = env.sharedClassFileHeader;
+                               this.contents = env.sharedClassFileContents;
+                       }
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
+        * for all inner types of the receiver.
+        * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
+        */
+       public ClassFile outerMostEnclosingClassFile() {
+               ClassFile current = this;
+               while (current.enclosingClassFile != null)
+                       current = current.enclosingClassFile;
+               return current;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+        * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+        */
+       public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
+               // add all the enclosing types
+               ReferenceBinding enclosingType = referenceBinding.enclosingType();
+               int depth = 0;
+               while (enclosingType != null) {
+                       depth++;
+                       enclosingType = enclosingType.enclosingType();
+               }
+               enclosingType = referenceBinding;
+               ReferenceBinding enclosingTypes[];
+               if (depth >= 2) {
+                       enclosingTypes = new ReferenceBinding[depth];
+                       for (int i = depth - 1; i >= 0; i--) {
+                               enclosingTypes[i] = enclosingType;
+                               enclosingType = enclosingType.enclosingType();
+                       }
+                       for (int i = 0; i < depth; i++) {
+                               addInnerClasses(enclosingTypes[i]);
+                       }
+               } else {
+                       addInnerClasses(referenceBinding);
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+        * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+        */
+       public void recordNestedLocalAttribute(ReferenceBinding binding) {
+               // add all the enclosing types
+               ReferenceBinding enclosingType = referenceBinding.enclosingType();
+               int depth = 0;
+               while (enclosingType != null) {
+                       depth++;
+                       enclosingType = enclosingType.enclosingType();
+               }
+               enclosingType = referenceBinding;
+               ReferenceBinding enclosingTypes[];
+               if (depth >= 2) {
+                       enclosingTypes = new ReferenceBinding[depth];
+                       for (int i = depth - 1; i >= 0; i--) {
+                               enclosingTypes[i] = enclosingType;
+                               enclosingType = enclosingType.enclosingType();
+                       }
+                       for (int i = 0; i < depth; i++)
+                               addInnerClasses(enclosingTypes[i]);
+               } else {
+                       addInnerClasses(binding);
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+        * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+        */
+       public void recordNestedMemberAttribute(ReferenceBinding binding) {
+               addInnerClasses(binding);
+       }
+       
+       /**
+        * Resize the pool contents
+        */
+       private final void resizeContents(int minimalSize) {
+               int length = this.contents.length;
+               int toAdd = length;
+               if (toAdd < minimalSize)
+                       toAdd = minimalSize;
+               System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length);
+       }
+
+       /**
+        * 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() {
+               // leave some space for the methodCount
+               methodCountOffset = contentsOffset;
+               contentsOffset += 2;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * outputPath is formed like:
+        *         c:\temp\ the last character is a file separator
+        * relativeFileName is formed like:
+        *     java\lang\String.class
+        * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
+        * @param outputPath the output directory
+        * @param relativeFileName java.lang.String
+        * @param contents byte[]
+        * 
+        */
+       public static void writeToDisk(
+               boolean generatePackagesStructure,
+               String outputPath,
+               String relativeFileName,
+               byte[] contents)
+               throws IOException {
+                       
+               BufferedOutputStream output = null;
+               if (generatePackagesStructure) {
+                       output = new BufferedOutputStream(
+                               new FileOutputStream(
+                                               new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
+               } else {
+                       String fileName = null;
+                       char fileSeparatorChar = File.separatorChar;
+                       String fileSeparator = File.separator;
+                       // First we ensure that the outputPath exists
+                       outputPath = outputPath.replace('/', fileSeparatorChar);
+                       // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+                       int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
+                       if (indexOfPackageSeparator == -1) {
+                               if (outputPath.endsWith(fileSeparator)) {
+                                       fileName = outputPath + relativeFileName;
+                               } else {
+                                       fileName = outputPath + fileSeparator + relativeFileName;
+                               }
+                       } else {
+                               int length = relativeFileName.length();
+                               if (outputPath.endsWith(fileSeparator)) {
+                                       fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+                               } else {
+                                       fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+                               }
+                       }
+                       output = new BufferedOutputStream(
+                               new FileOutputStream(
+                                               new File(fileName)));
+               }
+               try {
+                       output.write(contents);
+               } finally {
+                       output.flush();
+                       output.close();
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/CompilationResult.java b/src/java/org/eclipse/jdt/internal/compiler/CompilationResult.java
new file mode 100644 (file)
index 0000000..684df0b
--- /dev/null
@@ -0,0 +1,427 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * A compilation result consists of all information returned by the compiler for 
+ * a single compiled compilation source unit.  This includes:
+ * <ul>
+ * <li> the compilation unit that was compiled
+ * <li> for each type produced by compiling the compilation unit, its binary and optionally its principal structure
+ * <li> any problems (errors or warnings) produced
+ * <li> dependency info
+ * </ul>
+ *
+ * The principle structure and binary may be null if the compiler could not produce them.
+ * If neither could be produced, there is no corresponding entry for the type.
+ *
+ * The dependency info includes type references such as supertypes, field types, method
+ * parameter and return types, local variable types, types of intermediate expressions, etc.
+ * It also includes the namespaces (packages) in which names were looked up.
+ * It does <em>not</em> include finer grained dependencies such as information about
+ * specific fields and methods which were referenced, but does contain their 
+ * declaring types and any other types used to locate such fields or methods.
+ */
+
+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 java.util.*;
+
+public class CompilationResult {
+       
+       public IProblem problems[];
+       public IProblem tasks[];
+       public int problemCount;
+       public int taskCount;
+       public ICompilationUnit compilationUnit;
+       private Map problemsMap;
+       private Map firstErrorsMap;
+       private int maxProblemPerUnit;
+       public char[][][] qualifiedReferences;
+       public char[][] simpleNameReferences;
+
+       public int lineSeparatorPositions[];
+       public Hashtable compiledTypes = new Hashtable(11);
+       public int unitIndex, totalUnitsKnown;
+       public boolean hasBeenAccepted = false;
+       public char[] fileName;
+       
+       public CompilationResult(
+               char[] fileName,
+               int unitIndex, 
+               int totalUnitsKnown,
+               int maxProblemPerUnit){
+       
+               this.fileName = fileName;
+               this.unitIndex = unitIndex;
+               this.totalUnitsKnown = totalUnitsKnown;
+               this.maxProblemPerUnit = maxProblemPerUnit;
+       }
+       
+       public CompilationResult(
+               ICompilationUnit compilationUnit,
+               int unitIndex, 
+               int totalUnitsKnown,
+               int maxProblemPerUnit){
+       
+               this.fileName = compilationUnit.getFileName();
+               this.compilationUnit = compilationUnit;
+               this.unitIndex = unitIndex;
+               this.totalUnitsKnown = totalUnitsKnown;
+               this.maxProblemPerUnit = maxProblemPerUnit;
+       }
+
+       private int computePriority(IProblem problem){
+       
+               final int P_STATIC = 10000;
+               final int P_OUTSIDE_METHOD = 40000;
+               final int P_FIRST_ERROR = 20000;
+               final int P_ERROR = 100000;
+               
+               int priority = 10000 - problem.getSourceLineNumber(); // early problems first
+               if (priority < 0) priority = 0;
+               if (problem.isError()){
+                       priority += P_ERROR;
+               }
+               ReferenceContext context = problemsMap == null ? null : (ReferenceContext) problemsMap.get(problem);
+               if (context != null){
+                       if (context instanceof AbstractMethodDeclaration){
+                               AbstractMethodDeclaration method = (AbstractMethodDeclaration) context;
+                               if (method.isStatic()) {
+                                       priority += P_STATIC;
+                               }
+                       } else {
+                       priority += P_OUTSIDE_METHOD;
+                       }
+               } else {
+                       priority += P_OUTSIDE_METHOD;
+               }
+               if (firstErrorsMap.containsKey(problem)){
+                       priority += P_FIRST_ERROR;
+               }
+               return priority;
+       }
+
+       
+       public IProblem[] getAllProblems() {
+               IProblem[] onlyProblems = this.getProblems();
+               int onlyProblemCount = onlyProblems != null ? onlyProblems.length : 0;
+               IProblem[] onlyTasks = this.getTasks();
+               int onlyTaskCount = onlyTasks != null ? onlyTasks.length : 0;
+               if (onlyTaskCount == 0) {
+                       return onlyProblems;
+               }
+               if (onlyProblemCount == 0) {
+                       return onlyTasks;
+               }
+
+               int totalNumberOfProblem = onlyProblemCount + onlyTaskCount;
+               IProblem[] allProblems = new IProblem[totalNumberOfProblem];
+               int allProblemIndex = 0;
+               int taskIndex = 0;
+               int problemIndex = 0;
+               while (taskIndex + problemIndex < totalNumberOfProblem) {
+                       IProblem nextTask = null;
+                       IProblem nextProblem = null;
+                       if (taskIndex < onlyTaskCount) {
+                               nextTask = onlyTasks[taskIndex];
+                       }
+                       if (problemIndex < onlyProblemCount) {
+                               nextProblem = onlyProblems[problemIndex];
+                       }
+                       // select the next problem
+                       IProblem currentProblem = null;
+                       if (nextProblem != null) {
+                               if (nextTask != null) {
+                                       if (nextProblem.getSourceStart() < nextTask.getSourceStart()) {
+                                               currentProblem = nextProblem;
+                                               problemIndex++;
+                                       } else {
+                                               currentProblem = nextTask;
+                                               taskIndex++;
+                                       }
+                               } else {
+                                       currentProblem = nextProblem;
+                                       problemIndex++;
+                               }
+                       } else {
+                               if (nextTask != null) {
+                                       currentProblem = nextTask;
+                                       taskIndex++;
+                               }
+                       }
+                       allProblems[allProblemIndex++] = currentProblem;
+               }
+               return allProblems;
+       }
+       
+       public ClassFile[] getClassFiles() {
+               Enumeration files = compiledTypes.elements();
+               ClassFile[] classFiles = new ClassFile[compiledTypes.size()];
+               int index = 0;
+               while (files.hasMoreElements()){
+                       classFiles[index++] = (ClassFile)files.nextElement();
+               }
+               return classFiles;      
+       }
+
+       /**
+        * Answer the initial compilation unit corresponding to the present compilation result
+        */
+       public ICompilationUnit getCompilationUnit(){
+               return compilationUnit;
+       }
+
+       /**
+        * Answer the initial file name
+        */
+       public char[] getFileName(){
+               return fileName;
+       }
+       
+       /**
+        * Answer the errors encountered during compilation.
+        */
+       public IProblem[] getErrors() {
+       
+               IProblem[] reportedProblems = getProblems();
+               int errorCount = 0;
+               for (int i = 0; i < this.problemCount; i++) {
+                       if (reportedProblems[i].isError()) errorCount++;
+               }
+               if (errorCount == this.problemCount) return reportedProblems;
+               IProblem[] errors = new IProblem[errorCount];
+               int index = 0;
+               for (int i = 0; i < this.problemCount; i++) {
+                       if (reportedProblems[i].isError()) errors[index++] = reportedProblems[i];
+               }
+               return errors;
+       }
+       
+       /**
+        * Answer the problems (errors and warnings) encountered during compilation.
+        *
+        * This is not a compiler internal API - it has side-effects !
+        * It is intended to be used only once all problems have been detected,
+        * and makes sure the problems slot as the exact size of the number of
+        * problems.
+        */
+       public IProblem[] getProblems() {
+               
+               // Re-adjust the size of the problems if necessary.
+               if (problems != null) {
+       
+                       if (this.problemCount != problems.length) {
+                               System.arraycopy(problems, 0, (problems = new IProblem[problemCount]), 0, problemCount);
+                       }
+       
+                       if (this.maxProblemPerUnit > 0 && this.problemCount > this.maxProblemPerUnit){
+                               quickPrioritize(problems, 0, problemCount - 1);
+                               this.problemCount = this.maxProblemPerUnit;
+                               System.arraycopy(problems, 0, (problems = new IProblem[problemCount]), 0, problemCount);
+                       }
+       
+                       // Sort problems per source positions.
+                       quickSort(problems, 0, problems.length-1);
+               }
+               return problems;
+       }
+
+       /**
+        * Answer the tasks (TO-DO, ...) encountered during compilation.
+        *
+        * This is not a compiler internal API - it has side-effects !
+        * It is intended to be used only once all problems have been detected,
+        * and makes sure the problems slot as the exact size of the number of
+        * problems.
+        */
+       public IProblem[] getTasks() {
+               
+               // Re-adjust the size of the tasks if necessary.
+               if (this.tasks != null) {
+       
+                       if (this.taskCount != this.tasks.length) {
+                               System.arraycopy(this.tasks, 0, (this.tasks = new IProblem[this.taskCount]), 0, this.taskCount);
+                       }
+                       quickSort(tasks, 0, tasks.length-1);
+               }
+               return this.tasks;
+       }
+       
+       public boolean hasErrors() {
+
+               if (problems != null)
+                       for (int i = 0; i < problemCount; i++) {
+                               if (problems[i].isError())
+                                       return true;
+                       }
+               return false;
+       }
+
+       public boolean hasProblems() {
+
+               return problemCount != 0;
+       }
+
+       public boolean hasSyntaxError(){
+
+               if (problems != null)
+                       for (int i = 0; i < problemCount; i++) {
+                               IProblem problem = problems[i];
+                               if ((problem.getID() & IProblem.Syntax) != 0 && problem.isError())
+                                       return true;
+                       }
+               return false;
+       }
+
+       public boolean hasTasks() {
+               return this.taskCount != 0;
+       }
+       
+       public boolean hasWarnings() {
+
+               if (problems != null)
+                       for (int i = 0; i < problemCount; i++) {
+                               if (problems[i].isWarning())
+                                       return true;
+                       }
+               return false;
+       }
+       
+       private static void quickSort(IProblem[] list, int left, int right) {
+
+               if (left >= right) return;
+       
+               // sort the problems by their source start position... starting with 0
+               int original_left = left;
+               int original_right = right;
+               int mid = list[(left + right) / 2].getSourceStart();
+               do {
+                       while (list[left].getSourceStart() < mid)
+                               left++;
+                       while (mid < list[right].getSourceStart())
+                               right--;
+                       if (left <= right) {
+                               IProblem tmp = list[left];
+                               list[left] = list[right];
+                               list[right] = tmp;
+                               left++;
+                               right--;
+                       }
+               } while (left <= right);
+               if (original_left < right)
+                       quickSort(list, original_left, right);
+               if (left < original_right)
+                       quickSort(list, left, original_right);
+       }
+       
+       private void quickPrioritize(IProblem[] list, int left, int right) {
+               
+               if (left >= right) return;
+       
+               // sort the problems by their priority... starting with the highest priority
+               int original_left = left;
+               int original_right = right;
+               int mid = computePriority(list[(left + right) / 2]);
+               do {
+                       while (computePriority(list[right]) < mid)
+                               right--;
+                       while (mid < computePriority(list[left]))
+                               left++;
+                       if (left <= right) {
+                               IProblem tmp = list[left];
+                               list[left] = list[right];
+                               list[right] = tmp;
+                               left++;
+                               right--;
+                       }
+               } while (left <= right);
+               if (original_left < right)
+                       quickPrioritize(list, original_left, right);
+               if (left < original_right)
+                       quickPrioritize(list, left, original_right);
+       }
+       
+       /**
+        * For now, remember the compiled type using its compound name.
+        */
+       public void record(char[] typeName, ClassFile classFile) {
+
+               compiledTypes.put(typeName, classFile);
+       }
+
+       public void record(IProblem newProblem, ReferenceContext referenceContext) {
+
+               if (newProblem.getID() == IProblem.Task) {
+                       recordTask(newProblem);
+                       return;
+               }
+               if (problemCount == 0) {
+                       problems = new IProblem[5];
+               } else if (problemCount == problems.length) {
+                       System.arraycopy(problems, 0, (problems = new IProblem[problemCount * 2]), 0, problemCount);
+               }
+               problems[problemCount++] = newProblem;
+               if (referenceContext != null){
+                       if (problemsMap == null) problemsMap = new Hashtable(5);
+                       if (firstErrorsMap == null) firstErrorsMap = new Hashtable(5);
+                       if (newProblem.isError() && !referenceContext.hasErrors()) firstErrorsMap.put(newProblem, newProblem);
+                       problemsMap.put(newProblem, referenceContext);
+               }
+       }
+
+       private void recordTask(IProblem newProblem) {
+               if (this.taskCount == 0) {
+                       this.tasks = new IProblem[5];
+               } else if (this.taskCount == this.tasks.length) {
+                       System.arraycopy(this.tasks, 0, (this.tasks = new IProblem[this.taskCount * 2]), 0, this.taskCount);
+               }
+               this.tasks[this.taskCount++] = newProblem;
+       }
+       
+       public CompilationResult tagAsAccepted(){
+
+               this.hasBeenAccepted = true;
+               this.problemsMap = null; // flush
+               return this;
+       }
+       
+       public String toString(){
+
+               StringBuffer buffer = new StringBuffer();
+               if (this.fileName != null){
+                       buffer.append("Filename : ").append(this.fileName).append('\n'); //$NON-NLS-1$
+               }
+               if (this.compiledTypes != null){
+                       buffer.append("COMPILED type(s) \n");  //$NON-NLS-1$
+                       Enumeration typeNames = this.compiledTypes.keys();
+                       while (typeNames.hasMoreElements()) {
+                               char[] typeName = (char[]) typeNames.nextElement();
+                               buffer.append("\t - ").append(typeName).append('\n');   //$NON-NLS-1$
+                               
+                       }
+               } else {
+                       buffer.append("No COMPILED type\n");  //$NON-NLS-1$
+               }
+               if (problems != null){
+                       buffer.append(this.problemCount).append(" PROBLEM(s) detected \n"); //$NON-NLS-1$//$NON-NLS-2$
+                       for (int i = 0; i < this.problemCount; i++){
+                               buffer.append("\t - ").append(this.problems[i]).append('\n'); //$NON-NLS-1$
+                       }
+               } else {
+                       buffer.append("No PROBLEM\n"); //$NON-NLS-1$
+               } 
+               return buffer.toString();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/Compiler.java b/src/java/org/eclipse/jdt/internal/compiler/Compiler.java
new file mode 100644 (file)
index 0000000..92c85dc
--- /dev/null
@@ -0,0 +1,610 @@
+/*******************************************************************************
+ * 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;
+
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.env.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+import org.eclipse.jdt.internal.compiler.util.*;
+
+import java.io.*;
+import java.util.*;
+
+public class Compiler implements ITypeRequestor, ProblemSeverities {
+       public Parser parser;
+       public ICompilerRequestor requestor;
+       public CompilerOptions options;
+       public ProblemReporter problemReporter;
+
+       // management of unit to be processed
+       //public CompilationUnitResult currentCompilationUnitResult;
+       public CompilationUnitDeclaration[] unitsToProcess;
+       public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
+
+       // name lookup
+       public LookupEnvironment lookupEnvironment;
+
+       // ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
+       public static boolean DEBUG = false;
+       public int parseThreshold = -1;
+       // number of initial units parsed at once (-1: none)
+
+       /*
+        * Static requestor reserved to listening compilation results in debug mode,
+        * so as for example to monitor compiler activity independantly from a particular
+        * builder implementation. It is reset at the end of compilation, and should not 
+        * persist any information after having been reset.
+        */
+       public static IDebugRequestor DebugRequestor = null;
+
+       /**
+        * Answer a new compiler using the given name environment and compiler options.
+        * The environment and options will be in effect for the lifetime of the compiler.
+        * When the compiler is run, compilation results are sent to the given requestor.
+        *
+        *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
+        *      Environment used by the compiler in order to resolve type and package
+        *      names. The name environment implements the actual connection of the compiler
+        *      to the outside world (e.g. in batch mode the name environment is performing
+        *      pure file accesses, reuse previous build state or connection to repositories).
+        *      Note: the name environment is responsible for implementing the actual classpath
+        *            rules.
+        *
+        *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
+        *      Configurable part for problem handling, allowing the compiler client to
+        *      specify the rules for handling problems (stop on first error or accumulate
+        *      them all) and at the same time perform some actions such as opening a dialog
+        *      in UI when compiling interactively.
+        *      @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
+        *      
+        *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
+        *      Component which will receive and persist all compilation results and is intended
+        *      to consume them as they are produced. Typically, in a batch compiler, it is 
+        *      responsible for writing out the actual .class files to the file system.
+        *      @see org.eclipse.jdt.internal.compiler.CompilationResult
+        *
+        *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
+        *      Factory used inside the compiler to create problem descriptors. It allows the
+        *      compiler client to supply its own representation of compilation problems in
+        *      order to avoid object conversions. Note that the factory is not supposed
+        *      to accumulate the created problems, the compiler will gather them all and hand
+        *      them back as part of the compilation unit result.
+        */
+       public Compiler(
+               INameEnvironment environment,
+               IErrorHandlingPolicy policy,
+               Map settings,
+               final ICompilerRequestor requestor,
+               IProblemFactory problemFactory) {
+
+               // create a problem handler given a handling policy
+               this.options = new CompilerOptions(settings);
+               
+               // wrap requestor in DebugRequestor if one is specified
+               if(DebugRequestor == null) {
+                       this.requestor = requestor;
+               } else {
+                       this.requestor = new ICompilerRequestor(){
+                               public void acceptResult(CompilationResult result){
+                                       if (DebugRequestor.isActive()){
+                                               DebugRequestor.acceptDebugResult(result);
+                                       }
+                                       requestor.acceptResult(result);
+                               }
+                       };
+               }
+               this.problemReporter =
+                       new ProblemReporter(policy, this.options, problemFactory);
+               this.lookupEnvironment =
+                       new LookupEnvironment(this, options, problemReporter, environment);
+               initializeParser();
+       }
+       
+       /**
+        * Answer a new compiler using the given name environment and compiler options.
+        * The environment and options will be in effect for the lifetime of the compiler.
+        * When the compiler is run, compilation results are sent to the given requestor.
+        *
+        *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
+        *      Environment used by the compiler in order to resolve type and package
+        *      names. The name environment implements the actual connection of the compiler
+        *      to the outside world (e.g. in batch mode the name environment is performing
+        *      pure file accesses, reuse previous build state or connection to repositories).
+        *      Note: the name environment is responsible for implementing the actual classpath
+        *            rules.
+        *
+        *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
+        *      Configurable part for problem handling, allowing the compiler client to
+        *      specify the rules for handling problems (stop on first error or accumulate
+        *      them all) and at the same time perform some actions such as opening a dialog
+        *      in UI when compiling interactively.
+        *      @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
+        *      
+        *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
+        *      Component which will receive and persist all compilation results and is intended
+        *      to consume them as they are produced. Typically, in a batch compiler, it is 
+        *      responsible for writing out the actual .class files to the file system.
+        *      @see org.eclipse.jdt.internal.compiler.CompilationResult
+        *
+        *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
+        *      Factory used inside the compiler to create problem descriptors. It allows the
+        *      compiler client to supply its own representation of compilation problems in
+        *      order to avoid object conversions. Note that the factory is not supposed
+        *      to accumulate the created problems, the compiler will gather them all and hand
+        *      them back as part of the compilation unit result.
+        *      @param parseLiteralExpressionsAsConstants <code>boolean</code>
+        *              This parameter is used to optimize the literals or leave them as they are in the source.
+        *              If you put true, "Hello" + " world" will be converted to "Hello world".
+        */
+       public Compiler(
+               INameEnvironment environment,
+               IErrorHandlingPolicy policy,
+               Map settings,
+               final ICompilerRequestor requestor,
+               IProblemFactory problemFactory,
+               boolean parseLiteralExpressionsAsConstants) {
+
+               // create a problem handler given a handling policy
+               this.options = new CompilerOptions(settings);
+               
+               // wrap requestor in DebugRequestor if one is specified
+               if(DebugRequestor == null) {
+                       this.requestor = requestor;
+               } else {
+                       this.requestor = new ICompilerRequestor(){
+                               public void acceptResult(CompilationResult result){
+                                       if (DebugRequestor.isActive()){
+                                               DebugRequestor.acceptDebugResult(result);
+                                       }
+                                       requestor.acceptResult(result);
+                               }
+                       };
+               }
+               this.problemReporter = new ProblemReporter(policy, this.options, problemFactory);
+               this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, environment);
+               initializeParser();
+       }
+       
+       /**
+        * Add an additional binary type
+        */
+       public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+               if (options.verbose) {
+                       System.out.println(
+                               Util.bind(
+                                       "compilation.loadBinary" , //$NON-NLS-1$
+                                       new String[] {
+                                               new String(binaryType.getName())}));
+//                     new Exception("TRACE BINARY").printStackTrace(System.out);
+//                 System.out.println();
+               }
+               lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+       }
+
+       /**
+        * Add an additional compilation unit into the loop
+        *  ->  build compilation unit declarations, their bindings and record their results.
+        */
+       public void accept(ICompilationUnit sourceUnit) {
+               // Switch the current policy and compilation result for this unit to the requested one.
+               CompilationResult unitResult =
+                       new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
+               try {
+                       if (options.verbose) {
+                               String count = String.valueOf(totalUnits + 1);
+                               System.out.println(
+                                       Util.bind(
+                                               "compilation.request" , //$NON-NLS-1$
+                                               new String[] {
+                                                       count,
+                                                       count,
+                                                       new String(sourceUnit.getFileName())}));
+                       }
+                       // diet parsing for large collection of unit
+                       CompilationUnitDeclaration parsedUnit;
+                       if (totalUnits < parseThreshold) {
+                               parsedUnit = parser.parse(sourceUnit, unitResult);
+                       } else {
+                               parsedUnit = parser.dietParse(sourceUnit, unitResult);
+                       }
+                       // initial type binding creation
+                       lookupEnvironment.buildTypeBindings(parsedUnit);
+                       this.addCompilationUnit(sourceUnit, parsedUnit);
+
+                       // binding resolution
+                       lookupEnvironment.completeTypeBindings(parsedUnit);
+               } catch (AbortCompilationUnit e) {
+                       // at this point, currentCompilationUnitResult may not be sourceUnit, but some other
+                       // one requested further along to resolve sourceUnit.
+                       if (unitResult.compilationUnit == sourceUnit) { // only report once
+                               requestor.acceptResult(unitResult.tagAsAccepted());
+                       } else {
+                               throw e; // want to abort enclosing request to compile
+                       }
+               }
+       }
+
+       /**
+        * Add additional source types
+        */
+       public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
+               problemReporter.abortDueToInternalError(
+                       Util.bind(
+                               "abort.againstSourceModel" , //$NON-NLS-1$
+                               String.valueOf(sourceTypes[0].getName()),
+                               String.valueOf(sourceTypes[0].getFileName())));
+       }
+
+       protected void addCompilationUnit(
+               ICompilationUnit sourceUnit,
+               CompilationUnitDeclaration parsedUnit) {
+
+               // append the unit to the list of ones to process later on
+               int size = unitsToProcess.length;
+               if (totalUnits == size)
+                       // when growing reposition units starting at position 0
+                       System.arraycopy(
+                               unitsToProcess,
+                               0,
+                               (unitsToProcess = new CompilationUnitDeclaration[size * 2]),
+                               0,
+                               totalUnits);
+               unitsToProcess[totalUnits++] = parsedUnit;
+       }
+
+       /**
+        * Add the initial set of compilation units into the loop
+        *  ->  build compilation unit declarations, their bindings and record their results.
+        */
+       protected void beginToCompile(ICompilationUnit[] sourceUnits) {
+               int maxUnits = sourceUnits.length;
+               totalUnits = 0;
+               unitsToProcess = new CompilationUnitDeclaration[maxUnits];
+
+               // Switch the current policy and compilation result for this unit to the requested one.
+               for (int i = 0; i < maxUnits; i++) {
+                       CompilationUnitDeclaration parsedUnit;
+                       CompilationResult unitResult =
+                               new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit);
+                       try {
+                               if (options.verbose) {
+                                       System.out.println(
+                                               Util.bind(
+                                                       "compilation.request" , //$NON-NLS-1$
+                                                       new String[] {
+                                                               String.valueOf(i + 1),
+                                                               String.valueOf(maxUnits),
+                                                               new String(sourceUnits[i].getFileName())}));
+                               }
+                               // diet parsing for large collection of units
+                               if (totalUnits < parseThreshold) {
+                                       parsedUnit = parser.parse(sourceUnits[i], unitResult);
+                               } else {
+                                       parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
+                               }
+                               // initial type binding creation
+                               lookupEnvironment.buildTypeBindings(parsedUnit);
+                               this.addCompilationUnit(sourceUnits[i], parsedUnit);
+                               //} catch (AbortCompilationUnit e) {
+                               //      requestor.acceptResult(unitResult.tagAsAccepted());
+                       } finally {
+                               sourceUnits[i] = null; // no longer hold onto the unit
+                       }
+               }
+               // binding resolution
+               lookupEnvironment.completeTypeBindings();
+       }
+
+       /**
+        * General API
+        * -> compile each of supplied files
+        * -> recompile any required types for which we have an incomplete principle structure
+        */
+       public void compile(ICompilationUnit[] sourceUnits) {
+               CompilationUnitDeclaration unit = null;
+               int i = 0;
+               try {
+                       // build and record parsed units
+
+                       beginToCompile(sourceUnits);
+
+                       // process all units (some more could be injected in the loop by the lookup environment)
+                       for (; i < totalUnits; i++) {
+                               unit = unitsToProcess[i];
+                               try {
+                                       if (options.verbose)
+                                               System.out.println(
+                                                       Util.bind(
+                                                               "compilation.process" , //$NON-NLS-1$
+                                                               new String[] {
+                                                                       String.valueOf(i + 1),
+                                                                       String.valueOf(totalUnits),
+                                                                       new String(unitsToProcess[i].getFileName())}));
+                                       process(unit, i);
+                               } finally {
+                                       // cleanup compilation unit result
+                                       unit.cleanUp();
+                               }
+                               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())}));
+                       }
+               } catch (AbortCompilation e) {
+                       this.handleInternalException(e, unit);
+               } catch (Error e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } catch (RuntimeException e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } finally {
+                       this.reset();
+               }
+               if (options.verbose) {
+                       if (totalUnits > 1) {
+                               System.out.println(
+                                       Util.bind("compilation.units" , String.valueOf(totalUnits))); //$NON-NLS-1$
+                       } else {
+                               System.out.println(
+                                       Util.bind("compilation.unit" , String.valueOf(totalUnits))); //$NON-NLS-1$
+                       }
+               }
+       }
+
+       /*
+        * Compiler crash recovery in case of unexpected runtime exceptions
+        */
+       protected void handleInternalException(
+               Throwable internalException,
+               CompilationUnitDeclaration unit,
+               CompilationResult result) {
+
+               /* find a compilation result */
+               if ((unit != null)) // basing result upon the current unit if available
+                       result = unit.compilationResult; // current unit being processed ?
+               if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
+                       result = unitsToProcess[totalUnits - 1].compilationResult;
+               // last unit in beginToCompile ?
+
+               boolean needToPrint = true;
+               if (result != null) {
+                       /* create and record a compilation problem */
+                       StringWriter stringWriter = new StringWriter();
+                       PrintWriter writer = new PrintWriter(stringWriter);
+                       internalException.printStackTrace(writer);
+                       StringBuffer buffer = stringWriter.getBuffer();
+
+                       String[] pbArguments = new String[] {
+                               Util.bind("compilation.internalError" ) //$NON-NLS-1$
+                                       + "\n"  //$NON-NLS-1$
+                                       + buffer.toString()};
+
+                       result
+                               .record(
+                                       problemReporter
+                                       .createProblem(
+                                               result.getFileName(),
+                                               IProblem.Unclassified,
+                                               pbArguments,
+                                               pbArguments,
+                                               Error, // severity
+                                               0, // source start
+                                               0, // source end
+                                               0), // line number              
+                                       unit);
+
+                       /* hand back the compilation result */
+                       if (!result.hasBeenAccepted) {
+                               requestor.acceptResult(result.tagAsAccepted());
+                               needToPrint = false;
+                       }
+               }
+               if (needToPrint) {
+                       /* dump a stack trace to the console */
+                       internalException.printStackTrace();
+               }
+       }
+
+       /*
+        * Compiler recovery in case of internal AbortCompilation event
+        */
+       protected void handleInternalException(
+               AbortCompilation abortException,
+               CompilationUnitDeclaration unit) {
+
+               /* special treatment for SilentAbort: silently cancelling the compilation process */
+               if (abortException.isSilent) {
+                       if (abortException.silentException == null) {
+                               return;
+                       }
+                       throw abortException.silentException;
+               }
+
+               /* uncomment following line to see where the abort came from */
+               // abortException.printStackTrace(); 
+
+               // Exception may tell which compilation result it is related, and which problem caused it
+               CompilationResult result = abortException.compilationResult;
+               if ((result == null) && (unit != null)) {
+                       result = unit.compilationResult; // current unit being processed ?
+               }
+               // Lookup environment may be in middle of connecting types
+               if ((result == null) && lookupEnvironment.unitBeingCompleted != null) {
+                   result = lookupEnvironment.unitBeingCompleted.compilationResult;
+               }
+               if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
+                       result = unitsToProcess[totalUnits - 1].compilationResult;
+               // last unit in beginToCompile ?
+               if (result != null && !result.hasBeenAccepted) {
+                       /* distant problem which could not be reported back there? */
+                       if (abortException.problem != null) {
+                               recordDistantProblem: {
+                                       IProblem distantProblem = abortException.problem;
+                                       IProblem[] knownProblems = result.problems;
+                                       for (int i = 0; i < result.problemCount; i++) {
+                                               if (knownProblems[i] == distantProblem) { // already recorded
+                                                       break recordDistantProblem;
+                                               }
+                                       }
+                                       if (distantProblem instanceof DefaultProblem) { // fixup filename TODO (philippe) should improve API to make this official
+                                               ((DefaultProblem) distantProblem).setOriginatingFileName(result.getFileName());
+                                       }
+                                       result  .record(distantProblem, unit);
+                               }
+                       } else {
+                               /* distant internal exception which could not be reported back there */
+                               if (abortException.exception != null) {
+                                       this.handleInternalException(abortException.exception, null, result);
+                                       return;
+                               }
+                       }
+                       /* hand back the compilation result */
+                       if (!result.hasBeenAccepted) {
+                               requestor.acceptResult(result.tagAsAccepted());
+                       }
+               } else {
+                       abortException.printStackTrace();
+               }
+       }
+
+       public void initializeParser() {
+
+               this.parser = new Parser(this.problemReporter, this.options.parseLiteralExpressionsAsConstants);
+       }
+       
+       /**
+        * Process a compilation unit already parsed and build.
+        */
+       public void process(CompilationUnitDeclaration unit, int i) {
+
+               this.parser.getMethodBodies(unit);
+
+               // fault in fields & methods
+               if (unit.scope != null)
+                       unit.scope.faultInTypes();
+
+               // verify inherited methods
+               if (unit.scope != null)
+                       unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+
+               // type checking
+               unit.resolve();
+
+               // flow analysis
+               unit.analyseCode();
+
+               // code generation
+               unit.generateCode();
+
+               // reference info
+               if (options.produceReferenceInfo && unit.scope != null)
+                       unit.scope.storeDependencyInfo();
+
+               // refresh the total number of units known at this stage
+               unit.compilationResult.totalUnitsKnown = totalUnits;
+       }
+       public void reset() {
+               lookupEnvironment.reset();
+               parser.scanner.source = null;
+               unitsToProcess = null;
+               if (DebugRequestor != null) DebugRequestor.reset();
+       }
+
+       /**
+        * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+        */
+       public CompilationUnitDeclaration resolve(
+                       CompilationUnitDeclaration unit, 
+                       ICompilationUnit sourceUnit, 
+                       boolean verifyMethods,
+                       boolean analyzeCode,
+                       boolean generateCode) {
+                               
+               try {
+                       if (unit == null) {
+                               // build and record parsed units
+                               parseThreshold = 0; // will request a full parse
+                               beginToCompile(new ICompilationUnit[] { sourceUnit });
+                               // process all units (some more could be injected in the loop by the lookup environment)
+                               unit = unitsToProcess[0];
+                       } else {
+                               // initial type binding creation
+                               lookupEnvironment.buildTypeBindings(unit);
+
+                               // binding resolution
+                               lookupEnvironment.completeTypeBindings();
+                       }
+                       this.parser.getMethodBodies(unit);
+                       if (unit.scope != null) {
+                               // fault in fields & methods
+                               unit.scope.faultInTypes();
+                               if (unit.scope != null && verifyMethods) {
+                                       // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
+                                       // verify inherited methods
+                                       unit.scope.verifyMethods(lookupEnvironment.methodVerifier());
+                               }
+                               // type checking
+                               unit.resolve();         
+
+                               // flow analysis
+                               if (analyzeCode) unit.analyseCode();
+               
+                               // code generation
+                               if (generateCode) unit.generateCode();
+                       }
+                       if (unitsToProcess != null) unitsToProcess[0] = null; // release reference to processed unit declaration
+                       requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+                       return unit;
+               } catch (AbortCompilation e) {
+                       this.handleInternalException(e, unit);
+                       return unit == null ? unitsToProcess[0] : unit;
+               } catch (Error e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } catch (RuntimeException e) {
+                       this.handleInternalException(e, unit, null);
+                       throw e; // rethrow
+               } finally {
+                       // No reset is performed there anymore since,
+                       // within the CodeAssist (or related tools),
+                       // the compiler may be called *after* a call
+                       // to this resolve(...) method. And such a call
+                       // needs to have a compiler with a non-empty
+                       // environment.
+                       // this.reset();
+               }
+       }
+       /**
+        * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
+        */
+       public CompilationUnitDeclaration resolve(
+                       ICompilationUnit sourceUnit, 
+                       boolean verifyMethods,
+                       boolean analyzeCode,
+                       boolean generateCode) {
+                               
+               return resolve(
+                       null,
+                       sourceUnit,
+                       verifyMethods,
+                       analyzeCode,
+                       generateCode);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ConfigurableOption.java b/src/java/org/eclipse/jdt/internal/compiler/ConfigurableOption.java
new file mode 100644 (file)
index 0000000..13e2858
--- /dev/null
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * 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;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java b/src/java/org/eclipse/jdt/internal/compiler/DefaultErrorHandlingPolicies.java
new file mode 100644 (file)
index 0000000..5036df6
--- /dev/null
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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;
+
+public class DefaultErrorHandlingPolicies {
+/*
+ * Accumulate all problems, then exit without proceeding.
+ *
+ * Typically, the #proceedWithProblems(Problem[]) should
+ * show the problems.
+ *
+ */
+public static IErrorHandlingPolicy exitAfterAllProblems() {
+       return new IErrorHandlingPolicy() {
+               public boolean stopOnFirstError() {
+                       return false;
+               }
+               public boolean proceedOnErrors(){
+                       return false;
+               }
+       };
+}
+/*
+ * Exit without proceeding on the first problem wich appears
+ * to be an error.
+ *
+ */
+public static IErrorHandlingPolicy exitOnFirstError() {
+       return new IErrorHandlingPolicy() {
+               public boolean stopOnFirstError() {
+                       return true;
+               }
+               public boolean proceedOnErrors(){
+                       return false;
+               }
+       };
+}
+/*
+ * Proceed on the first error met.
+ *
+ */
+public static IErrorHandlingPolicy proceedOnFirstError() {
+       return new IErrorHandlingPolicy() {
+               public boolean stopOnFirstError() {
+                       return true;
+               }
+               public boolean proceedOnErrors(){
+                       return true;
+               }
+       };
+}
+/*
+ * Accumulate all problems, then proceed with them.
+ *
+ */
+public static IErrorHandlingPolicy proceedWithAllProblems() {
+       return new IErrorHandlingPolicy() {
+               public boolean stopOnFirstError() {
+                       return false;
+               }
+               public boolean proceedOnErrors(){
+                       return true;
+               }
+       };
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java b/src/java/org/eclipse/jdt/internal/compiler/ICompilerRequestor.java
new file mode 100644 (file)
index 0000000..0d8d039
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * A callback interface for receiving compilation results.
+ */
+public interface ICompilerRequestor {
+       
+       /**
+        * Accept a compilation result.
+        */
+       public void acceptResult(CompilationResult result);
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/IDebugRequestor.java b/src/java/org/eclipse/jdt/internal/compiler/IDebugRequestor.java
new file mode 100644 (file)
index 0000000..31570e3
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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;
+
+public interface IDebugRequestor {
+
+       /*
+        * Debug callback method allowing to take into account a new compilation result.
+        * Any side-effect performed on the actual result might interfere with the
+        * original compiler requestor, and should be prohibited.
+        */
+       void acceptDebugResult(CompilationResult result);
+
+       /*
+        * Answers true when in active mode
+        */
+       boolean isActive();
+       
+       /* 
+        * Activate debug callbacks
+        */     
+       void activate();
+
+       /* 
+        * Deactivate debug callbacks
+        */     
+       void deactivate();
+       
+       /*
+        * Reset debug requestor after compilation has finished
+        */
+       void reset();
+}
+
diff --git a/src/java/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java b/src/java/org/eclipse/jdt/internal/compiler/IErrorHandlingPolicy.java
new file mode 100644 (file)
index 0000000..a585e9f
--- /dev/null
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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;
+
+/*
+ * Handler policy is responsible to answer the 2 following
+ * questions:
+ * 1. should the handler stop on first problem which appears
+ *     to be a real error (that is, not a warning),
+ * 2. should it proceed once it has gathered all problems
+ *
+ * The intent is that one can supply its own policy to implement 
+ * some interactive error handling strategy where some UI would 
+ * display problems and ask user if he wants to proceed or not.
+ */
+
+public interface IErrorHandlingPolicy {
+       boolean proceedOnErrors();
+       boolean stopOnFirstError();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/IProblemFactory.java b/src/java/org/eclipse/jdt/internal/compiler/IProblemFactory.java
new file mode 100644 (file)
index 0000000..f5e8d1b
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.Locale;
+
+import org.eclipse.jdt.core.compiler.*;
+
+/*
+ * Factory used from inside the compiler to build the actual problems
+ * which are handed back in the compilation result.
+ *
+ * This allows sharing the internal problem representation with the environment.
+ *
+ * Note: The factory is responsible for computing and storing a localized error message.
+ */
+
+public interface IProblemFactory {
+
+       IProblem createProblem(
+               char[] originatingFileName,
+               int problemId,
+               String[] problemArguments,
+               String[] messageArguments, // shorter versions of the problemArguments
+               int severity,
+               int startPosition,
+               int endPosition,
+               int lineNumber);
+               
+       Locale getLocale();
+       
+       String getLocalizedMessage(int problemId, String[] messageArguments);
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
new file mode 100644 (file)
index 0000000..a8db03f
--- /dev/null
@@ -0,0 +1,269 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+//dedicated treatment for the &&
+public class AND_AND_Expression extends BinaryExpression {
+
+       int rightInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+
+       public AND_AND_Expression(Expression left, Expression right, int operator) {
+               super(left, right, operator);
+       }
+
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+               Constant cst = this.left.optimizedBooleanConstant();
+               boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isLeftOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+
+               if (isLeftOptimizedTrue) {
+                       // TRUE && anything
+                       // need to be careful of scenario:
+                       //  (x && y) && !z, if passing the left info to the right, it would
+                       // be swapped by the !
+                       FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo)
+                                       .unconditionalInits();
+                       mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
+                       mergedInitStateIndex = currentScope.methodScope()
+                                       .recordInitializationStates(mergedInfo);
+                       return mergedInfo;
+               }
+
+               FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
+               // need to be careful of scenario:
+               //  (x && y) && !z, if passing the left info to the right, it would be
+               // swapped by the !
+               FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalInits().copy();
+               rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo);
+
+               int previousMode = rightInfo.reachMode();
+               if (isLeftOptimizedFalse) {
+                       rightInfo.setReachMode(FlowInfo.UNREACHABLE);
+               }
+               rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
+               FlowInfo trueMergedInfo = rightInfo.initsWhenTrue().copy();
+               rightInfo.setReachMode(previousMode); // reset after trueMergedInfo got extracted
+               FlowInfo mergedInfo = FlowInfo.conditional(
+                               trueMergedInfo, 
+                               leftInfo.initsWhenFalse().copy().unconditionalInits().mergedWith(
+                                               rightInfo.initsWhenFalse().copy().unconditionalInits()));
+               mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+               return mergedInfo;
+       }
+
+       /**
+        * Code generation for a binary operation
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+               int pc = codeStream.position;
+               if (constant != Constant.NotAConstant) {
+                       // inlined value
+                       if (valueRequired)
+                               codeStream.generateConstant(constant, implicitConversion);
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               Constant cst = right.constant;
+               if (cst != NotAConstant) {
+                       // <expr> && true --> <expr>
+                       if (cst.booleanValue() == true) {
+                               this.left.generateCode(currentScope, codeStream, valueRequired);
+                       } else {
+                               // <expr> && false --> false
+                               this.left.generateCode(currentScope, codeStream, false);
+                               if (valueRequired) codeStream.iconst_0();
+                       }
+                       if (mergedInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       }                       
+                       codeStream.generateImplicitConversion(implicitConversion);
+                       codeStream.updateLastRecordedEndPC(codeStream.position);
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               
+               Label falseLabel = new Label(codeStream), endLabel;
+               cst = left.optimizedBooleanConstant();
+               boolean leftIsConst = cst != NotAConstant;
+               boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
+
+               cst = right.optimizedBooleanConstant();
+               boolean rightIsConst = cst != NotAConstant;
+               boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
+               generateOperands : {
+                       if (leftIsConst) {
+                               left.generateCode(currentScope, codeStream, false);
+                               if (!leftIsTrue) {
+                                       break generateOperands; // no need to generate right operand
+                               }
+                       } else {
+                               left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true); 
+                               // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1 
+                       }
+                       if (rightInitStateIndex != -1) {
+                               codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+                       }
+                       if (rightIsConst) {
+                               right.generateCode(currentScope, codeStream, false);
+                       } else {
+                               right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
+                       }
+               }
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+               /*
+                * improving code gen for such a case: boolean b = i < 0 && false since
+                * the label has never been used, we have the inlined value on the
+                * stack.
+                */
+               if (valueRequired) {
+                       if (leftIsConst && !leftIsTrue) {
+                               codeStream.iconst_0();
+                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                       } else {
+                               if (rightIsConst && !rightIsTrue) {
+                                       codeStream.iconst_0();
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);
+                               } else {
+                                       codeStream.iconst_1();
+                               }
+                               if (falseLabel.hasForwardReferences()) {
+                                       if ((bits & ValueForReturnMASK) != 0) {
+                                               codeStream.ireturn();
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                       } else {
+                                               codeStream.goto_(endLabel = new Label(codeStream));
+                                               codeStream.decrStackSize(1);
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                               endLabel.place();
+                                       }
+                               } else {
+                                       falseLabel.place();
+                               }
+                       }
+                       codeStream.generateImplicitConversion(implicitConversion);
+                       codeStream.updateLastRecordedEndPC(codeStream.position);
+               } else {
+                       falseLabel.place();
+               }
+       }
+
+       /**
+        * Boolean operator code generation Optimized operations are: &&
+        */
+       public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream,
+                       Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+               if (constant != Constant.NotAConstant) {
+                       super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel,
+                                       valueRequired);
+                       return;
+               }
+
+               // <expr> && true --> <expr>
+               Constant cst = right.constant;
+               if (cst != NotAConstant && cst.booleanValue() == true) {
+                       int pc = codeStream.position;
+                       this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+                       if (mergedInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       }                       
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               cst = left.optimizedBooleanConstant();
+               boolean leftIsConst = cst != NotAConstant;
+               boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
+
+               cst = right.optimizedBooleanConstant();
+               boolean rightIsConst = cst != NotAConstant;
+               boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
+               // default case
+               generateOperands : {
+                       if (falseLabel == null) {
+                               if (trueLabel != null) {
+                                       // implicit falling through the FALSE case
+                                       Label internalFalseLabel = new Label(codeStream);
+                                       left.generateOptimizedBoolean(currentScope, codeStream, null,
+                                                       internalFalseLabel, !leftIsConst); 
+                                       // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1
+                                       if (leftIsConst && !leftIsTrue) {
+                                               internalFalseLabel.place();
+                                               break generateOperands; // no need to generate right operand
+                                       }
+                                       if (rightInitStateIndex != -1) {
+                                               codeStream
+                                                               .addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+                                       }
+                                       right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null,
+                                                       valueRequired && !rightIsConst);
+                                       if (valueRequired && rightIsConst && rightIsTrue) {
+                                               codeStream.goto_(trueLabel);
+                                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                                       }
+                                       internalFalseLabel.place();
+                               }
+                       } else {
+                               // implicit falling through the TRUE case
+                               if (trueLabel == null) {
+                                       left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, !leftIsConst); 
+                                       // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1
+                                       if (leftIsConst && !leftIsTrue) {
+                                               codeStream.goto_(falseLabel);
+                                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                                               break generateOperands; // no need to generate right operand
+                                       }
+                                       if (rightInitStateIndex != -1) {
+                                               codeStream
+                                                               .addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+                                       }
+                                       right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel,
+                                                       valueRequired && !rightIsConst);
+                                       if (valueRequired && rightIsConst && !rightIsTrue) {
+                                               codeStream.goto_(falseLabel);
+                                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                                       }
+                               } else {
+                                       // no implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+       }
+
+       public boolean isCompactableOperation() {
+               return false;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               if (visitor.visit(this, scope)) {
+                       left.traverse(visitor, scope);
+                       right.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
\ No newline at end of file
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
new file mode 100644 (file)
index 0000000..74ba90b
--- /dev/null
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+
+public abstract class ASTNode implements BaseTypes, CompilerModifiers, TypeConstants, TypeIds {
+       
+       public int sourceStart, sourceEnd;
+
+       //some global provision for the hierarchy
+       public final static Constant NotAConstant = Constant.NotAConstant;
+
+       // storage for internal flags (32 bits)                                         BIT USAGE
+       public final static int Bit1 = 0x1;                                             // return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement)
+       public final static int Bit2 = 0x2;                                             // return type (operator) | name reference kind (name ref) | has local type (type, method, field decl)
+       public final static int Bit3 = 0x4;                                             // return type (operator) | name reference kind (name ref) | implicit this (this ref)
+       public final static int Bit4 = 0x8;                                             // return type (operator) | first assignment to local (local decl) | undocumented empty block (block, type and method decl)
+       public final static int Bit5 = 0x10;                                            // value for return (expression) | has all method bodies (unit)
+       public final static int Bit6 = 0x20;                                            // depth (name ref, msg) | only value required (binary expression) | ignore need cast check (cast expression)
+       public final static int Bit7 = 0x40;                                            // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression)
+       public final static int Bit8 = 0x80;                                            // depth (name ref, msg) | operator (operator) 
+       public final static int Bit9 = 0x100;                                   // depth (name ref, msg) | operator (operator) | is local type (type decl)
+       public final static int Bit10= 0x200;                                   // depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
+       public final static int Bit11 = 0x400;                                  // depth (name ref, msg) | operator (operator) | is member type (type decl)
+       public final static int Bit12 = 0x800;                                  // depth (name ref, msg) | operator (operator)
+       public final static int Bit13 = 0x1000;                                 // depth (name ref, msg) 
+       public final static int Bit14 = 0x2000;                                 // strictly assigned (reference lhs)
+       public final static int Bit15 = 0x4000;                                 // is unnecessary cast (expression)
+       public final static int Bit16 = 0x8000;                                 // in javadoc comment (name ref, type ref, msg)
+       public final static int Bit17 = 0x10000;                                // compound assigned (reference lhs)
+       public final static int Bit18 = 0x20000; 
+       public final static int Bit19 = 0x40000; 
+       public final static int Bit20 = 0x80000; 
+       public final static int Bit21 = 0x100000;               
+       public final static int Bit22 = 0x200000;                       // parenthesis count (expression)
+       public final static int Bit23 = 0x400000;                       // parenthesis count (expression)
+       public final static int Bit24 = 0x800000;                       // parenthesis count (expression)
+       public final static int Bit25 = 0x1000000;                      // parenthesis count (expression)
+       public final static int Bit26 = 0x2000000;                      // parenthesis count (expression)
+       public final static int Bit27 = 0x4000000;                      // parenthesis count (expression)
+       public final static int Bit28 = 0x8000000;                      // parenthesis count (expression)
+       public final static int Bit29 = 0x10000000;             // parenthesis count (expression)
+       public final static int Bit30 = 0x20000000;             // assignment with no effect (assignment) | elseif (if statement)
+       public final static int Bit31 = 0x40000000;             // local declaration reachable (local decl)
+       public final static int Bit32 = 0x80000000;             // reachable (statement)
+
+       public final static long Bit32L = 0x80000000L;          
+       public final static long Bit33L = 0x100000000L;
+       public final static long Bit34L = 0x200000000L;
+       public final static long Bit35L = 0x400000000L;
+       public final static long Bit36L = 0x800000000L;
+       public final static long Bit37L = 0x1000000000L;
+       public final static long Bit38L = 0x2000000000L;
+       public final static long Bit39L = 0x4000000000L;
+       public final static long Bit40L = 0x8000000000L;
+
+       public int bits = IsReachableMASK;                              // reachable by default
+
+       // for operators 
+       public static final int ReturnTypeIDMASK = Bit1|Bit2|Bit3|Bit4; 
+       public static final int OperatorSHIFT = 6;      // Bit7 -> Bit12
+       public static final int OperatorMASK = Bit7|Bit8|Bit9|Bit10|Bit11|Bit12; // 6 bits for operator ID
+
+       // for binary expressions
+       public static final int ValueForReturnMASK = Bit5; 
+       public static final int OnlyValueRequiredMASK = Bit6; 
+
+       // for cast expressions
+       public static final int UnnecessaryCastMask = Bit15;
+       public static final int NeedRuntimeCheckCastMASK = Bit7;
+       public static final int IgnoreNeedForCastCheckMASK = Bit6;
+       
+       // for name references 
+       public static final int RestrictiveFlagMASK = Bit1|Bit2|Bit3;   
+       public static final int FirstAssignmentToLocalMASK = Bit4;
+       
+       // for this reference
+       public static final int IsImplicitThisMask = Bit3; 
+
+       // for single name references
+       public static final int DepthSHIFT = 5; // Bit6 -> Bit13
+       public static final int DepthMASK = Bit6|Bit7|Bit8|Bit9|Bit10|Bit11|Bit12|Bit13; // 8 bits for actual depth value (max. 255)
+
+       // for statements 
+       public static final int IsReachableMASK = Bit32; 
+       public static final int IsLocalDeclarationReachableMASK = Bit31; 
+
+       // for type declaration
+       public static final int AddAssertionMASK = Bit1;
+       public static final int IsLocalTypeMASK = Bit9;
+       public static final int IsAnonymousTypeMASK = Bit10; // used to test for anonymous 
+       public static final int AnonymousAndLocalMask = IsAnonymousTypeMASK | IsLocalTypeMASK; // used to set anonymous marker
+       public static final int IsMemberTypeMASK = Bit11; // local member do not know it is local at parse time (need to look at binding)
+       
+       // for type, method and field declarations 
+       public static final int HasLocalTypeMASK = Bit2; // cannot conflict with AddAssertionMASK
+
+       // for expression 
+       public static final int ParenthesizedSHIFT = 21; // Bit22 -> Bit29
+       public static final int ParenthesizedMASK = Bit22|Bit23|Bit24|Bit25|Bit26|Bit27|Bit28|Bit29; // 8 bits for parenthesis count value (max. 255)
+
+       // for assignment
+       public static final int IsAssignmentWithNoEffectMASK = Bit30;   
+       
+       // for references on lhs of assignment
+       public static final int IsStrictlyAssignedMASK = Bit14; // set only for true assignments, as opposed to compound ones
+       public static final int IsCompoundAssignedMASK = Bit17; // set only for compound assignments, as opposed to other ones
+
+       // for empty statement
+       public static final int IsUsefulEmptyStatementMASK = Bit1;
+
+       // for block and method declaration
+       public static final int UndocumentedEmptyBlockMASK = Bit4;
+
+       // for compilation unit
+       public static final int HasAllMethodBodies = Bit5;
+       
+       // for references in Javadoc comments
+       public static final int InsideJavadoc = Bit16;
+       
+       // for if statement
+       public static final int IsElseIfStatement = Bit30;
+       
+       public ASTNode() {
+
+               super();
+       }
+
+       public ASTNode concreteStatement() {
+               return this;
+       }
+
+       /* Answer true if the field use is considered deprecated.
+       * An access in the same compilation unit is allowed.
+       */
+       public final boolean isFieldUseDeprecated(FieldBinding field, Scope scope, boolean isStrictlyAssigned) {
+
+               if (!isStrictlyAssigned && field.isPrivate() && !scope.isDefinedInField(field)) {
+                       // ignore cases where field is used from within inside itself 
+                       field.modifiers |= AccPrivateUsed;
+               }
+
+               if (!field.isViewedAsDeprecated()) return false;
+
+               // inside same unit - no report
+               if (scope.isDefinedInSameUnit(field.declaringClass)) return false;
+               
+               // if context is deprecated, may avoid reporting
+               if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
+               return true;
+       }
+
+       public boolean isImplicitThis() {
+               
+               return false;
+       }
+       
+       /* Answer true if the method use is considered deprecated.
+       * An access in the same compilation unit is allowed.
+       */
+       public final boolean isMethodUseDeprecated(MethodBinding method, Scope scope) {
+
+               if (method.isPrivate() && !scope.isDefinedInMethod(method)) {
+                       // ignore cases where method is used from within inside itself (e.g. direct recursions)
+                       method.modifiers |= AccPrivateUsed;
+               }
+               
+               if (!method.isViewedAsDeprecated()) return false;
+
+               // inside same unit - no report
+               if (scope.isDefinedInSameUnit(method.declaringClass)) return false;
+               
+               // if context is deprecated, may avoid reporting
+               if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
+               return true;
+       }
+
+       public boolean isSuper() {
+
+               return false;
+       }
+
+       public boolean isThis() {
+
+               return false;
+       }
+
+       /* Answer true if the type use is considered deprecated.
+       * An access in the same compilation unit is allowed.
+       */
+       public final boolean isTypeUseDeprecated(TypeBinding type, Scope scope) {
+
+               if (type.isArrayType())
+                       type = ((ArrayBinding) type).leafComponentType;
+               if (type.isBaseType())
+                       return false;
+
+               ReferenceBinding refType = (ReferenceBinding) type;
+
+               if (refType.isPrivate() && !scope.isDefinedInType(refType)) {
+                       // ignore cases where type is used from within inside itself 
+                       refType.modifiers |= AccPrivateUsed;
+               }
+
+               if (!refType.isViewedAsDeprecated()) return false;
+               
+               // inside same unit - no report
+               if (scope.isDefinedInSameUnit(refType)) return false;
+               
+               // if context is deprecated, may avoid reporting
+               if (!scope.environment().options.reportDeprecationInsideDeprecatedCode && scope.isInsideDeprecatedCode()) return false;
+               return true;
+       }
+
+       public abstract StringBuffer print(int indent, StringBuffer output);
+
+       public static StringBuffer printIndent(int indent, StringBuffer output) {
+
+               for (int i = indent; i > 0; i--) output.append("  "); //$NON-NLS-1$
+               return output;
+       }
+
+       public static StringBuffer printModifiers(int modifiers, StringBuffer output) {
+
+               if ((modifiers & AccPublic) != 0)
+                       output.append("public "); //$NON-NLS-1$
+               if ((modifiers & AccPrivate) != 0)
+                       output.append("private "); //$NON-NLS-1$
+               if ((modifiers & AccProtected) != 0)
+                       output.append("protected "); //$NON-NLS-1$
+               if ((modifiers & AccStatic) != 0)
+                       output.append("static "); //$NON-NLS-1$
+               if ((modifiers & AccFinal) != 0)
+                       output.append("final "); //$NON-NLS-1$
+               if ((modifiers & AccSynchronized) != 0)
+                       output.append("synchronized "); //$NON-NLS-1$
+               if ((modifiers & AccVolatile) != 0)
+                       output.append("volatile "); //$NON-NLS-1$
+               if ((modifiers & AccTransient) != 0)
+                       output.append("transient "); //$NON-NLS-1$
+               if ((modifiers & AccNative) != 0)
+                       output.append("native "); //$NON-NLS-1$
+               if ((modifiers & AccAbstract) != 0)
+                       output.append("abstract "); //$NON-NLS-1$
+               return output;
+       }
+       public int sourceStart() {
+               return this.sourceStart;
+       }
+       public int sourceEnd() {
+               return this.sourceEnd;
+       }
+       public String toString() {
+
+               return print(0, new StringBuffer(30)).toString();
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               // do nothing by default
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
new file mode 100644 (file)
index 0000000..c25253e
--- /dev/null
@@ -0,0 +1,398 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
+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.problem.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+
+public abstract class AbstractMethodDeclaration
+       extends ASTNode
+       implements ProblemSeverities, ReferenceContext {
+               
+       public MethodScope scope;
+       //it is not relevent for constructor but it helps to have the name of the constructor here 
+       //which is always the name of the class.....parsing do extra work to fill it up while it do not have to....
+       public char[] selector;
+       public int declarationSourceStart;
+       public int declarationSourceEnd;
+       public int modifiers;
+       public int modifiersSourceStart;
+       public Argument[] arguments;
+       public TypeReference[] thrownExceptions;
+       public Statement[] statements;
+       public int explicitDeclarations;
+       public MethodBinding binding;
+       public boolean ignoreFurtherInvestigation = false;
+       public boolean needFreeReturn = false;
+       
+       public Javadoc javadoc;
+       
+       public int bodyStart;
+       public int bodyEnd = -1;
+       public CompilationResult compilationResult;
+       
+       public boolean errorInSignature = false; 
+       
+       AbstractMethodDeclaration(CompilationResult compilationResult){
+               this.compilationResult = compilationResult;
+       }
+       
+       /*
+        *      We cause the compilation task to abort to a given extent.
+        */
+       public void abort(int abortLevel, IProblem problem) {
+
+               switch (abortLevel) {
+                       case AbortCompilation :
+                               throw new AbortCompilation(this.compilationResult, problem);
+                       case AbortCompilationUnit :
+                               throw new AbortCompilationUnit(this.compilationResult, problem);
+                       case AbortType :
+                               throw new AbortType(this.compilationResult, problem);
+                       default :
+                               throw new AbortMethod(this.compilationResult, problem);
+               }
+       }
+
+       public abstract void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo info);
+
+               /**
+        * Bind and add argument's binding into the scope of the method
+        */
+       public void bindArguments() {
+
+               if (this.arguments != null) {
+                       // by default arguments in abstract/native methods are considered to be used (no complaint is expected)
+                       boolean used = this.binding == null || this.binding.isAbstract() || this.binding.isNative();
+
+                       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);
+                       }
+               }
+       }
+
+       /**
+        * Record the thrown exception type bindings in the corresponding type references.
+        */
+       public void bindThrownExceptions() {
+
+               if (this.thrownExceptions != null
+                       && this.binding != null
+                       && this.binding.thrownExceptions != null) {
+                       int thrownExceptionLength = this.thrownExceptions.length;
+                       int length = this.binding.thrownExceptions.length;
+                       if (length == thrownExceptionLength) {
+                               for (int i = 0; i < length; i++) {
+                                       this.thrownExceptions[i].resolvedType = this.binding.thrownExceptions[i];
+                               }
+                       } else {
+                               int bindingIndex = 0;
+                               for (int i = 0; i < thrownExceptionLength && bindingIndex < length; i++) {
+                                       TypeReference thrownException = this.thrownExceptions[i];
+                                       ReferenceBinding thrownExceptionBinding = this.binding.thrownExceptions[bindingIndex];
+                                       char[][] bindingCompoundName = thrownExceptionBinding.compoundName;
+                                       if (thrownException instanceof SingleTypeReference) {
+                                               // single type reference
+                                               int lengthName = bindingCompoundName.length;
+                                               char[] thrownExceptionTypeName = thrownException.getTypeName()[0];
+                                               if (CharOperation.equals(thrownExceptionTypeName, bindingCompoundName[lengthName - 1])) {
+                                                       thrownException.resolvedType = thrownExceptionBinding;
+                                                       bindingIndex++;
+                                               }
+                                       } else {
+                                               // qualified type reference
+                                               if (CharOperation.equals(thrownException.getTypeName(), bindingCompoundName)) {
+                                                       thrownException.resolvedType = thrownExceptionBinding;
+                                                       bindingIndex++;
+                                               }                                               
+                                       }
+                               }
+                       }
+               }
+       }
+
+       public CompilationResult compilationResult() {
+               
+               return this.compilationResult;
+       }
+       
+       /**
+        * Bytecode generation for a method
+        * @param classScope
+        * @param classFile
+        */
+       public void generateCode(ClassScope classScope, ClassFile classFile) {
+               
+               int problemResetPC = 0;
+               classFile.codeStream.wideMode = false; // reset wideMode to false
+               if (this.ignoreFurtherInvestigation) {
+                       // method is known to have errors, dump a problem method
+                       if (this.binding == null)
+                               return; // handle methods with invalid signature or duplicates
+                       int problemsLength;
+                       IProblem[] problems =
+                               this.scope.referenceCompilationUnit().compilationResult.getProblems();
+                       IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+                       System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+                       classFile.addProblemMethod(this, this.binding, problemsCopy);
+                       return;
+               }
+               // regular code generation
+               try {
+                       problemResetPC = classFile.contentsOffset;
+                       this.generateCode(classFile);
+               } catch (AbortMethod e) {
+                       // a fatal error was detected during code generation, need to restart code gen if possible
+                       if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
+                               // a branch target required a goto_w, restart code gen in wide mode.
+                               try {
+                                       classFile.contentsOffset = problemResetPC;
+                                       classFile.methodCount--;
+                                       classFile.codeStream.wideMode = true; // request wide mode 
+                                       this.generateCode(classFile); // restart method generation
+                               } catch (AbortMethod e2) {
+                                       int problemsLength;
+                                       IProblem[] problems =
+                                               this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
+                                       IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+                                       System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+                                       classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
+                               }
+                       } else {
+                               // produce a problem method accounting for this fatal error
+                               int problemsLength;
+                               IProblem[] problems =
+                                       this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
+                               IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+                               System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+                               classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
+                       }
+               }
+       }
+
+       private void generateCode(ClassFile classFile) {
+
+               classFile.generateMethodInfoHeader(this.binding);
+               int methodAttributeOffset = classFile.contentsOffset;
+               int attributeNumber = classFile.generateMethodInfoAttribute(this.binding);
+               if ((!this.binding.isNative()) && (!this.binding.isAbstract())) {
+                       int codeAttributeOffset = classFile.contentsOffset;
+                       classFile.generateCodeAttributeHeader();
+                       CodeStream codeStream = classFile.codeStream;
+                       codeStream.reset(this, classFile);
+                       // initialize local positions
+                       this.scope.computeLocalVariablePositions(this.binding.isStatic() ? 0 : 1, codeStream);
+
+                       // arguments initialization for local variable debug attributes
+                       if (this.arguments != null) {
+                               for (int i = 0, max = this.arguments.length; i < max; i++) {
+                                       LocalVariableBinding argBinding;
+                                       codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
+                                       argBinding.recordInitializationStartPC(0);
+                               }
+                       }
+                       if (this.statements != null) {
+                               for (int i = 0, max = this.statements.length; i < max; i++)
+                                       this.statements[i].generateCode(this.scope, codeStream);
+                       }
+                       if (this.needFreeReturn) {
+                               codeStream.return_();
+                       }
+                       // local variable attributes
+                       codeStream.exitUserScope(this.scope);
+                       codeStream.recordPositionsFrom(0, this.declarationSourceEnd);
+                       classFile.completeCodeAttribute(codeAttributeOffset);
+                       attributeNumber++;
+               } else {
+                       checkArgumentsSize();
+               }
+               classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
+
+               // if a problem got reported during code gen, then trigger problem method creation
+               if (this.ignoreFurtherInvestigation) {
+                       throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
+               }
+       }
+
+       private void checkArgumentsSize() {
+               TypeBinding[] parameters = this.binding.parameters;
+               int size = 1; // an abstact method or a native method cannot be static
+               for (int i = 0, max = parameters.length; i < max; i++) {
+                       TypeBinding parameter = parameters[i];
+                       if (parameter == LongBinding || parameter == DoubleBinding) {
+                               size += 2;
+                       } else {
+                               size++;
+                       }
+                       if (size > 0xFF) {
+                               this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration);
+                       }
+               }
+       }
+       
+       public boolean hasErrors() {
+               return this.ignoreFurtherInvestigation;
+       }
+
+       public boolean isAbstract() {
+
+               if (this.binding != null)
+                       return this.binding.isAbstract();
+               return (this.modifiers & AccAbstract) != 0;
+       }
+
+       public boolean isClinit() {
+
+               return false;
+       }
+
+       public boolean isConstructor() {
+
+               return false;
+       }
+
+       public boolean isDefaultConstructor() {
+
+               return false;
+       }
+
+       public boolean isInitializationMethod() {
+
+               return false;
+       }
+
+       public boolean isNative() {
+
+               if (this.binding != null)
+                       return this.binding.isNative();
+               return (this.modifiers & AccNative) != 0;
+       }
+
+       public boolean isStatic() {
+
+               if (this.binding != null)
+                       return this.binding.isStatic();
+               return (this.modifiers & AccStatic) != 0;
+       }
+
+       /**
+        * Fill up the method body with statement
+        * @param parser
+        * @param unit
+        */
+       public abstract void parseStatements(
+               Parser parser,
+               CompilationUnitDeclaration unit);
+
+       public StringBuffer print(int tab, StringBuffer output) {
+
+               printIndent(tab, output);
+               printModifiers(this.modifiers, output);
+               printReturnType(0, output).append(this.selector).append('(');
+               if (this.arguments != null) {
+                       for (int i = 0; i < this.arguments.length; i++) {
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               this.arguments[i].print(0, output);
+                       }
+               }
+               output.append(')');
+               if (this.thrownExceptions != null) {
+                       output.append(" throws "); //$NON-NLS-1$
+                       for (int i = 0; i < this.thrownExceptions.length; i++) {
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               this.thrownExceptions[i].print(0, output);
+                       }
+               }
+               printBody(tab + 1, output);
+               return output;
+       }
+
+       public StringBuffer printBody(int indent, StringBuffer output) {
+
+               if (isAbstract() || (this.modifiers & AccSemicolonBody) != 0) 
+                       return output.append(';');
+
+               output.append(" {"); //$NON-NLS-1$
+               if (this.statements != null) {
+                       for (int i = 0; i < this.statements.length; i++) {
+                               output.append('\n');
+                               this.statements[i].printStatement(indent, output); 
+                       }
+               }
+               output.append('\n'); //$NON-NLS-1$
+               printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
+               return output;
+       }
+
+       public StringBuffer printReturnType(int indent, StringBuffer output) {
+               
+               return output;
+       }
+
+       public void resolve(ClassScope upperScope) {
+
+               if (this.binding == null) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+
+               try {
+                       bindArguments(); 
+                       bindThrownExceptions();
+                       resolveJavadoc();
+                       resolveStatements();
+               } catch (AbortMethod e) {       // ========= abort on fatal error =============
+                       this.ignoreFurtherInvestigation = true;
+               } 
+       }
+
+       public void resolveJavadoc() {
+               
+               if (this.binding == null) return;
+               if (this.javadoc != null) {
+                       this.javadoc.resolve(this.scope);
+                       return;
+               }
+               if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
+                       this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+               }
+       }
+
+       public void resolveStatements() {
+
+               if (this.statements != null) {
+                       for (int i = 0, length = this.statements.length; i < length; i++) {
+                               this.statements[i].resolve(this.scope);
+                       }
+               } else if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+                       this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd+1);
+               }
+       }
+
+       public void tagAsHavingErrors() {
+
+               this.ignoreFurtherInvestigation = true;
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               ClassScope classScope) {
+               // default implementation: subclass will define it
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/AbstractVariableDeclaration.java
new file mode 100644 (file)
index 0000000..cce62fc
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+
+public abstract class AbstractVariableDeclaration extends Statement implements InvocationSite {
+       public int declarationEnd;
+       public int declarationSourceEnd;
+       public int declarationSourceStart;
+       public int hiddenVariableDepth; // used to diagnose hiding scenarii
+       public Expression initialization;
+       public int modifiers;
+       public int modifiersSourceStart;
+
+       public char[] name;
+
+       public TypeReference type;
+       
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+               return flowInfo;
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+        */
+       public boolean isSuperAccess() {
+               return false;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isTypeAccess()
+        */
+       public boolean isTypeAccess() {
+               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);
+               }
+               return output.append(';');
+       }
+
+       public void resolve(BlockScope scope) {
+               // do nothing by default (redefined for local variables)
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setActualReceiverType(org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding)
+        */
+       public void setActualReceiverType(ReferenceBinding receiverType) {
+               // do nothing by default
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setDepth(int)
+        */
+       public void setDepth(int depth) {
+
+               this.hiddenVariableDepth = depth;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#setFieldIndex(int)
+        */
+       public void setFieldIndex(int depth) {
+               // do nothing by default
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
new file mode 100644 (file)
index 0000000..2a47d4d
--- /dev/null
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class AllocationExpression
+       extends Expression
+       implements InvocationSite {
+               
+       public TypeReference type;
+       public Expression[] arguments;
+       public MethodBinding binding;
+
+       MethodBinding syntheticAccessor;
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // check captured variables are initialized in current context (26134)
+               checkCapturedLocalInitializationIfNecessary(this.binding.declaringClass, currentScope, flowInfo);
+
+               // process arguments
+               if (arguments != null) {
+                       for (int i = 0, count = arguments.length; i < count; i++) {
+                               flowInfo =
+                                       arguments[i]
+                                               .analyseCode(currentScope, flowContext, flowInfo)
+                                               .unconditionalInits();
+                       }
+               }
+               // record some dependency information for exception types
+               ReferenceBinding[] thrownExceptions;
+               if (((thrownExceptions = this.binding.thrownExceptions).length) != 0) {
+                       // check exception handling
+                       flowContext.checkExceptionHandlers(
+                               thrownExceptions,
+                               this,
+                               flowInfo,
+                               currentScope);
+               }
+               manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+               manageSyntheticAccessIfNecessary(currentScope, flowInfo);
+               
+               return flowInfo;
+       }
+
+       public void checkCapturedLocalInitializationIfNecessary(ReferenceBinding checkedType, BlockScope currentScope, FlowInfo flowInfo) {
+
+               if (checkedType.isLocalType() 
+                               && !checkedType.isAnonymousType()
+                               && !currentScope.isDefinedInType(checkedType)) { // only check external allocations
+                       NestedTypeBinding nestedType = (NestedTypeBinding) checkedType;
+                       SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
+                       if (syntheticArguments != null) 
+                               for (int i = 0, count = syntheticArguments.length; i < count; i++){
+                                       SyntheticArgumentBinding syntheticArgument = syntheticArguments[i];
+                                       LocalVariableBinding targetLocal;
+                                       if ((targetLocal = syntheticArgument.actualOuterLocalVariable) == null) continue;
+                                       if (targetLocal.declaration != null && !flowInfo.isDefinitelyAssigned(targetLocal)){
+                                               currentScope.problemReporter().uninitializedLocalVariable(targetLocal, this);
+                                       }
+                               }
+                                               
+               }
+       }
+       
+       public Expression enclosingInstance() {
+               return null;
+       }
+
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+
+               int pc = codeStream.position;
+               ReferenceBinding allocatedType = binding.declaringClass;
+
+               codeStream.new_(allocatedType);
+               if (valueRequired) {
+                       codeStream.dup();
+               }
+               // better highlight for allocation: display the type individually
+               codeStream.recordPositionsFrom(pc, type.sourceStart);
+
+               // handling innerclass instance allocation - enclosing instance arguments
+               if (allocatedType.isNestedType()) {
+                       codeStream.generateSyntheticEnclosingInstanceValues(
+                               currentScope,
+                               allocatedType,
+                               enclosingInstance(),
+                               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);
+                       }
+               }
+               // handling innerclass instance allocation - outer local arguments
+               if (allocatedType.isNestedType()) {
+                       codeStream.generateSyntheticOuterArgumentValues(
+                               currentScope,
+                               allocatedType,
+                               this);
+               }
+               // invoke constructor
+               if (syntheticAccessor == null) {
+                       codeStream.invokespecial(binding);
+               } 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;
+                               i < max;
+                               i++) {
+                               codeStream.aconst_null();
+                       }
+                       codeStream.invokespecial(syntheticAccessor);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public boolean isSuperAccess() {
+
+               return false;
+       }
+
+       public boolean isTypeAccess() {
+
+               return true;
+       }
+
+       /* Inner emulation consists in either recording a dependency 
+        * link only, or performing one level of propagation.
+        *
+        * Dependency mechanism is used whenever dealing with source target
+        * types, since by the time we reach them, we might not yet know their
+        * exact need.
+        */
+       public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               ReferenceBinding allocatedType;
+
+               // perform some emulation work in case there is some and we are inside a local type only
+               if ((allocatedType = binding.declaringClass).isNestedType()
+                       && currentScope.enclosingSourceType().isLocalType()) {
+
+                       if (allocatedType.isLocalType()) {
+                               ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, false);
+                               // request cascade of accesses
+                       } else {
+                               // locally propagate, since we already now the desired shape for sure
+                               currentScope.propagateInnerEmulation(allocatedType, false);
+                               // request cascade of accesses
+                       }
+               }
+       }
+
+       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();
+                               // constructor will not be dumped as private, no emulation required thus
+                       } else {
+                               syntheticAccessor =
+                                       ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
+                               currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+                       }
+               }
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               output.append("new "); //$NON-NLS-1$
+               type.printExpression(0, output); 
+               output.append('(');
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               arguments[i].printExpression(0, output);
+                       }
+               }
+               return output.append(')');
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+
+               // Propagate the type checking to the arguments, and check if the constructor is defined.
+               constant = NotAConstant;
+               this.resolvedType = type.resolveType(scope);
+               // will check for null after args are resolved
+
+               // buffering the arguments' types
+               boolean argsContainCast = false;
+               TypeBinding[] argumentTypes = NoParameters;
+               if (arguments != null) {
+                       boolean argHasError = false;
+                       int length = arguments.length;
+                       argumentTypes = new TypeBinding[length];
+                       for (int i = 0; i < length; i++) {
+                               Expression argument = this.arguments[i];
+                               if (argument instanceof CastExpression) {
+                                       argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+                                       argsContainCast = true;
+                               }
+                               if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
+                                       argHasError = true;
+                               }
+                       }
+                       if (argHasError) {
+                               return this.resolvedType;
+                       }
+               }
+               if (this.resolvedType == null)
+                       return null;
+
+               if (!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.declaringClass == null)
+                               binding.declaringClass = allocationType;
+                       scope.problemReporter().invalidConstructor(this, binding);
+                       return this.resolvedType;
+               }
+               if (isMethodUseDeprecated(binding, scope))
+                       scope.problemReporter().deprecatedMethod(binding, this);
+
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+                       }
+                       if (argsContainCast) {
+                               CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
+                       }
+               }
+               return allocationType;
+       }
+
+       public void setActualReceiverType(ReferenceBinding receiverType) {
+               // ignored
+       }
+
+       public void setDepth(int i) {
+               // ignored
+       }
+
+       public void setFieldIndex(int i) {
+               // ignored
+       }
+
+       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);
+                       }
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Argument.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Argument.java
new file mode 100644 (file)
index 0000000..b6669ac
--- /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.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Argument extends LocalDeclaration {
+       
+       // prefix for setter method (to recognize special hiding argument)
+       private final static char[] SET = "set".toCharArray(); //$NON-NLS-1$
+
+       public Argument(char[] name, long posNom, TypeReference tr, int modifiers) {
+
+               super(name, (int) (posNom >>> 32), (int) posNom);
+               this.declarationSourceEnd = (int) posNom;
+               this.modifiers = modifiers;
+               type = tr;
+               this.bits |= IsLocalDeclarationReachableMASK;
+       }
+
+       public void bind(MethodScope scope, TypeBinding typeBinding, boolean used) {
+
+               if (this.type != null)
+                       this.type.resolvedType = typeBinding;
+               // 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*/);
+               if (existingVariable != null && existingVariable.isValidBinding()){
+                       if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+                               scope.problemReporter().redefineArgument(this);
+                               return;
+                       }
+                       boolean isSpecialArgument = false;
+                       if (existingVariable instanceof FieldBinding) {
+                               if (scope.isInsideConstructor()) {
+                                       isSpecialArgument = true; // constructor argument
+                               } else {
+                                       AbstractMethodDeclaration methodDecl = scope.referenceMethod();
+                                       if (methodDecl != null && CharOperation.prefixEquals(SET, methodDecl.selector)) {
+                                               isSpecialArgument = true; // setter argument
+                                       }
+                               }
+                       }
+                       scope.problemReporter().localVariableHiding(this, existingVariable, isSpecialArgument);
+               }
+
+               scope.addLocalVariable(
+                       this.binding =
+                               new LocalVariableBinding(this, typeBinding, modifierFlag, true));
+               //true stand for argument instead of just local
+               if (typeBinding != null && isTypeUseDeprecated(typeBinding, scope))
+                       scope.problemReporter().deprecatedType(typeBinding, this.type);
+               this.binding.declaration = this;
+               this.binding.useFlag = used ? LocalVariableBinding.USED : LocalVariableBinding.UNUSED;
+       }
+
+       public StringBuffer print(int indent, StringBuffer output) {
+
+               printIndent(indent, output);
+               printModifiers(this.modifiers, output);
+               if (type == null) {
+                       output.append("<no type> "); //$NON-NLS-1$
+               } else {
+                       type.print(0, output).append(' '); 
+               }
+               return output.append(this.name);
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               return print(indent, output).append(';');
+       }       
+
+       public TypeBinding resolveForCatch(BlockScope scope) {
+
+               // resolution on an argument of a catch clause
+               // 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)
+                       return null;
+
+               Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+               if (existingVariable != null && existingVariable.isValidBinding()){
+                       if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+                               scope.problemReporter().redefineArgument(this);
+                               return null;
+                       }
+                       scope.problemReporter().localVariableHiding(this, existingVariable, false);
+               }
+
+               binding = new LocalVariableBinding(this, tb, modifiers, false); // argument decl, but local var  (where isArgument = false)
+               scope.addLocalVariable(binding);
+               binding.constant = NotAConstant;
+               return tb;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               if (visitor.visit(this, scope)) {
+                       if (type != null)
+                               type.traverse(visitor, scope);
+                       if (initialization != null)
+                               initialization.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
new file mode 100644 (file)
index 0000000..d9ab28d
--- /dev/null
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ArrayAllocationExpression extends Expression {
+
+       public TypeReference type;
+
+       //dimensions.length gives the number of dimensions, but the
+       // last ones may be nulled as in new int[4][5][][]
+       public Expression[] dimensions;
+       public ArrayInitializer initializer;
+
+       /**
+        * ArrayAllocationExpression constructor comment.
+        */
+       public ArrayAllocationExpression() {
+               super();
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+               for (int i = 0, max = dimensions.length; i < max; i++) {
+                       Expression dim;
+                       if ((dim = dimensions[i]) != null) {
+                               flowInfo = dim.analyseCode(currentScope, flowContext, flowInfo);
+                       }
+               }
+               if (initializer != null) {
+                       return initializer.analyseCode(currentScope, flowContext, flowInfo);
+               }
+               return flowInfo;
+       }
+
+       /**
+        * Code generation for a array allocation expression
+        */
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+
+               int pc = codeStream.position;
+
+               if (initializer != null) {
+                       initializer.generateCode(currentScope, codeStream, valueRequired);
+                       return;
+               }
+
+               int nonNullDimensionsLength = 0;
+               for (int i = 0, max = dimensions.length; i < max; i++)
+                       if (dimensions[i] != null) {
+                               dimensions[i].generateCode(currentScope, codeStream, true);
+                               nonNullDimensionsLength++;
+                       }
+
+               // Generate a sequence of bytecodes corresponding to an array allocation
+               if (this.resolvedType.dimensions() == 1) {
+                       // Mono-dimensional array
+                       codeStream.newArray(currentScope, (ArrayBinding)this.resolvedType);
+               } else {
+                       // Multi-dimensional array
+                       codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
+               }
+
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(implicitConversion);
+               } else {
+                       codeStream.pop();
+               }
+
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               output.append("new "); //$NON-NLS-1$
+               type.print(0, output); 
+               for (int i = 0; i < dimensions.length; i++) {
+                       if (dimensions[i] == null)
+                               output.append("[]"); //$NON-NLS-1$
+                       else {
+                               output.append('[');
+                               dimensions[i].printExpression(0, output);
+                               output.append(']');
+                       }
+               } 
+               if (initializer != null) initializer.printExpression(0, output);
+               return output;
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+
+               // Build an array type reference using the current dimensions
+               // The parser does not check for the fact that dimension may be null
+               // 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);
+               
+               // will check for null after dimensions are checked
+               constant = Constant.NotAConstant;
+               if (referenceType == VoidBinding) {
+                       scope.problemReporter().cannotAllocateVoidArray(this);
+                       referenceType = null;
+               }
+
+               // check the validity of the dimension syntax (and test for all null dimensions)
+               int explicitDimIndex = -1;
+               for (int i = dimensions.length; --i >= 0;) {
+                       if (dimensions[i] != null) {
+                               if (explicitDimIndex < 0) explicitDimIndex = i;
+                       } else if (explicitDimIndex> 0) {
+                               // should not have an empty dimension before an non-empty one
+                               scope.problemReporter().incorrectLocationForEmptyDimension(this, i);
+                       }
+               }
+
+               // explicitDimIndex < 0 says if all dimensions are nulled
+               // when an initializer is given, no dimension must be specified
+               if (initializer == null) {
+                       if (explicitDimIndex < 0) {
+                               scope.problemReporter().mustDefineDimensionsOrInitializer(this);
+                       }
+               } else if (explicitDimIndex >= 0) {
+                       scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
+               }
+
+               // dimensions resolution 
+               for (int i = 0; i <= explicitDimIndex; i++) {
+                       if (dimensions[i] != null) {
+                               TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
+                               if (dimensionType != null) {
+                                       dimensions[i].implicitWidening(IntBinding, dimensionType);
+                               }
+                       }
+               }
+
+               // building the array binding
+               if (referenceType != null) {
+                       if (dimensions.length > 255) {
+                               scope.problemReporter().tooManyDimensions(this);
+                       }
+                       this.resolvedType = scope.createArray(referenceType, dimensions.length);
+
+                       // check the initializer
+                       if (initializer != null) {
+                               if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
+                                       initializer.binding = (ArrayBinding)this.resolvedType;
+                       }
+               }
+               return this.resolvedType;
+       }
+
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       int dimensionsLength = dimensions.length;
+                       type.traverse(visitor, scope);
+                       for (int i = 0; i < dimensionsLength; i++) {
+                               if (dimensions[i] != null)
+                                       dimensions[i].traverse(visitor, scope);
+                       }
+                       if (initializer != null)
+                               initializer.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
new file mode 100644 (file)
index 0000000..b717047
--- /dev/null
@@ -0,0 +1,209 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ArrayInitializer extends Expression {
+               
+       public Expression[] expressions;
+       public ArrayBinding binding; //the type of the { , , , }
+       
+       /**
+        * ArrayInitializer constructor comment.
+        */
+       public ArrayInitializer() {
+
+               super();
+       }
+
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+               if (expressions != null) {
+                       for (int i = 0, max = expressions.length; i < max; i++) {
+                               flowInfo = expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+                       }
+               }
+               return flowInfo;
+       }
+
+       /**
+        * Code generation for a array initializer
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+               // Flatten the values and compute the dimensions, by iterating in depth into nested array initializers
+               int pc = codeStream.position;
+               int expressionLength = (expressions == null) ? 0: expressions.length;
+               codeStream.generateInlinedValue(expressionLength);
+               codeStream.newArray(currentScope, binding);
+               if (expressions != null) {
+                       // binding is an ArrayType, so I can just deal with the dimension
+                       int elementsTypeID = binding.dimensions > 1 ? -1 : binding.leafComponentType.id;
+                       for (int i = 0; i < expressionLength; i++) {
+                               Expression expr;
+                               if ((expr = expressions[i]).constant != NotAConstant) {
+                                       switch (elementsTypeID) { // filter out initializations to default values
+                                               case T_int :
+                                               case T_short :
+                                               case T_byte :
+                                               case T_char :
+                                               case T_long :
+                                                       if (expr.constant.longValue() != 0) {
+                                                               codeStream.dup();
+                                                               codeStream.generateInlinedValue(i);
+                                                               expr.generateCode(currentScope, codeStream, true);
+                                                               codeStream.arrayAtPut(elementsTypeID, false);
+                                                       }
+                                                       break;
+                                               case T_float :
+                                               case T_double :
+                                                       double constantValue = expr.constant.doubleValue();
+                                                       if (constantValue == -0.0 || constantValue != 0) {
+                                                               codeStream.dup();
+                                                               codeStream.generateInlinedValue(i);
+                                                               expr.generateCode(currentScope, codeStream, true);
+                                                               codeStream.arrayAtPut(elementsTypeID, false);
+                                                       }
+                                                       break;
+                                               case T_boolean :
+                                                       if (expr.constant.booleanValue() != false) {
+                                                               codeStream.dup();
+                                                               codeStream.generateInlinedValue(i);
+                                                               expr.generateCode(currentScope, codeStream, true);
+                                                               codeStream.arrayAtPut(elementsTypeID, false);
+                                                       }
+                                                       break;
+                                               default :
+                                                       if (!(expr instanceof NullLiteral)) {
+                                                               codeStream.dup();
+                                                               codeStream.generateInlinedValue(i);
+                                                               expr.generateCode(currentScope, codeStream, true);
+                                                               codeStream.arrayAtPut(elementsTypeID, false);
+                                                       }
+                                       }
+                               } else if (!(expr instanceof NullLiteral)) {
+                                       codeStream.dup();
+                                       codeStream.generateInlinedValue(i);
+                                       expr.generateCode(currentScope, codeStream, true);
+                                       codeStream.arrayAtPut(elementsTypeID, false);
+                               }
+                       }
+               }
+               if (!valueRequired) {
+                       codeStream.pop();
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+       
+               output.append('{');
+               if (expressions != null) {      
+                       int j = 20 ; 
+                       for (int i = 0 ; i < expressions.length ; i++) {        
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               expressions[i].printExpression(0, output);
+                               j -- ;
+                               if (j == 0) {
+                                       output.append('\n');
+                                       printIndent(indent+1, output);
+                                       j = 20;
+                               }
+                       }
+               }
+               return output.append('}');
+       }
+
+       public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedTb) {
+               // Array initializers can only occur on the right hand side of an assignment
+               // expression, therefore the expected type contains the valid information
+               // concerning the type that must be enforced by the elements of the array initializer.
+       
+               // this method is recursive... (the test on isArrayType is the stop case)
+       
+               constant = NotAConstant;
+               if (expectedTb.isArrayType()) {
+                       binding = (ArrayBinding) expectedTb;
+                       if (expressions == null)
+                               return binding;
+                       TypeBinding expectedElementsTb = binding.elementsType(scope);
+                       if (expectedElementsTb.isBaseType()) {
+                               for (int i = 0, length = expressions.length; i < length; i++) {
+                                       Expression expression = expressions[i];
+                                       TypeBinding expressionTb =
+                                               (expression instanceof ArrayInitializer)
+                                                       ? expression.resolveTypeExpecting(scope, expectedElementsTb)
+                                                       : expression.resolveType(scope);
+                                       if (expressionTb == null)
+                                               return null;
+       
+                                       // Compile-time conversion required?
+                                       if (expression.isConstantValueOfTypeAssignableToType(expressionTb, expectedElementsTb)) {
+                                               expression.implicitWidening(expectedElementsTb, expressionTb);
+                                       } else if (BaseTypeBinding.isWidening(expectedElementsTb.id, expressionTb.id)) {
+                                               expression.implicitWidening(expectedElementsTb, expressionTb);
+                                       } else {
+                                               scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionTb, expectedElementsTb);
+                                               return null;
+                                       }
+                               }
+                       } else {
+                               for (int i = 0, length = expressions.length; i < length; i++)
+                                       if (expressions[i].resolveTypeExpecting(scope, expectedElementsTb) == null)
+                                               return null;
+                       }
+                       return binding;
+               }
+               
+               // infer initializer type for error reporting based on first element
+               TypeBinding leafElementType = null;
+               int dim = 1;
+               if (expressions == null) {
+                       leafElementType = scope.getJavaLangObject();
+               } else {
+                       Expression currentExpression = expressions[0];
+                       while(currentExpression != null && currentExpression instanceof ArrayInitializer) {
+                               dim++;
+                               Expression[] subExprs = ((ArrayInitializer) currentExpression).expressions;
+                               if (subExprs == null){
+                                       leafElementType = scope.getJavaLangObject();
+                                       currentExpression = null;
+                                       break;
+                               }
+                               currentExpression = ((ArrayInitializer) currentExpression).expressions[0];
+                       }
+                       if (currentExpression != null) {
+                               leafElementType = currentExpression.resolveType(scope);
+                       }
+               }
+               if (leafElementType != null) {
+                       TypeBinding probableTb = scope.createArray(leafElementType, dim);
+                       scope.problemReporter().typeMismatchErrorActualTypeExpectedType(this, probableTb, expectedTb);
+               }
+               return null;
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       if (expressions != null) {
+                               int expressionsLength = expressions.length;
+                               for (int i = 0; i < expressionsLength; i++)
+                                       expressions[i].traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
new file mode 100644 (file)
index 0000000..701f3a6
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.*;
+
+public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
+       int dimensions;
+       
+       public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss) {
+               
+               super( sources , poss);
+               dimensions = dim ;
+       }
+       
+       public ArrayQualifiedTypeReference(char[][] sources , TypeBinding tb, int dim, long[] poss) {
+               
+               super( sources , tb, poss);
+               dimensions = dim ;
+       }
+       
+       public int dimensions() {
+               
+               return dimensions;
+       }
+       
+       public TypeBinding getTypeBinding(Scope scope) {
+               
+               if (this.resolvedType != null)
+                       return this.resolvedType;
+               if (dimensions > 255) {
+                       scope.problemReporter().tooManyDimensions(this);
+               }
+               return scope.createArray(scope.getType(tokens), dimensions);
+       }
+       
+       public StringBuffer printExpression(int indent, StringBuffer output){
+               
+               super.printExpression(indent, output);
+               for (int i = 0 ; i < dimensions ; i++) {
+                       output.append("[]"); //$NON-NLS-1$
+               }
+               return output;
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+       
+       public void traverse(ASTVisitor visitor, ClassScope scope) {
+               
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayReference.java
new file mode 100644 (file)
index 0000000..915b347
--- /dev/null
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ArrayReference extends Reference {
+       
+       public Expression receiver;
+       public Expression position;
+
+       public ArrayReference(Expression rec, Expression pos) {
+               this.receiver = rec;
+               this.position = pos;
+               sourceStart = rec.sourceStart;
+       }
+
+       public FlowInfo analyseAssignment(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo,
+               Assignment assignment,
+               boolean compoundAssignment) {
+
+               if (assignment.expression == null) {
+                       return analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+               }
+               return assignment
+                       .expression
+                       .analyseCode(
+                               currentScope,
+                               flowContext,
+                               analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
+                       .unconditionalInits();
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return position.analyseCode(
+                       currentScope,
+                       flowContext,
+                       receiver.analyseCode(currentScope, flowContext, flowInfo));
+       }
+
+       public void generateAssignment(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Assignment assignment,
+               boolean valueRequired) {
+
+               receiver.generateCode(currentScope, codeStream, true);
+               if (receiver instanceof CastExpression  // ((type[])null)[0]
+                               && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
+                       codeStream.checkcast(receiver.resolvedType); 
+               }       
+               position.generateCode(currentScope, codeStream, true);
+               assignment.expression.generateCode(currentScope, codeStream, true);
+               codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(assignment.implicitConversion);
+               }
+       }
+
+       /**
+        * Code generation for a array reference
+        */
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+
+               int pc = codeStream.position;
+               receiver.generateCode(currentScope, codeStream, true);
+               if (receiver instanceof CastExpression  // ((type[])null)[0]
+                               && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
+                       codeStream.checkcast(receiver.resolvedType); 
+               }                       
+               position.generateCode(currentScope, codeStream, true);
+               codeStream.arrayAt(this.resolvedType.id);
+               // Generating code for the potential runtime type checking
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(implicitConversion);
+               } else {
+                       if (this.resolvedType == LongBinding
+                               || this.resolvedType == DoubleBinding) {
+                               codeStream.pop2();
+                       } else {
+                               codeStream.pop();
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public void generateCompoundAssignment(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Expression expression,
+               int operator,
+               int assignmentImplicitConversion,
+               boolean valueRequired) {
+
+               receiver.generateCode(currentScope, codeStream, true);
+               if (receiver instanceof CastExpression  // ((type[])null)[0]
+                               && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
+                       codeStream.checkcast(receiver.resolvedType); 
+               }       
+               position.generateCode(currentScope, codeStream, true);
+               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);
+               }
+               codeStream.arrayAtPut(this.resolvedType.id, valueRequired);
+       }
+
+       public void generatePostIncrement(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               CompoundAssignment postIncrement,
+               boolean valueRequired) {
+
+               receiver.generateCode(currentScope, codeStream, true);
+               if (receiver instanceof CastExpression  // ((type[])null)[0]
+                               && ((CastExpression)receiver).innermostCastedExpression().resolvedType == NullBinding){
+                       codeStream.checkcast(receiver.resolvedType); 
+               }       
+               position.generateCode(currentScope, codeStream, true);
+               codeStream.dup2();
+               codeStream.arrayAt(this.resolvedType.id);
+               if (valueRequired) {
+                       if ((this.resolvedType == LongBinding)
+                               || (this.resolvedType == DoubleBinding)) {
+                               codeStream.dup2_x2();
+                       } else {
+                               codeStream.dup_x2();
+                       }
+               }
+               codeStream.generateConstant(
+                       postIncrement.expression.constant,
+                       implicitConversion);
+               codeStream.sendOperator(postIncrement.operator, this.resolvedType.id);
+               codeStream.generateImplicitConversion(
+                       postIncrement.assignmentImplicitConversion);
+               codeStream.arrayAtPut(this.resolvedType.id, false);
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               receiver.printExpression(0, output).append('[');
+               return position.printExpression(0, output).append(']');
+       } 
+
+       public TypeBinding resolveType(BlockScope scope) {
+
+               constant = Constant.NotAConstant;
+               if (receiver instanceof CastExpression  // no cast check for ((type[])null)[0]
+                               && ((CastExpression)receiver).innermostCastedExpression() instanceof NullLiteral) {
+                       this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+               }               
+               TypeBinding arrayType = receiver.resolveType(scope);
+               if (arrayType != null) {
+                       if (arrayType.isArrayType()) {
+                               this.resolvedType = ((ArrayBinding) arrayType).elementsType(scope);
+                       } else {
+                               scope.problemReporter().referenceMustBeArrayTypeAt(arrayType, this);
+                       }
+               }
+               TypeBinding positionType = position.resolveTypeExpecting(scope, IntBinding);
+               if (positionType != null) {
+                       position.implicitWidening(IntBinding, positionType);
+               }
+               return this.resolvedType;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               if (visitor.visit(this, scope)) {
+                       receiver.traverse(visitor, scope);
+                       position.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
new file mode 100644 (file)
index 0000000..eec8865
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.*;
+
+public class ArrayTypeReference extends SingleTypeReference {
+       public int dimensions;
+
+       /**
+        * ArrayTypeReference constructor comment.
+        * @param source char[]
+        * @param dimensions int
+        * @param pos int
+        */
+       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.dimensions = dimensions ;
+       }
+       
+       public int dimensions() {
+               
+               return dimensions;
+       }
+       
+       public TypeBinding getTypeBinding(Scope scope) {
+               
+               if (this.resolvedType != null) return this.resolvedType;
+               if (dimensions > 255) {
+                       scope.problemReporter().tooManyDimensions(this);
+               }
+               return scope.createArray(scope.getType(token), dimensions);
+       
+       }
+       
+       public StringBuffer printExpression(int indent, StringBuffer output){
+       
+               super.printExpression(indent, output)  ;
+               for (int i= 0 ; i < dimensions ; i++) {
+                       output.append("[]"); //$NON-NLS-1$
+               }
+               return output;
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/AssertStatement.java
new file mode 100644 (file)
index 0000000..cf3093a
--- /dev/null
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * 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.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+
+public class AssertStatement extends Statement {
+       
+       public Expression assertExpression, exceptionArgument;
+
+       // for local variable attribute
+       int preAssertInitStateIndex = -1;
+       private FieldBinding assertionSyntheticFieldBinding;
+       
+       public AssertStatement(
+               Expression exceptionArgument,
+               Expression assertExpression,
+               int startPosition) {
+                       
+               this.assertExpression = assertExpression;
+               this.exceptionArgument = exceptionArgument;
+               sourceStart = startPosition;
+               sourceEnd = exceptionArgument.sourceEnd;
+       }
+
+       public AssertStatement(Expression assertExpression, int startPosition) {
+
+               this.assertExpression = assertExpression;
+               sourceStart = startPosition;
+               sourceEnd = assertExpression.sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+                       
+               preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
+
+               Constant cst = this.assertExpression.optimizedBooleanConstant();                
+               boolean isOptimizedTrueAssertion = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isOptimizedFalseAssertion = cst != NotAConstant && cst.booleanValue() == false;
+
+               FlowInfo assertInfo = flowInfo.copy();
+               if (isOptimizedTrueAssertion) {
+                       assertInfo.setReachMode(FlowInfo.UNREACHABLE);
+               }
+               assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits();
+               
+               if (exceptionArgument != null) {
+                       // only gets evaluated when escaping - results are not taken into account
+                       FlowInfo exceptionInfo = exceptionArgument.analyseCode(currentScope, flowContext, assertInfo.copy()); 
+                       
+                       if (!isOptimizedTrueAssertion){
+                               flowContext.checkExceptionHandlers(
+                                       currentScope.getJavaLangAssertionError(),
+                                       this,
+                                       exceptionInfo,
+                                       currentScope);
+                       }
+               }
+               
+               if (!isOptimizedTrueAssertion){
+                       // add the assert support in the clinit
+                       manageSyntheticAccessIfNecessary(currentScope, flowInfo);
+               }
+               if (isOptimizedFalseAssertion) {
+                       return flowInfo; // if assertions are enabled, the following code will be unreachable
+               } else {
+                       return flowInfo.mergedWith(assertInfo.unconditionalInits()); 
+               }
+       }
+
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+               if ((bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               int pc = codeStream.position;
+       
+               if (this.assertionSyntheticFieldBinding != null) {
+                       Label assertionActivationLabel = new Label(codeStream);
+                       codeStream.getstatic(this.assertionSyntheticFieldBinding);
+                       codeStream.ifne(assertionActivationLabel);
+                       
+                       Label falseLabel = new Label(codeStream);
+                       this.assertExpression.generateOptimizedBoolean(currentScope, codeStream, (falseLabel = new Label(codeStream)), null , true);
+                       codeStream.newJavaLangAssertionError();
+                       codeStream.dup();
+                       if (exceptionArgument != null) {
+                               exceptionArgument.generateCode(currentScope, codeStream, true);
+                               codeStream.invokeJavaLangAssertionErrorConstructor(exceptionArgument.implicitConversion & 0xF);
+                       } else {
+                               codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
+                       }
+                       codeStream.athrow();
+                       falseLabel.place();
+                       assertionActivationLabel.place();
+               }
+               
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (preAssertInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, preAssertInitStateIndex);
+               }       
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public void resolve(BlockScope scope) {
+
+               assertExpression.resolveTypeExpecting(scope, BooleanBinding);
+               if (exceptionArgument != null) {
+                       TypeBinding exceptionArgumentType = exceptionArgument.resolveType(scope);
+                       if (exceptionArgumentType != null){
+                           int id = exceptionArgumentType.id;
+                           switch(id) {
+                                       case T_void :
+                                               scope.problemReporter().illegalVoidExpression(exceptionArgument);
+                                       default:
+                                           id = T_Object;
+                                       case T_boolean :
+                                       case T_byte :
+                                       case T_char :
+                                       case T_short :
+                                       case T_double :
+                                       case T_float :
+                                       case T_int :
+                                       case T_long :
+                                       case T_String :
+                                               exceptionArgument.implicitConversion = (id << 4) + id;
+                               }
+                       }
+               }
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       assertExpression.traverse(visitor, scope);
+                       if (exceptionArgument != null) {
+                               exceptionArgument.traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, scope);
+       }       
+       
+       public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               
+               // need assertion flag: $assertionsDisabled on outer most source clas
+               // (in case of static member of interface, will use the outermost static member - bug 22334)
+               SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
+               while (outerMostClass.isLocalType()){
+                       ReferenceBinding enclosing = outerMostClass.enclosingType();
+                       if (enclosing == null || enclosing.isInterface()) break;
+                       outerMostClass = (SourceTypeBinding) enclosing;
+               }
+
+               this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticField(this, currentScope);
+
+               // find <clinit> and enable assertion support
+               TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
+               AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+               for (int i = 0, max = methods.length; i < max; i++) {
+                       AbstractMethodDeclaration method = methods[i];
+                       if (method.isClinit()) {
+                               ((Clinit) method).setAssertionSupport(assertionSyntheticFieldBinding);
+                               break;
+                       }
+               }
+       }
+
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+
+               printIndent(tab, output);
+               output.append("assert "); //$NON-NLS-1$
+               this.assertExpression.printExpression(0, output);
+               if (this.exceptionArgument != null) {
+                       output.append(": "); //$NON-NLS-1$
+                       this.exceptionArgument.printExpression(0, output);
+               }
+               return output.append(';');
+       }
+       
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Assignment.java
new file mode 100644 (file)
index 0000000..5b86ade
--- /dev/null
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * 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
+ *     Genady Beriozkin - added support for reporting assignment with no effect
+ *******************************************************************************/
+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.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Assignment extends Expression {
+
+       public Expression lhs;
+       public Expression expression;
+               
+       public Assignment(Expression lhs, Expression expression, int sourceEnd) {
+               //lhs is always a reference by construction ,
+               //but is build as an expression ==> the checkcast cannot fail
+
+               this.lhs = lhs;
+               lhs.bits |= IsStrictlyAssignedMASK; // tag lhs as assigned
+               
+               this.expression = expression;
+
+               this.sourceStart = lhs.sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+               // record setting a variable: various scenarii are possible, setting an array reference, 
+               // a field reference, a blank final field reference, a field of an enclosing instance or 
+               // just a local variable.
+
+               return ((Reference) lhs)
+                       .analyseAssignment(currentScope, flowContext, flowInfo, this, false)
+                       .unconditionalInits();
+       }
+
+       void checkAssignmentEffect(BlockScope scope) {
+               
+               Binding left = getDirectBinding(this.lhs);
+               if (left != null && left == getDirectBinding(this.expression)) {
+                       scope.problemReporter().assignmentHasNoEffect(this, left.shortReadableName());
+                       this.bits |= IsAssignmentWithNoEffectMASK; // record assignment has no effect
+               }
+       }
+
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+
+               // various scenarii are possible, setting an array reference, 
+               // a field reference, a blank final field reference, a field of an enclosing instance or 
+               // just a local variable.
+
+               int pc = codeStream.position;
+               if ((this.bits & IsAssignmentWithNoEffectMASK) != 0) {
+                       if (valueRequired) {
+                               this.expression.generateCode(currentScope, codeStream, true);
+                       }
+               } else {
+                        ((Reference) lhs).generateAssignment(currentScope, codeStream, this, valueRequired);
+                       // variable may have been optimized out
+                       // the lhs is responsible to perform the implicitConversion generation for the assignment since optimized for unused local assignment.
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       Binding getDirectBinding(Expression someExpression) {
+               if (someExpression instanceof SingleNameReference) {
+                       return ((SingleNameReference)someExpression).binding;
+               } else if (someExpression instanceof FieldReference) {
+                       FieldReference fieldRef = (FieldReference)someExpression;
+                       if (fieldRef.receiver.isThis() && !(fieldRef.receiver instanceof QualifiedThisReference)) {
+                               return fieldRef.binding;
+                       }                       
+               }
+               return null;
+       }
+       public StringBuffer print(int indent, StringBuffer output) {
+
+               //no () when used as a statement 
+               printIndent(indent, output);
+               return printExpressionNoParenthesis(indent, output);
+       }
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               //subclass redefine printExpressionNoParenthesis()
+               output.append('(');
+               return printExpressionNoParenthesis(0, output).append(')');
+       } 
+
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+               lhs.printExpression(indent, output).append(" = "); //$NON-NLS-1$
+               return expression.printExpression(0, output);
+       }
+       
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               //no () when used as a statement 
+               return print(indent, output).append(';');
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+
+               // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
+               constant = NotAConstant;
+               if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
+                       scope.problemReporter().expressionShouldBeAVariable(this.lhs);
+                       return null;
+               }
+               this.resolvedType = lhs.resolveType(scope); // expressionType contains the assignment type (lhs Type)
+               TypeBinding rhsType = expression.resolveType(scope);
+               if (this.resolvedType == 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);
+                       return this.resolvedType;
+               }
+               scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+                       expression,
+                       rhsType,
+                       this.resolvedType);
+               return this.resolvedType;
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveTypeExpecting(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.lookup.TypeBinding)
+        */
+       public TypeBinding resolveTypeExpecting(
+                       BlockScope scope,
+                       TypeBinding expectedType) {
+
+               TypeBinding type = super.resolveTypeExpecting(scope, expectedType);
+               // signal possible accidental boolean assignment (instead of using '==' operator)
+               if (expectedType == BooleanBinding 
+                               && this.lhs.resolvedType == BooleanBinding 
+                               && (this.lhs.bits & IsStrictlyAssignedMASK) != 0) {
+                       scope.problemReporter().possibleAccidentalBooleanAssignment(this);
+               }
+
+               return type;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               if (visitor.visit(this, scope)) {
+                       lhs.traverse(visitor, scope);
+                       expression.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
\ No newline at end of file
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
new file mode 100644 (file)
index 0000000..b5804d0
--- /dev/null
@@ -0,0 +1,1761 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class BinaryExpression extends OperatorExpression {
+
+       public Expression left, right;
+       public Constant optimizedBooleanConstant;
+
+       public BinaryExpression(Expression left, Expression right, int operator) {
+
+               this.left = left;
+               this.right = right;
+               this.bits |= operator << OperatorSHIFT; // encode operator
+               this.sourceStart = left.sourceStart;
+               this.sourceEnd = right.sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return right
+                       .analyseCode(
+                               currentScope,
+                               flowContext,
+                               left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits())
+                       .unconditionalInits();
+       }
+
+       public void computeConstant(BlockScope scope, int leftId, int rightId) {
+
+               //compute the constant when valid
+               if ((this.left.constant != Constant.NotAConstant)
+                       && (this.right.constant != Constant.NotAConstant)) {
+                       try {
+                               this.constant =
+                                       Constant.computeConstantOperation(
+                                               this.left.constant,
+                                               leftId,
+                                               (this.bits & OperatorMASK) >> OperatorSHIFT,
+                                               this.right.constant,
+                                               rightId);
+                       } catch (ArithmeticException e) {
+                               this.constant = Constant.NotAConstant;
+                               // 1.2 no longer throws an exception at compile-time
+                               //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
+                       }
+               } else {
+                       this.constant = Constant.NotAConstant;
+                       //add some work for the boolean operators & |  
+                       this.optimizedBooleanConstant(
+                               leftId,
+                               (this.bits & OperatorMASK) >> OperatorSHIFT,
+                               rightId);
+               }
+       }
+
+       public Constant optimizedBooleanConstant() {
+
+               return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant;
+       }
+
+       /**
+        * Code generation for a binary operation
+        */
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+
+               int pc = codeStream.position;
+               Label falseLabel, endLabel;
+               if (constant != Constant.NotAConstant) {
+                       if (valueRequired)
+                               codeStream.generateConstant(constant, implicitConversion);
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               bits |= OnlyValueRequiredMASK;
+               switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+                       case PLUS :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_String :
+                                               codeStream.generateStringAppend(currentScope, left, right);
+                                               if (!valueRequired)
+                                                       codeStream.pop();
+                                               break;
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.iadd();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.ladd();
+                                               break;
+                                       case T_double :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.dadd();
+                                               break;
+                                       case T_float :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.fadd();
+                                               break;
+                               }
+                               break;
+                       case MINUS :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.isub();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.lsub();
+                                               break;
+                                       case T_double :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.dsub();
+                                               break;
+                                       case T_float :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.fsub();
+                                               break;
+                               }
+                               break;
+                       case MULTIPLY :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.imul();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.lmul();
+                                               break;
+                                       case T_double :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.dmul();
+                                               break;
+                                       case T_float :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.fmul();
+                                               break;
+                               }
+                               break;
+                       case DIVIDE :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, true);
+                                               right.generateCode(currentScope, codeStream, true);
+                                               codeStream.idiv();
+                                               if (!valueRequired)
+                                                       codeStream.pop();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, true);
+                                               right.generateCode(currentScope, codeStream, true);
+                                               codeStream.ldiv();
+                                               if (!valueRequired)
+                                                       codeStream.pop2();
+                                               break;
+                                       case T_double :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.ddiv();
+                                               break;
+                                       case T_float :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.fdiv();
+                                               break;
+                               }
+                               break;
+                       case REMAINDER :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, true);
+                                               right.generateCode(currentScope, codeStream, true);
+                                               codeStream.irem();
+                                               if (!valueRequired)
+                                                       codeStream.pop();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, true);
+                                               right.generateCode(currentScope, codeStream, true);
+                                               codeStream.lrem();
+                                               if (!valueRequired)
+                                                       codeStream.pop2();
+                                               break;
+                                       case T_double :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.drem();
+                                               break;
+                                       case T_float :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.frem();
+                                               break;
+                               }
+                               break;
+                       case AND :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               // 0 & x
+                                               if ((left.constant != Constant.NotAConstant)
+                                                       && (left.constant.typeID() == T_int)
+                                                       && (left.constant.intValue() == 0)) {
+                                                       right.generateCode(currentScope, codeStream, false);
+                                                       if (valueRequired)
+                                                               codeStream.iconst_0();
+                                               } else {
+                                                       // x & 0
+                                                       if ((right.constant != Constant.NotAConstant)
+                                                               && (right.constant.typeID() == T_int)
+                                                               && (right.constant.intValue() == 0)) {
+                                                               left.generateCode(currentScope, codeStream, false);
+                                                               if (valueRequired)
+                                                                       codeStream.iconst_0();
+                                                       } else {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                                               if (valueRequired)
+                                                                       codeStream.iand();
+                                                       }
+                                               }
+                                               break;
+                                       case T_long :
+                                               // 0 & x
+                                               if ((left.constant != Constant.NotAConstant)
+                                                       && (left.constant.typeID() == T_long)
+                                                       && (left.constant.longValue() == 0L)) {
+                                                       right.generateCode(currentScope, codeStream, false);
+                                                       if (valueRequired)
+                                                               codeStream.lconst_0();
+                                               } else {
+                                                       // x & 0
+                                                       if ((right.constant != Constant.NotAConstant)
+                                                               && (right.constant.typeID() == T_long)
+                                                               && (right.constant.longValue() == 0L)) {
+                                                               left.generateCode(currentScope, codeStream, false);
+                                                               if (valueRequired)
+                                                                       codeStream.lconst_0();
+                                                       } else {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                                               if (valueRequired)
+                                                                       codeStream.land();
+                                                       }
+                                               }
+                                               break;
+                                       case T_boolean : // logical and
+                                               generateOptimizedLogicalAnd(
+                                                       currentScope,
+                                                       codeStream,
+                                                       null,
+                                                       (falseLabel = new Label(codeStream)),
+                                                       valueRequired);
+                                               /* improving code gen for such a case: boolean b = i < 0 && false;
+                                                * since the label has never been used, we have the inlined value on the stack. */
+                                               if (falseLabel.hasForwardReferences()) {
+                                                       if (valueRequired) {
+                                                               codeStream.iconst_1();
+                                                               if ((bits & ValueForReturnMASK) != 0) {
+                                                                       codeStream.ireturn();
+                                                                       falseLabel.place();
+                                                                       codeStream.iconst_0();
+                                                               } else {
+                                                                       codeStream.goto_(endLabel = new Label(codeStream));
+                                                                       codeStream.decrStackSize(1);
+                                                                       falseLabel.place();
+                                                                       codeStream.iconst_0();
+                                                                       endLabel.place();
+                                                               }
+                                                       } else {
+                                                               falseLabel.place();
+                                                       }
+                                               }
+                               }
+                               break;
+                       case OR :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               // 0 | x
+                                               if ((left.constant != Constant.NotAConstant)
+                                                       && (left.constant.typeID() == T_int)
+                                                       && (left.constant.intValue() == 0)) {
+                                                       right.generateCode(currentScope, codeStream, valueRequired);
+                                               } else {
+                                                       // x | 0
+                                                       if ((right.constant != Constant.NotAConstant)
+                                                               && (right.constant.typeID() == T_int)
+                                                               && (right.constant.intValue() == 0)) {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                       } else {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                                               if (valueRequired)
+                                                                       codeStream.ior();
+                                                       }
+                                               }
+                                               break;
+                                       case T_long :
+                                               // 0 | x
+                                               if ((left.constant != Constant.NotAConstant)
+                                                       && (left.constant.typeID() == T_long)
+                                                       && (left.constant.longValue() == 0L)) {
+                                                       right.generateCode(currentScope, codeStream, valueRequired);
+                                               } else {
+                                                       // x | 0
+                                                       if ((right.constant != Constant.NotAConstant)
+                                                               && (right.constant.typeID() == T_long)
+                                                               && (right.constant.longValue() == 0L)) {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                       } else {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                                               if (valueRequired)
+                                                                       codeStream.lor();
+                                                       }
+                                               }
+                                               break;
+                                       case T_boolean : // logical or
+                                               generateOptimizedLogicalOr(
+                                                       currentScope,
+                                                       codeStream,
+                                                       null,
+                                                       (falseLabel = new Label(codeStream)),
+                                                       valueRequired);
+                                               /* improving code gen for such a case: boolean b = i < 0 || true;
+                                                * since the label has never been used, we have the inlined value on the stack. */
+                                               if (falseLabel.hasForwardReferences()) {
+                                                       if (valueRequired) {
+                                                               codeStream.iconst_1();
+                                                               if ((bits & ValueForReturnMASK) != 0) {
+                                                                       codeStream.ireturn();
+                                                                       falseLabel.place();
+                                                                       codeStream.iconst_0();
+                                                               } else {
+                                                                       codeStream.goto_(endLabel = new Label(codeStream));
+                                                                       codeStream.decrStackSize(1);
+                                                                       falseLabel.place();
+                                                                       codeStream.iconst_0();
+                                                                       endLabel.place();
+                                                               }
+                                                       } else {
+                                                               falseLabel.place();
+                                                       }
+                                               }
+                               }
+                               break;
+                       case XOR :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               // 0 ^ x
+                                               if ((left.constant != Constant.NotAConstant)
+                                                       && (left.constant.typeID() == T_int)
+                                                       && (left.constant.intValue() == 0)) {
+                                                       right.generateCode(currentScope, codeStream, valueRequired);
+                                               } else {
+                                                       // x ^ 0
+                                                       if ((right.constant != Constant.NotAConstant)
+                                                               && (right.constant.typeID() == T_int)
+                                                               && (right.constant.intValue() == 0)) {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                       } else {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                                               if (valueRequired)
+                                                                       codeStream.ixor();
+                                                       }
+                                               }
+                                               break;
+                                       case T_long :
+                                               // 0 ^ x
+                                               if ((left.constant != Constant.NotAConstant)
+                                                       && (left.constant.typeID() == T_long)
+                                                       && (left.constant.longValue() == 0L)) {
+                                                       right.generateCode(currentScope, codeStream, valueRequired);
+                                               } else {
+                                                       // x ^ 0
+                                                       if ((right.constant != Constant.NotAConstant)
+                                                               && (right.constant.typeID() == T_long)
+                                                               && (right.constant.longValue() == 0L)) {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                       } else {
+                                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                                               if (valueRequired)
+                                                                       codeStream.lxor();
+                                                       }
+                                               }
+                                               break;
+                                       case T_boolean :
+                                               generateOptimizedLogicalXor(
+                                                       currentScope,
+                                                       codeStream,
+                                                       null,
+                                                       (falseLabel = new Label(codeStream)),
+                                                       valueRequired);
+                                               /* improving code gen for such a case: boolean b = i < 0 ^ bool;
+                                                * since the label has never been used, we have the inlined value on the stack. */
+                                               if (falseLabel.hasForwardReferences()) {
+                                                       if (valueRequired) {
+                                                               codeStream.iconst_1();
+                                                               if ((bits & ValueForReturnMASK) != 0) {
+                                                                       codeStream.ireturn();
+                                                                       falseLabel.place();
+                                                                       codeStream.iconst_0();
+                                                               } else {
+                                                                       codeStream.goto_(endLabel = new Label(codeStream));
+                                                                       codeStream.decrStackSize(1);
+                                                                       falseLabel.place();
+                                                                       codeStream.iconst_0();
+                                                                       endLabel.place();
+                                                               }
+                                                       } else {
+                                                               falseLabel.place();
+                                                       }
+                                               }
+                               }
+                               break;
+                       case LEFT_SHIFT :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.ishl();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.lshl();
+                               }
+                               break;
+                       case RIGHT_SHIFT :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.ishr();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.lshr();
+                               }
+                               break;
+                       case UNSIGNED_RIGHT_SHIFT :
+                               switch (bits & ReturnTypeIDMASK) {
+                                       case T_int :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.iushr();
+                                               break;
+                                       case T_long :
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired)
+                                                       codeStream.lushr();
+                               }
+                               break;
+                       case GREATER :
+                               generateOptimizedGreaterThan(
+                                       currentScope,
+                                       codeStream,
+                                       null,
+                                       (falseLabel = new Label(codeStream)),
+                                       valueRequired);
+                               if (valueRequired) {
+                                       codeStream.iconst_1();
+                                       if ((bits & ValueForReturnMASK) != 0) {
+                                               codeStream.ireturn();
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                       } else {
+                                               codeStream.goto_(endLabel = new Label(codeStream));
+                                               codeStream.decrStackSize(1);
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                               endLabel.place();
+                                       }
+                               }
+                               break;
+                       case GREATER_EQUAL :
+                               generateOptimizedGreaterThanOrEqual(
+                                       currentScope,
+                                       codeStream,
+                                       null,
+                                       (falseLabel = new Label(codeStream)),
+                                       valueRequired);
+                               if (valueRequired) {
+                                       codeStream.iconst_1();
+                                       if ((bits & ValueForReturnMASK) != 0) {
+                                               codeStream.ireturn();
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                       } else {
+                                               codeStream.goto_(endLabel = new Label(codeStream));
+                                               codeStream.decrStackSize(1);
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                               endLabel.place();
+                                       }
+                               }
+                               break;
+                       case LESS :
+                               generateOptimizedLessThan(
+                                       currentScope,
+                                       codeStream,
+                                       null,
+                                       (falseLabel = new Label(codeStream)),
+                                       valueRequired);
+                               if (valueRequired) {
+                                       codeStream.iconst_1();
+                                       if ((bits & ValueForReturnMASK) != 0) {
+                                               codeStream.ireturn();
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                       } else {
+                                               codeStream.goto_(endLabel = new Label(codeStream));
+                                               codeStream.decrStackSize(1);
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                               endLabel.place();
+                                       }
+                               }
+                               break;
+                       case LESS_EQUAL :
+                               generateOptimizedLessThanOrEqual(
+                                       currentScope,
+                                       codeStream,
+                                       null,
+                                       (falseLabel = new Label(codeStream)),
+                                       valueRequired);
+                               if (valueRequired) {
+                                       codeStream.iconst_1();
+                                       if ((bits & ValueForReturnMASK) != 0) {
+                                               codeStream.ireturn();
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                       } else {
+                                               codeStream.goto_(endLabel = new Label(codeStream));
+                                               codeStream.decrStackSize(1);
+                                               falseLabel.place();
+                                               codeStream.iconst_0();
+                                               endLabel.place();
+                                       }
+                               }
+               }
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(implicitConversion);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /**
+        * Boolean operator code generation
+        *      Optimized operations are: <, <=, >, >=, &, |, ^
+        */
+       public void generateOptimizedBoolean(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
+                       super.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               trueLabel,
+                               falseLabel,
+                               valueRequired);
+                       return;
+               }
+               switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+                       case LESS :
+                               generateOptimizedLessThan(
+                                       currentScope,
+                                       codeStream,
+                                       trueLabel,
+                                       falseLabel,
+                                       valueRequired);
+                               return;
+                       case LESS_EQUAL :
+                               generateOptimizedLessThanOrEqual(
+                                       currentScope,
+                                       codeStream,
+                                       trueLabel,
+                                       falseLabel,
+                                       valueRequired);
+                               return;
+                       case GREATER :
+                               generateOptimizedGreaterThan(
+                                       currentScope,
+                                       codeStream,
+                                       trueLabel,
+                                       falseLabel,
+                                       valueRequired);
+                               return;
+                       case GREATER_EQUAL :
+                               generateOptimizedGreaterThanOrEqual(
+                                       currentScope,
+                                       codeStream,
+                                       trueLabel,
+                                       falseLabel,
+                                       valueRequired);
+                               return;
+                       case AND :
+                               generateOptimizedLogicalAnd(
+                                       currentScope,
+                                       codeStream,
+                                       trueLabel,
+                                       falseLabel,
+                                       valueRequired);
+                               return;
+                       case OR :
+                               generateOptimizedLogicalOr(
+                                       currentScope,
+                                       codeStream,
+                                       trueLabel,
+                                       falseLabel,
+                                       valueRequired);
+                               return;
+                       case XOR :
+                               generateOptimizedLogicalXor(
+                                       currentScope,
+                                       codeStream,
+                                       trueLabel,
+                                       falseLabel,
+                                       valueRequired);
+                               return;
+               }
+               super.generateOptimizedBoolean(
+                       currentScope,
+                       codeStream,
+                       trueLabel,
+                       falseLabel,
+                       valueRequired);
+       }
+
+       /**
+        * Boolean generation for >
+        */
+       public void generateOptimizedGreaterThan(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               int promotedTypeID = left.implicitConversion >> 4;
+               // both sides got promoted in the same way
+               if (promotedTypeID == T_int) {
+                       // 0 > x
+                       if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+                               right.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.iflt(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.ifge(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               // reposition the endPC
+                               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               return;
+                       }
+                       // x > 0
+                       if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+                               left.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.ifgt(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.ifle(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               // reposition the endPC
+                               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               return;
+                       }
+               }
+               // default comparison
+               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 (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmpgt(trueLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpl();
+                                                       codeStream.ifgt(trueLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.ifgt(trueLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpl();
+                                                       codeStream.ifgt(trueLabel);
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                                       return;
+                               }
+                       } else {
+                               if (trueLabel == null) {
+                                       // implicit falling through the TRUE case
+                                       switch (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmple(falseLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpl();
+                                                       codeStream.ifle(falseLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.ifle(falseLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpl();
+                                                       codeStream.ifle(falseLabel);
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                                       return;
+                               } else {
+                                       // no implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Boolean generation for >=
+        */
+       public void generateOptimizedGreaterThanOrEqual(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               int promotedTypeID = left.implicitConversion >> 4;
+               // both sides got promoted in the same way
+               if (promotedTypeID == T_int) {
+                       // 0 >= x
+                       if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+                               right.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.ifle(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.ifgt(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               // reposition the endPC
+                               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               return;
+                       }
+                       // x >= 0
+                       if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+                               left.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.ifge(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.iflt(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               // reposition the endPC
+                               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               return;
+                       }
+               }
+               // default comparison
+               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 (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmpge(trueLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpl();
+                                                       codeStream.ifge(trueLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.ifge(trueLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpl();
+                                                       codeStream.ifge(trueLabel);
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                                       return;
+                               }
+                       } else {
+                               if (trueLabel == null) {
+                                       // implicit falling through the TRUE case
+                                       switch (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmplt(falseLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpl();
+                                                       codeStream.iflt(falseLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.iflt(falseLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpl();
+                                                       codeStream.iflt(falseLabel);
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                                       return;
+                               } else {
+                                       // no implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Boolean generation for <
+        */
+       public void generateOptimizedLessThan(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               int promotedTypeID = left.implicitConversion >> 4;
+               // both sides got promoted in the same way
+               if (promotedTypeID == T_int) {
+                       // 0 < x
+                       if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+                               right.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.ifgt(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.ifle(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                               return;
+                       }
+                       // x < 0
+                       if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+                               left.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.iflt(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.ifge(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                               return;
+                       }
+               }
+               // default comparison
+               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 (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmplt(trueLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpg();
+                                                       codeStream.iflt(trueLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.iflt(trueLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpg();
+                                                       codeStream.iflt(trueLabel);
+                                       }
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);
+                                       return;
+                               }
+                       } else {
+                               if (trueLabel == null) {
+                                       // implicit falling through the TRUE case
+                                       switch (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmpge(falseLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpg();
+                                                       codeStream.ifge(falseLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.ifge(falseLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpg();
+                                                       codeStream.ifge(falseLabel);
+                                       }
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);
+                                       return;
+                               } else {
+                                       // no implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Boolean generation for <=
+        */
+       public void generateOptimizedLessThanOrEqual(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               int promotedTypeID = left.implicitConversion >> 4;
+               // both sides got promoted in the same way
+               if (promotedTypeID == T_int) {
+                       // 0 <= x
+                       if ((left.constant != NotAConstant) && (left.constant.intValue() == 0)) {
+                               right.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.ifge(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.iflt(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               // reposition the endPC
+                               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               return;
+                       }
+                       // x <= 0
+                       if ((right.constant != NotAConstant) && (right.constant.intValue() == 0)) {
+                               left.generateCode(currentScope, codeStream, valueRequired);
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               if (trueLabel != null) {
+                                                       // implicitly falling through the FALSE case
+                                                       codeStream.ifle(trueLabel);
+                                               }
+                                       } else {
+                                               if (trueLabel == null) {
+                                                       // implicitly falling through the TRUE case
+                                                       codeStream.ifgt(falseLabel);
+                                               } else {
+                                                       // no implicit fall through TRUE/FALSE --> should never occur
+                                               }
+                                       }
+                               }
+                               // reposition the endPC
+                               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               return;
+                       }
+               }
+               // default comparison
+               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 (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmple(trueLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpg();
+                                                       codeStream.ifle(trueLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.ifle(trueLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpg();
+                                                       codeStream.ifle(trueLabel);
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                                       return;
+                               }
+                       } else {
+                               if (trueLabel == null) {
+                                       // implicit falling through the TRUE case
+                                       switch (promotedTypeID) {
+                                               case T_int :
+                                                       codeStream.if_icmpgt(falseLabel);
+                                                       break;
+                                               case T_float :
+                                                       codeStream.fcmpg();
+                                                       codeStream.ifgt(falseLabel);
+                                                       break;
+                                               case T_long :
+                                                       codeStream.lcmp();
+                                                       codeStream.ifgt(falseLabel);
+                                                       break;
+                                               case T_double :
+                                                       codeStream.dcmpg();
+                                                       codeStream.ifgt(falseLabel);
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                                       return;
+                               } else {
+                                       // no implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+       }
+       
+       /**
+        * Boolean generation for &
+        */
+       public void generateOptimizedLogicalAnd(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+                       
+               Constant condConst;
+               if ((left.implicitConversion & 0xF) == T_boolean) {
+                       if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+                               if (condConst.booleanValue() == true) {
+                                       // <something equivalent to true> & x
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       if ((bits & OnlyValueRequiredMASK) != 0) {
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                       } else {
+                                               right.generateOptimizedBoolean(
+                                                       currentScope,
+                                                       codeStream,
+                                                       trueLabel,
+                                                       falseLabel,
+                                                       valueRequired);
+                                       }
+                               } else {
+                                       // <something equivalent to false> & x
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       Label internalTrueLabel = new Label(codeStream);
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       internalTrueLabel.place();
+                                       if (valueRequired) {
+                                               if ((bits & OnlyValueRequiredMASK) != 0) {
+                                                       codeStream.iconst_0();
+                                               } else {
+                                                       if (falseLabel != null) {
+                                                               // implicit falling through the TRUE case
+                                                               codeStream.goto_(falseLabel);
+                                                       }
+                                               }
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               }
+                               return;
+                       }
+                       if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+                               if (condConst.booleanValue() == true) {
+                                       // x & <something equivalent to true>
+                                       if ((bits & OnlyValueRequiredMASK) != 0) {
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                       } else {
+                                               left.generateOptimizedBoolean(
+                                                       currentScope,
+                                                       codeStream,
+                                                       trueLabel,
+                                                       falseLabel,
+                                                       valueRequired);
+                                       }
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                               } else {
+                                       // x & <something equivalent to false>
+                                       Label internalTrueLabel = new Label(codeStream);
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               internalTrueLabel,
+                                               falseLabel,
+                                               false);
+                                       internalTrueLabel.place();
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       if (valueRequired) {
+                                               if ((bits & OnlyValueRequiredMASK) != 0) {
+                                                       codeStream.iconst_0();
+                                               } else {
+                                                       if (falseLabel != null) {
+                                                               // implicit falling through the TRUE case
+                                                               codeStream.goto_(falseLabel);
+                                                       }
+                                               }
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               }
+                               return;
+                       }
+               }
+               // default case
+               left.generateCode(currentScope, codeStream, valueRequired);
+               right.generateCode(currentScope, codeStream, valueRequired);
+               if (valueRequired) {
+                       codeStream.iand();
+                       if ((bits & OnlyValueRequiredMASK) == 0) {
+                               if (falseLabel == null) {
+                                       if (trueLabel != null) {
+                                               // implicit falling through the FALSE case
+                                               codeStream.ifne(trueLabel);
+                                       }
+                               } else {
+                                       // implicit falling through the TRUE case
+                                       if (trueLabel == null) {
+                                               codeStream.ifeq(falseLabel);
+                                       } else {
+                                               // no implicit fall through TRUE/FALSE --> should never occur
+                                       }
+                               }
+                       }
+               }
+               // reposition the endPC
+               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+       }
+       
+       /**
+        * Boolean generation for |
+        */
+       public void generateOptimizedLogicalOr(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+                       
+               Constant condConst;
+               if ((left.implicitConversion & 0xF) == T_boolean) {
+                       if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+                               if (condConst.booleanValue() == true) {
+                                       // <something equivalent to true> | x
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       Label internalFalseLabel = new Label(codeStream);
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               internalFalseLabel,
+                                               false);
+                                       internalFalseLabel.place();
+                                       if (valueRequired) {
+                                               if ((bits & OnlyValueRequiredMASK) != 0) {
+                                                       codeStream.iconst_1();
+                                               } else {
+                                                       if (trueLabel != null) {
+                                                               codeStream.goto_(trueLabel);
+                                                       }
+                                               }
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               } else {
+                                       // <something equivalent to false> | x
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       if ((bits & OnlyValueRequiredMASK) != 0) {
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                       } else {
+                                               right.generateOptimizedBoolean(
+                                                       currentScope,
+                                                       codeStream,
+                                                       trueLabel,
+                                                       falseLabel,
+                                                       valueRequired);
+                                       }
+                               }
+                               return;
+                       }
+                       if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+                               if (condConst.booleanValue() == true) {
+                                       // x | <something equivalent to true>
+                                       Label internalFalseLabel = new Label(codeStream);
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               internalFalseLabel,
+                                               false);
+                                       internalFalseLabel.place();
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       if (valueRequired) {
+                                               if ((bits & OnlyValueRequiredMASK) != 0) {
+                                                       codeStream.iconst_1();
+                                               } else {
+                                                       if (trueLabel != null) {
+                                                               codeStream.goto_(trueLabel);
+                                                       }
+                                               }
+                                       }
+                                       // reposition the endPC
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+                               } else {
+                                       // x | <something equivalent to false>
+                                       if ((bits & OnlyValueRequiredMASK) != 0) {
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                       } else {
+                                               left.generateOptimizedBoolean(
+                                                       currentScope,
+                                                       codeStream,
+                                                       trueLabel,
+                                                       falseLabel,
+                                                       valueRequired);
+                                       }
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                               }
+                               return;
+                       }
+               }
+               // default case
+               left.generateCode(currentScope, codeStream, valueRequired);
+               right.generateCode(currentScope, codeStream, valueRequired);
+               if (valueRequired) {
+                       codeStream.ior();
+                       if ((bits & OnlyValueRequiredMASK) == 0) {
+                               if (falseLabel == null) {
+                                       if (trueLabel != null) {
+                                               // implicit falling through the FALSE case
+                                               codeStream.ifne(trueLabel);
+                                       }
+                               } else {
+                                       // implicit falling through the TRUE case
+                                       if (trueLabel == null) {
+                                               codeStream.ifeq(falseLabel);
+                                       } else {
+                                               // no implicit fall through TRUE/FALSE --> should never occur
+                                       }
+                               }
+                       }
+               }
+               // reposition the endPC
+               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+       }
+       
+       /**
+        * Boolean generation for ^
+        */
+       public void generateOptimizedLogicalXor(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+                       
+               Constant condConst;
+               if ((left.implicitConversion & 0xF) == T_boolean) {
+                       if ((condConst = left.optimizedBooleanConstant()) != NotAConstant) {
+                               if (condConst.booleanValue() == true) {
+                                       // <something equivalent to true> ^ x
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               falseLabel,
+                                               trueLabel,
+                                               valueRequired);
+                               } else {
+                                       // <something equivalent to false> ^ x
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                                       if ((bits & OnlyValueRequiredMASK) != 0) {
+                                               right.generateCode(currentScope, codeStream, valueRequired);
+                                       } else {
+                                               right.generateOptimizedBoolean(
+                                                       currentScope,
+                                                       codeStream,
+                                                       trueLabel,
+                                                       falseLabel,
+                                                       valueRequired);
+                                       }
+                               }
+                               return;
+                       }
+                       if ((condConst = right.optimizedBooleanConstant()) != NotAConstant) {
+                               if (condConst.booleanValue() == true) {
+                                       // x ^ <something equivalent to true>
+                                       left.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               falseLabel,
+                                               trueLabel,
+                                               valueRequired);
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                               } else {
+                                       // x ^ <something equivalent to false>
+                                       if ((bits & OnlyValueRequiredMASK) != 0) {
+                                               left.generateCode(currentScope, codeStream, valueRequired);
+                                       } else {
+                                               left.generateOptimizedBoolean(
+                                                       currentScope,
+                                                       codeStream,
+                                                       trueLabel,
+                                                       falseLabel,
+                                                       valueRequired);
+                                       }
+                                       right.generateOptimizedBoolean(
+                                               currentScope,
+                                               codeStream,
+                                               trueLabel,
+                                               falseLabel,
+                                               false);
+                               }
+                               return;
+                       }
+               }
+               // default case
+               left.generateCode(currentScope, codeStream, valueRequired);
+               right.generateCode(currentScope, codeStream, valueRequired);
+               if (valueRequired) {
+                       codeStream.ixor();
+                       if ((bits & OnlyValueRequiredMASK) == 0) {
+                               if (falseLabel == null) {
+                                       if (trueLabel != null) {
+                                               // implicit falling through the FALSE case
+                                               codeStream.ifne(trueLabel);
+                                       }
+                               } else {
+                                       // implicit falling through the TRUE case
+                                       if (trueLabel == null) {
+                                               codeStream.ifeq(falseLabel);
+                                       } else {
+                                               // no implicit fall through TRUE/FALSE --> should never occur
+                                       }
+                               }
+                       }
+               }
+               // reposition the endPC
+               codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+       }
+       
+       public void generateOptimizedStringBuffer(
+               BlockScope blockScope,
+               CodeStream codeStream,
+               int typeID) {
+                       
+               /* In the case trying to make a string concatenation, there is no need to create a new
+                * string buffer, thus use a lower-level API for code generation involving only the
+                * appending of arguments to the existing StringBuffer
+                */
+
+               if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
+                       && ((bits & ReturnTypeIDMASK) == T_String)) {
+                       if (constant != NotAConstant) {
+                               codeStream.generateConstant(constant, implicitConversion);
+                               codeStream.invokeStringBufferAppendForType(implicitConversion & 0xF);
+                       } else {
+                               int pc = codeStream.position;
+                               left.generateOptimizedStringBuffer(
+                                       blockScope,
+                                       codeStream,
+                                       left.implicitConversion & 0xF);
+                               codeStream.recordPositionsFrom(pc, left.sourceStart);
+                               pc = codeStream.position;
+                               right.generateOptimizedStringBuffer(
+                                       blockScope,
+                                       codeStream,
+                                       right.implicitConversion & 0xF);
+                               codeStream.recordPositionsFrom(pc, right.sourceStart);
+                       }
+               } else {
+                       super.generateOptimizedStringBuffer(blockScope, codeStream, typeID);
+               }
+       }
+       
+       public void generateOptimizedStringBufferCreation(
+               BlockScope blockScope,
+               CodeStream codeStream,
+               int typeID) {
+                       
+               /* In the case trying to make a string concatenation, there is no need to create a new
+                * string buffer, thus use a lower-level API for code generation involving only the 
+                * appending of arguments to the existing StringBuffer
+                */
+
+               if ((((bits & OperatorMASK) >> OperatorSHIFT) == PLUS)
+                       && ((bits & ReturnTypeIDMASK) == T_String)) {
+                       if (constant != NotAConstant) {
+                               codeStream.newStringBuffer(); // new: java.lang.StringBuffer
+                               codeStream.dup();
+                               codeStream.ldc(constant.stringValue());
+                               codeStream.invokeStringBufferStringConstructor();
+                               // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
+                       } else {
+                               int pc = codeStream.position;
+                               left.generateOptimizedStringBufferCreation(
+                                       blockScope,
+                                       codeStream,
+                                       left.implicitConversion & 0xF);
+                               codeStream.recordPositionsFrom(pc, left.sourceStart);
+                               pc = codeStream.position;
+                               right.generateOptimizedStringBuffer(
+                                       blockScope,
+                                       codeStream,
+                                       right.implicitConversion & 0xF);
+                               codeStream.recordPositionsFrom(pc, right.sourceStart);
+                       }
+               } else {
+                       super.generateOptimizedStringBufferCreation(blockScope, codeStream, typeID);
+               }
+       }
+       
+       public boolean isCompactableOperation() {
+               
+               return true;
+       }
+       
+       public void optimizedBooleanConstant(int leftId, int operator, int rightId) {
+
+               switch (operator) {
+                       case AND :
+                               if ((leftId != T_boolean) || (rightId != T_boolean))
+                                       return;
+                       case AND_AND :
+                               Constant cst;
+                               if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
+                                       if (cst.booleanValue() == false) { // left is equivalent to false
+                                               optimizedBooleanConstant = cst; // constant(false)
+                                               return;
+                                       } else { //left is equivalent to true
+                                               if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+                                                       optimizedBooleanConstant = cst;
+                                                       // the conditional result is equivalent to the right conditional value
+                                               }
+                                               return;
+                                       }
+                               }
+                               if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+                                       if (cst.booleanValue() == false) { // right is equivalent to false
+                                               optimizedBooleanConstant = cst; // constant(false)
+                                       }
+                               }
+                               return;
+                       case OR :
+                               if ((leftId != T_boolean) || (rightId != T_boolean))
+                                       return;
+                       case OR_OR :
+                               if ((cst = left.optimizedBooleanConstant()) != NotAConstant) {
+                                       if (cst.booleanValue() == true) { // left is equivalent to true
+                                               optimizedBooleanConstant = cst; // constant(true)
+                                               return;
+                                       } else { //left is equivalent to false
+                                               if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+                                                       optimizedBooleanConstant = cst;
+                                               }
+                                               return;
+                                       }
+                               }
+                               if ((cst = right.optimizedBooleanConstant()) != NotAConstant) {
+                                       if (cst.booleanValue() == true) { // right is equivalent to true
+                                               optimizedBooleanConstant = cst; // constant(true)
+                                       }
+                               }
+               }
+       }
+
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+               left.printExpression(indent, output).append(' ').append(operatorToString()).append(' ');
+               return right.printExpression(0, output);
+       }
+               
+       public TypeBinding resolveType(BlockScope scope) {
+
+               boolean leftIsCast, rightIsCast;
+               if ((leftIsCast = left instanceof CastExpression) == true) left.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+               TypeBinding leftType = left.resolveType(scope);
+
+               if ((rightIsCast = right instanceof CastExpression) == true) right.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+               TypeBinding rightType = right.resolveType(scope);
+
+               // use the id of the type to navigate into the table
+               if (leftType == null || rightType == null) {
+                       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;
+                       } else {
+                               constant = Constant.NotAConstant;
+                               scope.problemReporter().invalidOperator(this, leftType, rightType);
+                               return null;
+                       }
+               }
+               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);
+                       }
+               }
+
+               // the code is an int
+               // (cast)  left   Op (cast)  right --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       <<0
+
+               // Don't test for result = 0. If it is zero, some more work is done.
+               // On the one hand when it is not zero (correct code) we avoid doing the test   
+               int operator = (bits & OperatorMASK) >> OperatorSHIFT;
+               int operatorSignature = OperatorSignatures[operator][(leftTypeId << 4) + rightTypeId];
+               left.implicitConversion = operatorSignature >>> 12;
+               right.implicitConversion = (operatorSignature >>> 4) & 0x000FF;
+
+               bits |= operatorSignature & 0xF;
+               switch (operatorSignature & 0xF) { // record the current ReturnTypeID
+                       // only switch on possible result type.....
+                       case T_boolean :
+                               this.resolvedType = BooleanBinding;
+                               break;
+                       case T_byte :
+                               this.resolvedType = ByteBinding;
+                               break;
+                       case T_char :
+                               this.resolvedType = CharBinding;
+                               break;
+                       case T_double :
+                               this.resolvedType = DoubleBinding;
+                               break;
+                       case T_float :
+                               this.resolvedType = FloatBinding;
+                               break;
+                       case T_int :
+                               this.resolvedType = IntBinding;
+                               break;
+                       case T_long :
+                               this.resolvedType = LongBinding;
+                               break;
+                       case T_String :
+                               this.resolvedType = scope.getJavaLangString();
+                               break;
+                       default : //error........
+                               constant = Constant.NotAConstant;
+                               scope.problemReporter().invalidOperator(this, leftType, rightType);
+                               return null;
+               }
+
+               // check need for operand cast
+               if (leftIsCast || rightIsCast) {
+                       CastExpression.checkNeedForArgumentCasts(scope, operator, operatorSignature, left, leftTypeId, leftIsCast, right, rightTypeId, rightIsCast);
+               }
+               // compute the constant when valid
+               computeConstant(scope, leftTypeId, rightTypeId);
+               return this.resolvedType;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               if (visitor.visit(this, scope)) {
+                       left.traverse(visitor, scope);
+                       right.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Block.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Block.java
new file mode 100644 (file)
index 0000000..f9170be
--- /dev/null
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class Block extends Statement {
+       
+       public Statement[] statements;
+       public int explicitDeclarations;
+       // the number of explicit declaration , used to create scope
+       public BlockScope scope;
+       
+       public Block(int explicitDeclarations) {
+               this.explicitDeclarations = explicitDeclarations;
+       }
+       
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // empty block
+               if (statements == null) return flowInfo;
+               boolean didAlreadyComplain = false;
+               for (int i = 0, max = statements.length; i < max; i++) {
+                       Statement stat = statements[i];
+                       if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
+                               flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
+                       } else {
+                               didAlreadyComplain = true;
+                       }
+               }
+               return flowInfo;
+       }
+       /**
+        * Code generation for a block
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+               if ((bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               int pc = codeStream.position;
+               if (statements != null) {
+                       for (int i = 0, max = statements.length; i < max; i++) {
+                               statements[i].generateCode(scope, codeStream);
+                       }
+               } // for local variable debug attributes
+               if (scope != currentScope) { // was really associated with its own scope
+                       codeStream.exitUserScope(scope);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public boolean isEmptyBlock() {
+
+               return statements == null;
+       }
+
+       public StringBuffer printBody(int indent, StringBuffer output) {
+
+               if (this.statements == null) return output;
+               for (int i = 0; i < statements.length; i++) {
+                       statements[i].printStatement(indent + 1, output);
+                       output.append('\n'); 
+               }
+               return output;
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               printIndent(indent, output);
+               output.append("{\n"); //$NON-NLS-1$
+               printBody(indent, output);
+               return printIndent(indent, output).append('}');
+       }
+
+       public void resolve(BlockScope upperScope) {
+
+               if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+                       upperScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd);
+               }
+               if (statements != null) {
+                       scope =
+                               explicitDeclarations == 0
+                                       ? upperScope
+                                       : new BlockScope(upperScope, explicitDeclarations);
+                       for (int i = 0, length = statements.length; i < length; i++) {
+                               statements[i].resolve(scope);
+                       }
+               }
+       }
+
+       public void resolveUsing(BlockScope givenScope) {
+
+               if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+                       givenScope.problemReporter().undocumentedEmptyBlock(this.sourceStart, this.sourceEnd);
+               }
+               // this optimized resolve(...) is sent only on none empty blocks
+               scope = givenScope;
+               if (statements != null) {
+                       for (int i = 0, length = statements.length; i < length; i++) {
+                               statements[i].resolve(scope);
+                       }
+               }
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       if (statements != null) {
+                               for (int i = 0, length = statements.length; i < length; i++)
+                                       statements[i].traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, blockScope);
+       }
+       
+       /**
+        * Dispatch the call on its last statement.
+        */
+       public void branchChainTo(Label label) {
+                if (this.statements != null) {
+                       this.statements[statements.length - 1].branchChainTo(label);
+                }
+       }
+       
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/BranchStatement.java
new file mode 100644 (file)
index 0000000..2dede48
--- /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.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public abstract class BranchStatement extends Statement {
+       public char[] label;
+       public Label targetLabel;
+       public SubRoutineStatement[] subroutines;
+/**
+ * BranchStatement constructor comment.
+ */
+public BranchStatement(char[] l, int s,int e) {
+       label = l ;
+       sourceStart = s;
+       sourceEnd = e;
+}
+/**
+ * Branch code generation
+ *
+ *   generate the finallyInvocationSequence.
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+       if ((bits & IsReachableMASK) == 0) {
+               return;
+       }
+       int pc = codeStream.position;
+
+       // generation of code responsible for invoking the finally 
+       // blocks in sequence
+       if (subroutines != null){
+               for (int i = 0, max = subroutines.length; i < max; i++){
+                       SubRoutineStatement sub = subroutines[i];
+                       sub.generateSubRoutineInvocation(currentScope, codeStream);
+                       if (sub.isSubRoutineEscaping()) {
+                                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                                       SubRoutineStatement.reenterExceptionHandlers(subroutines, i, codeStream);
+                                       return;
+                       }
+                       sub.exitAnyExceptionHandler();
+               }
+       }
+       codeStream.goto_(targetLabel);
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+       SubRoutineStatement.reenterExceptionHandlers(subroutines, -1, codeStream);
+}
+public void resolve(BlockScope scope) {
+       // nothing to do during name resolution
+}
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/BreakStatement.java
new file mode 100644 (file)
index 0000000..dab79fe
--- /dev/null
@@ -0,0 +1,95 @@
+/*******************************************************************************
+ * 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.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class BreakStatement extends BranchStatement {
+       
+       public BreakStatement(char[] label, int sourceStart, int e) {
+               super(label, sourceStart, e);
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // here requires to generate a sequence of finally blocks invocations depending corresponding
+               // to each of the traversed try statements, so that execution will terminate properly.
+
+               // lookup the label, this should answer the returnContext
+               FlowContext targetContext = (label == null) 
+                       ? flowContext.getTargetContextForDefaultBreak()
+                       : flowContext.getTargetContextForBreakLabel(label);
+
+               if (targetContext == null) {
+                       if (label == null) {
+                               currentScope.problemReporter().invalidBreak(this);
+                       } else {
+                               currentScope.problemReporter().undefinedLabel(this); 
+                       }
+                       return flowInfo; // pretend it did not break since no actual target
+               }
+               
+               targetLabel = targetContext.breakLabel();
+               FlowContext traversedContext = flowContext;
+               int subIndex = 0, maxSub = 5;
+               subroutines = new SubRoutineStatement[maxSub];
+               
+               do {
+                       SubRoutineStatement sub;
+                       if ((sub = traversedContext.subRoutine()) != null) {
+                               if (subIndex == maxSub) {
+                                       System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[maxSub*=2]), 0, subIndex); // grow
+                               }
+                               subroutines[subIndex++] = sub;
+                               if (sub.isSubRoutineEscaping()) {
+                                       break;
+                               }
+                       }
+                       traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+
+                       ASTNode node;
+                       if ((node = traversedContext.associatedNode) instanceof TryStatement) {
+                               TryStatement tryStatement = (TryStatement) node;
+                               flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits                 
+                       } else if (traversedContext == targetContext) {
+                               // only record break info once accumulated through subroutines, and only against target context
+                               targetContext.recordBreakFrom(flowInfo);
+                               break;
+                       }
+               } while ((traversedContext = traversedContext.parent) != null);
+               
+               // resize subroutines
+               if (subIndex != maxSub) {
+                       System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[subIndex]), 0, subIndex);
+               }
+               return FlowInfo.DEAD_END;
+       }
+       
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+
+               printIndent(tab, output).append("break "); //$NON-NLS-1$
+               if (label != null) output.append(label);
+               return output.append(';');
+       }
+       
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockscope) {
+
+               visitor.visit(this, blockscope);
+               visitor.endVisit(this, blockscope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/CaseStatement.java
new file mode 100644 (file)
index 0000000..56380f7
--- /dev/null
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CaseStatement extends Statement {
+       
+       public Expression constantExpression;
+       public CaseLabel targetLabel;
+       public CaseStatement(Expression constantExpression, int sourceEnd, int sourceStart) {
+               this.constantExpression = constantExpression;
+               this.sourceEnd = sourceEnd;
+               this.sourceStart = sourceStart;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               if (constantExpression != null) {
+                       if (constantExpression.constant == NotAConstant) {
+                               currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
+                       }
+                       this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
+               }
+               return flowInfo;
+       }
+
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+
+               printIndent(tab, output);
+               if (constantExpression == null) {
+                       output.append("default : "); //$NON-NLS-1$
+               } else {
+                       output.append("case "); //$NON-NLS-1$
+                       constantExpression.printExpression(0, output).append(" : "); //$NON-NLS-1$
+               }
+               return output.append(';');
+       }
+       
+       /**
+        * Case code generation
+        *
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+               if ((bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               int pc = codeStream.position;
+               targetLabel.place();
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /**
+        * No-op : should use resolveCase(...) instead.
+        */
+       public void resolve(BlockScope scope) {
+               // no-op : should use resolveCase(...) instead.
+       }
+
+       public Constant resolveCase(
+               BlockScope scope,
+               TypeBinding switchType,
+               SwitchStatement switchStatement) {
+
+           scope.switchCase = this; // record entering in a switch case block
+           
+               if (constantExpression == null) {
+                       // remember the default case into the associated switch statement
+                       if (switchStatement.defaultCase != null)
+                               scope.problemReporter().duplicateDefaultCase(this);
+       
+                       // on error the last default will be the selected one ...       
+                       switchStatement.defaultCase = this;
+                       return null;
+               }
+               // add into the collection of cases of the associated switch statement
+               switchStatement.cases[switchStatement.caseCount++] = this;
+               TypeBinding caseType = constantExpression.resolveType(scope);
+               if (caseType == null || switchType == null) return null;
+               if (constantExpression.isConstantValueOfTypeAssignableToType(caseType, switchType))
+                       return constantExpression.constant;
+               if (caseType.isCompatibleWith(switchType))
+                       return constantExpression.constant;
+               scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+                       constantExpression,
+                       caseType,
+                       switchType);
+               return null;
+       }
+
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       if (constantExpression != null) constantExpression.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
new file mode 100644 (file)
index 0000000..ecfe767
--- /dev/null
@@ -0,0 +1,512 @@
+/*******************************************************************************
+ * 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
+ *     Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+public class CastExpression extends Expression {
+
+       public Expression expression;
+       public Expression type;
+       
+       //expression.implicitConversion holds the cast for baseType casting 
+       public CastExpression(Expression expression, Expression type) {
+               this.expression = expression;
+               this.type = type;
+
+               //due to the fact an expression may start with ( and that a cast also start with (
+               //the field is an expression....it can be a TypeReference OR a NameReference Or
+               //an expression <--this last one is invalid.......
+
+               //if (type instanceof TypeReference )
+               //      flag = IsTypeReference ;
+               //else
+               //      if (type instanceof NameReference)
+               //              flag = IsNameReference ;
+               //      else
+               //              flag = IsExpression ;
+
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return expression
+                       .analyseCode(currentScope, flowContext, flowInfo)
+                       .unconditionalInits();
+       }
+
+       /**
+        * 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) {
+       
+               if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+               
+               TypeBinding castedExpressionType = ((CastExpression)enclosingInstance).expression.resolvedType;
+               if (castedExpressionType == null) return; // cannot do better
+               // obvious identity cast
+               if (castedExpressionType == enclosingInstanceType) { 
+                       scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance);
+               } else if (castedExpressionType == NullBinding){
+                       return; // tolerate null enclosing instance cast
+               } else {
+                       TypeBinding alternateEnclosingInstanceType = castedExpressionType; 
+                       if (castedExpressionType.isBaseType() || castedExpressionType.isArrayType()) return; // error case
+                       if (memberType == scope.getMemberType(memberType.sourceName(), (ReferenceBinding) alternateEnclosingInstanceType)) {
+                               scope.problemReporter().unnecessaryCast((CastExpression)enclosingInstance);
+                       }
+               }
+       }
+
+       /**
+        * Only complain for identity cast, since other type of casts may be useful: e.g.  ~((~(long) 0) << 32)  is different from: ~((~0) << 32) 
+        */
+       public static void checkNeedForArgumentCast(BlockScope scope, int operator, int operatorSignature, Expression expression, int expressionTypeId) {
+       
+               if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+       
+               // check need for left operand cast
+               int alternateLeftTypeId = expressionTypeId;
+               if ((expression.bits & UnnecessaryCastMask) == 0 && expression.resolvedType.isBaseType()) {
+                       // narrowing conversion on base type may change value, thus necessary
+                       return;
+               } else  {
+                       TypeBinding alternateLeftType = ((CastExpression)expression).expression.resolvedType;
+                       if (alternateLeftType == null) return; // cannot do better
+                       if ((alternateLeftTypeId = alternateLeftType.id) == expressionTypeId) { // obvious identity cast
+                               scope.problemReporter().unnecessaryCast((CastExpression)expression); 
+                               return;
+                       } else if (alternateLeftTypeId == T_null) {
+                               alternateLeftTypeId = expressionTypeId;  // tolerate null argument cast
+                               return;
+                       }
+               }
+/*             tolerate widening cast in unary expressions, as may be used when combined in binary expressions (41680)
+               int alternateOperatorSignature = OperatorExpression.OperatorSignatures[operator][(alternateLeftTypeId << 4) + alternateLeftTypeId];
+               // (cast)  left   Op (cast)  right --> result
+               //  1111   0000       1111   0000     1111
+               //  <<16   <<12       <<8    <<4       <<0
+               final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types
+               if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result
+                       scope.problemReporter().unnecessaryCastForArgument((CastExpression)expression,  TypeBinding.wellKnownType(scope, expression.implicitConversion >> 4)); 
+               }
+*/             
+       }
+               
+       /**
+        * Cast expressions will considered as useful if removing them all would actually bind to a different method
+        * (no fine grain analysis on per casted argument basis, simply separate widening cast from narrowing ones)
+        */
+       public static void checkNeedForArgumentCasts(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] argumentTypes, final InvocationSite invocationSite) {
+       
+               if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+               
+               int length = argumentTypes.length;
+
+               // iterate over arguments, and retrieve original argument types (before cast)
+               TypeBinding[] rawArgumentTypes = argumentTypes;
+               for (int i = 0; i < length; i++) {
+                       Expression argument = arguments[i];
+                       if (argument instanceof CastExpression) {
+                               // narrowing conversion on base type may change value, thus necessary
+                               if ((argument.bits & UnnecessaryCastMask) == 0 && argument.resolvedType.isBaseType()) {
+                                       continue;
+                               }               
+                               TypeBinding castedExpressionType = ((CastExpression)argument).expression.resolvedType;
+                               if (castedExpressionType == null) return; // cannot do better
+                               // obvious identity cast
+                               if (castedExpressionType == argumentTypes[i]) { 
+                                       scope.problemReporter().unnecessaryCast((CastExpression)argument);
+                               } else if (castedExpressionType == NullBinding){
+                                       continue; // tolerate null argument cast
+                               } else {
+                                       if (rawArgumentTypes == argumentTypes) {
+                                               System.arraycopy(rawArgumentTypes, 0, rawArgumentTypes = new TypeBinding[length], 0, length);
+                                       }
+                                       // retain original argument type
+                                       rawArgumentTypes[i] = castedExpressionType; 
+                               }
+                       }                               
+               }
+               // perform alternate lookup with original types
+               if (rawArgumentTypes != argumentTypes) {
+                       checkAlternateBinding(scope, receiver, receiverType, binding, arguments, argumentTypes, rawArgumentTypes, invocationSite);
+               }
+       }
+
+       /**
+        * Check binary operator casted arguments 
+        */
+       public static void checkNeedForArgumentCasts(BlockScope scope, int operator, int operatorSignature, Expression left, int leftTypeId, boolean leftIsCast, Expression right, int rightTypeId, boolean rightIsCast) {
+
+               if (scope.environment().options.getSeverity(CompilerOptions.UnnecessaryTypeCheck) == ProblemSeverities.Ignore) return;
+
+               // check need for left operand cast
+               int alternateLeftTypeId = leftTypeId;
+               if (leftIsCast) {
+                       if ((left.bits & UnnecessaryCastMask) == 0 && left.resolvedType.isBaseType()) {
+                               // narrowing conversion on base type may change value, thus necessary
+                               leftIsCast = false;
+                       } else  {
+                               TypeBinding alternateLeftType = ((CastExpression)left).expression.resolvedType;
+                               if (alternateLeftType == null) return; // cannot do better
+                               if ((alternateLeftTypeId = alternateLeftType.id) == leftTypeId) { // obvious identity cast
+                                       scope.problemReporter().unnecessaryCast((CastExpression)left); 
+                                       leftIsCast = false;
+                               } else if (alternateLeftTypeId == T_null) {
+                                       alternateLeftTypeId = leftTypeId;  // tolerate null argument cast
+                                       leftIsCast = false;
+                               }
+                       }
+               }
+               // check need for right operand cast
+               int alternateRightTypeId = rightTypeId;
+               if (rightIsCast) {
+                       if ((right.bits & UnnecessaryCastMask) == 0 && right.resolvedType.isBaseType()) {
+                               // narrowing conversion on base type may change value, thus necessary
+                               rightIsCast = false;
+                       } else {
+                               TypeBinding alternateRightType = ((CastExpression)right).expression.resolvedType;
+                               if (alternateRightType == null) return; // cannot do better
+                               if ((alternateRightTypeId = alternateRightType.id) == rightTypeId) { // obvious identity cast
+                                       scope.problemReporter().unnecessaryCast((CastExpression)right); 
+                                       rightIsCast = false;
+                               } else if (alternateRightTypeId == T_null) {
+                                       alternateRightTypeId = rightTypeId;  // tolerate null argument cast
+                                       rightIsCast = false;
+                               }
+                       }       
+               }
+               if (leftIsCast || rightIsCast) {
+                       if (alternateLeftTypeId > 15 || alternateRightTypeId > 15) { // must convert String + Object || Object + String
+                               if (alternateLeftTypeId == T_String) {
+                                       alternateRightTypeId = T_Object;
+                               } else if (alternateRightTypeId == T_String) {
+                                       alternateLeftTypeId = T_Object;
+                               } else {
+                                       return; // invalid operator
+                               }
+                       }
+                       int alternateOperatorSignature = OperatorExpression.OperatorSignatures[operator][(alternateLeftTypeId << 4) + alternateRightTypeId];
+                       // (cast)  left   Op (cast)  right --> result
+                       //  1111   0000       1111   0000     1111
+                       //  <<16   <<12       <<8    <<4       <<0
+                       final int CompareMASK = (0xF<<16) + (0xF<<8) + 0xF; // mask hiding compile-time types
+                       if ((operatorSignature & CompareMASK) == (alternateOperatorSignature & CompareMASK)) { // same promotions and result
+                               if (leftIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)left,  TypeBinding.wellKnownType(scope, left.implicitConversion >> 4)); 
+                               if (rightIsCast) scope.problemReporter().unnecessaryCastForArgument((CastExpression)right, TypeBinding.wellKnownType(scope,  right.implicitConversion >> 4));
+                       }
+               }
+       }
+
+       private static void checkAlternateBinding(BlockScope scope, Expression receiver, TypeBinding receiverType, MethodBinding binding, Expression[] arguments, TypeBinding[] originalArgumentTypes, TypeBinding[] alternateArgumentTypes, final InvocationSite invocationSite) {
+
+                       InvocationSite fakeInvocationSite = new InvocationSite(){       
+                               public boolean isSuperAccess(){ return invocationSite.isSuperAccess(); }
+                               public boolean isTypeAccess() { return invocationSite.isTypeAccess(); }
+                               public void setActualReceiverType(ReferenceBinding actualReceiverType) { /* ignore */}
+                               public void setDepth(int depth) { /* ignore */}
+                               public void setFieldIndex(int depth){ /* ignore */}
+                               public int sourceStart() { return 0; }
+                               public int sourceEnd() { return 0; }
+                       };      
+                       MethodBinding bindingIfNoCast;
+                       if (binding.isConstructor()) {
+                               bindingIfNoCast = scope.getConstructor((ReferenceBinding)receiverType, alternateArgumentTypes, fakeInvocationSite);
+                       } else {
+                               bindingIfNoCast = receiver.isImplicitThis()
+                                       ? scope.getImplicitMethod(binding.selector, alternateArgumentTypes, fakeInvocationSite)
+                                       : scope.getMethod(receiverType, binding.selector, alternateArgumentTypes, fakeInvocationSite);  
+                       }
+                       if (bindingIfNoCast == binding) {
+                               for (int i = 0, length = originalArgumentTypes.length; i < length; i++) {
+                                       if (originalArgumentTypes[i] != alternateArgumentTypes[i]) {
+                                               scope.problemReporter().unnecessaryCastForArgument((CastExpression)arguments[i], binding.parameters[i]);
+                                       }
+                               }
+                       }       
+       }
+       /**
+        * Cast expression code generation
+        *
+        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+        * @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;
+               boolean needRuntimeCheckcast = (this.bits & NeedRuntimeCheckCastMASK) != 0;
+               if (constant != NotAConstant) {
+                       if (valueRequired || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
+                               codeStream.generateConstant(constant, implicitConversion);
+                               if (needRuntimeCheckcast) {
+                                       codeStream.checkcast(this.resolvedType);
+                                       if (!valueRequired)
+                                               codeStream.pop();
+                               }
+                       }
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               expression.generateCode(
+                       currentScope,
+                       codeStream,
+                       valueRequired || needRuntimeCheckcast);
+               if (needRuntimeCheckcast) {
+                       codeStream.checkcast(this.resolvedType);
+                       if (!valueRequired)
+                               codeStream.pop();
+               } else {
+                       if (valueRequired)
+                               codeStream.generateImplicitConversion(implicitConversion);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public Expression innermostCastedExpression(){ 
+               Expression current = this.expression;
+               while (current instanceof CastExpression) {
+                       current = ((CastExpression) current).expression;
+               }
+               return current;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               output.append('(');
+               type.print(0, output).append(") "); //$NON-NLS-1$
+               return expression.printExpression(0, output);
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+               // compute a new constant if the cast is effective
+
+               // due to the fact an expression may start with ( and that a cast can also start with (
+               // the field is an expression....it can be a TypeReference OR a NameReference Or
+               // any kind of Expression <-- this last one is invalid.......
+
+               constant = Constant.NotAConstant;
+               implicitConversion = T_undefined;
+
+               if ((type instanceof TypeReference) || (type instanceof NameReference)
+                               && ((type.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT) == 0) { // no extra parenthesis around type: ((A))exp
+
+                       this.resolvedType = type.resolveType(scope);
+                       TypeBinding expressionType = expression.resolveType(scope);
+                       if (this.resolvedType != null && expressionType != null) {
+                               boolean necessary = checkCastTypesCompatibility(scope, this.resolvedType, expressionType);
+                               if (!necessary && this.expression.resolvedType != null) { // cannot do better if expression is not bound
+                                       this.bits |= UnnecessaryCastMask;
+                                       if ((this.bits & IgnoreNeedForCastCheckMASK) == 0) {
+                                               scope.problemReporter().unnecessaryCast(this);
+                                       }
+                               }
+                       }
+                       return this.resolvedType;
+               } else { // expression as a cast !!!!!!!!
+                       TypeBinding expressionType = expression.resolveType(scope);
+                       if (expressionType == null) return null;
+                       scope.problemReporter().invalidTypeReference(type);
+                       return null;
+               }
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       type.traverse(visitor, blockScope);
+                       expression.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/CharLiteral.java
new file mode 100644 (file)
index 0000000..c2d90b0
--- /dev/null
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CharLiteral extends NumberLiteral {
+       char value;
+public CharLiteral(char[] token, int s, int e) {
+       super(token, s, e);
+       computeValue();
+}
+public void computeConstant() {
+       //The source is a  char[3] first and last char are '
+       //This is true for both regular char AND unicode char
+       //BUT not for escape char like '\b' which are char[4]....
+
+       constant = Constant.fromValue(value);
+}
+private void computeValue() {
+       //The source is a  char[3] first and last char are '
+       //This is true for both regular char AND unicode char
+       //BUT not for escape char like '\b' which are char[4]....
+
+       if ((value = source[1]) != '\\')
+               return;
+       char digit;
+       switch (digit = source[2]) {
+               case 'b' :
+                       value = '\b';
+                       break;
+               case 't' :
+                       value = '\t';
+                       break;
+               case 'n' :
+                       value = '\n';
+                       break;
+               case 'f' :
+                       value = '\f';
+                       break;
+               case 'r' :
+                       value = '\r';
+                       break;
+               case '\"' :
+                       value = '\"';
+                       break;
+               case '\'' :
+                       value = '\'';
+                       break;
+               case '\\' :
+                       value = '\\';
+                       break;
+               default : //octal (well-formed: ended by a ' )
+                       int number = Character.getNumericValue(digit);
+                       if ((digit = source[3]) != '\'')
+                               number = (number * 8) + Character.getNumericValue(digit);
+                       else {
+                               constant = Constant.fromValue(value = (char) number);
+                               break;
+                       }
+                       if ((digit = source[4]) != '\'')
+                               number = (number * 8) + Character.getNumericValue(digit);
+                       value = (char) number;
+                       break;
+       }
+}
+/**
+ * CharLiteral code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+       int pc = codeStream.position;
+       if (valueRequired)
+               if ((implicitConversion >> 4) == T_char)
+                       codeStream.generateInlinedValue(value);
+               else
+                       codeStream.generateConstant(constant, implicitConversion);
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public TypeBinding literalType(BlockScope scope) {
+       return CharBinding;
+}
+public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+       visitor.visit(this, blockScope);
+       visitor.endVisit(this, blockScope);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ClassLiteralAccess.java
new file mode 100644 (file)
index 0000000..4a4136e
--- /dev/null
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ClassLiteralAccess extends Expression {
+       
+       public TypeReference type;
+       public TypeBinding targetType;
+       FieldBinding syntheticField;
+
+       public ClassLiteralAccess(int sourceEnd, TypeReference t) {
+               type = t;
+               this.sourceStart = t.sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // 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);
+               }
+               return flowInfo;
+       }
+
+       /**
+        * MessageSendDotClass code generation
+        *
+        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+        * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+        * @param valueRequired boolean
+        */
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+               int pc = codeStream.position;
+
+               // in interface case, no caching occurs, since cannot make a cache field for interface
+               if (valueRequired)
+                       codeStream.generateClassLiteralAccessForType(type.resolvedType, syntheticField);
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               return type.print(0, output).append(".class"); //$NON-NLS-1$
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+
+               constant = NotAConstant;
+               if ((targetType = type.resolveType(scope)) == null)
+                       return null;
+
+               if (targetType.isArrayType()
+                       && ((ArrayBinding) targetType).leafComponentType == VoidBinding) {
+                       scope.problemReporter().cannotAllocateVoidArray(this);
+                       return null;
+               }
+
+               return this.resolvedType = scope.getJavaLangClass();
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       type.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Clinit.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Clinit.java
new file mode 100644 (file)
index 0000000..2bbac9c
--- /dev/null
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+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;
+       }
+
+       public void analyseCode(
+               ClassScope classScope,
+               InitializationFlowContext staticInitializerFlowContext,
+               FlowInfo flowInfo) {
+
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       ExceptionHandlingFlowContext clinitContext =
+                               new ExceptionHandlingFlowContext(
+                                       staticInitializerFlowContext.parent,
+                                       this,
+                                       NoExceptions,
+                                       scope,
+                                       FlowInfo.DEAD_END);
+
+                       // check for missing returning path
+                       this.needFreeReturn = flowInfo.isReachable();
+
+                       // check missing blank final field initializations
+                       flowInfo = flowInfo.mergedWith(staticInitializerFlowContext.initsOnReturn);
+                       FieldBinding[] fields = scope.enclosingSourceType().fields();
+                       for (int i = 0, count = fields.length; i < count; i++) {
+                               FieldBinding field;
+                               if ((field = fields[i]).isStatic()
+                                       && field.isFinal()
+                                       && (!flowInfo.isDefinitelyAssigned(fields[i]))) {
+                                       scope.problemReporter().uninitializedBlankFinalField(
+                                               field,
+                                               scope.referenceType().declarationOf(field));
+                                       // can complain against the field decl, since only one <clinit>
+                               }
+                       }
+                       // check static initializers thrown exceptions
+                       staticInitializerFlowContext.checkInitializerExceptions(
+                               scope,
+                               clinitContext,
+                               flowInfo);
+               } catch (AbortMethod e) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+       }
+
+       /**
+        * Bytecode generation for a <clinit> method
+        *
+        * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
+        * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+        */
+       public void generateCode(ClassScope classScope, ClassFile classFile) {
+
+               int clinitOffset = 0;
+               if (ignoreFurtherInvestigation) {
+                       // should never have to add any <clinit> problem method
+                       return;
+               }
+               try {
+                       clinitOffset = classFile.contentsOffset;
+                       this.generateCode(classScope, classFile, clinitOffset);
+               } catch (AbortMethod e) {
+                       // should never occur
+                       // the clinit referenceContext is the type declaration
+                       // All clinit problems will be reported against the type: AbortType instead of AbortMethod
+                       // reset the contentsOffset to the value before generating the clinit code
+                       // decrement the number of method info as well.
+                       // This is done in the addProblemMethod and addProblemConstructor for other
+                       // cases.
+                       if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
+                               // a branch target required a goto_w, restart code gen in wide mode.
+                               try {
+                                       classFile.contentsOffset = clinitOffset;
+                                       classFile.methodCount--;
+                                       classFile.codeStream.wideMode = true; // request wide mode 
+                                       this.generateCode(classScope, classFile, clinitOffset);
+                                       // restart method generation
+                               } catch (AbortMethod e2) {
+                                       classFile.contentsOffset = clinitOffset;
+                                       classFile.methodCount--;
+                               }
+                       } else {
+                               // produce a problem method accounting for this fatal error
+                               classFile.contentsOffset = clinitOffset;
+                               classFile.methodCount--;
+                       }
+               }
+       }
+
+       /**
+        * Bytecode generation for a <clinit> method
+        *
+        * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
+        * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+        */
+       private void generateCode(
+               ClassScope classScope,
+               ClassFile classFile,
+               int clinitOffset) {
+
+               ConstantPool constantPool = classFile.constantPool;
+               int constantPoolOffset = constantPool.currentOffset;
+               int constantPoolIndex = constantPool.currentIndex;
+               classFile.generateMethodInfoHeaderForClinit();
+               int codeAttributeOffset = classFile.contentsOffset;
+               classFile.generateCodeAttributeHeader();
+               CodeStream codeStream = classFile.codeStream;
+               this.resolve(classScope);
+
+               codeStream.reset(this, classFile);
+               TypeDeclaration declaringType = classScope.referenceContext;
+
+               // initialize local positions - including initializer scope.
+               MethodScope staticInitializerScope = declaringType.staticInitializerScope;
+               staticInitializerScope.computeLocalVariablePositions(0, codeStream);
+
+               // 1.4 feature
+               // This has to be done before any other initialization
+               if (this.assertionSyntheticFieldBinding != null) {
+                       // generate code related to the activation of assertion for this class
+                       codeStream.generateClassLiteralAccessForType(
+                               classScope.enclosingSourceType(),
+                               classLiteralSyntheticField);
+                       codeStream.invokeJavaLangClassDesiredAssertionStatus();
+                       Label falseLabel = new Label(codeStream);
+                       codeStream.ifne(falseLabel);
+                       codeStream.iconst_1();
+                       Label jumpLabel = new Label(codeStream);
+                       codeStream.goto_(jumpLabel);
+                       falseLabel.place();
+                       codeStream.iconst_0();
+                       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);
+                               }
+                       }
+               }
+               if (codeStream.position == 0) {
+                       // do not need to output a Clinit if no bytecodes
+                       // so we reset the offset inside the byte array contents.
+                       classFile.contentsOffset = clinitOffset;
+                       // like we don't addd a method we need to undo the increment on the method count
+                       classFile.methodCount--;
+                       // reset the constant pool to its state before the clinit
+                       constantPool.resetForClinit(constantPoolIndex, constantPoolOffset);
+               } else {
+                       if (this.needFreeReturn) {
+                               int oldPosition = codeStream.position;
+                               codeStream.return_();
+                               codeStream.updateLocalVariablesAttribute(oldPosition);
+                       }
+                       // Record the end of the clinit: point to the declaration of the class
+                       codeStream.recordPositionsFrom(0, declaringType.sourceStart);
+                       classFile.completeCodeAttributeForClinit(codeAttributeOffset);
+               }
+       }
+
+       public boolean isClinit() {
+
+               return true;
+       }
+
+       public boolean isInitializationMethod() {
+
+               return true;
+       }
+
+       public boolean isStatic() {
+
+               return true;
+       }
+
+       public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+               //the clinit is filled by hand .... 
+       }
+
+       public StringBuffer print(int tab, StringBuffer output) {
+
+               printIndent(tab, output).append("<clinit>()"); //$NON-NLS-1$
+               printBody(tab + 1, output);
+               return output;
+       }
+
+       public void resolve(ClassScope classScope) {
+
+               this.scope = new MethodScope(classScope, classScope.referenceContext, true);
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               ClassScope classScope) {
+
+               visitor.visit(this, classScope);
+               visitor.endVisit(this, classScope);
+       }
+
+       // 1.4 feature
+       public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding) {
+
+               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);
+       }
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
new file mode 100644 (file)
index 0000000..d736614
--- /dev/null
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+
+public class CompilationUnitDeclaration
+       extends ASTNode
+       implements ProblemSeverities, ReferenceContext {
+               
+       public ImportReference currentPackage;
+       public ImportReference[] imports;
+       public TypeDeclaration[] types;
+       public int[][] comments;
+
+       public boolean ignoreFurtherInvestigation = false;      // once pointless to investigate due to errors
+       public boolean ignoreMethodBodies = false;
+       public CompilationUnitScope scope;
+       public ProblemReporter problemReporter;
+       public CompilationResult compilationResult;
+
+       public LocalTypeBinding[] localTypes;
+       public int localTypeCount = 0;
+       
+       public boolean isPropagatingInnerClassEmulation;
+
+       public CompilationUnitDeclaration(
+               ProblemReporter problemReporter,
+               CompilationResult compilationResult,
+               int sourceLength) {
+
+               this.problemReporter = problemReporter;
+               this.compilationResult = compilationResult;
+
+               //by definition of a compilation unit....
+               sourceStart = 0;
+               sourceEnd = sourceLength - 1;
+
+       }
+
+       /*
+        *      We cause the compilation task to abort to a given extent.
+        */
+       public void abort(int abortLevel, IProblem problem) {
+
+               switch (abortLevel) {
+                       case AbortType :
+                               throw new AbortType(this.compilationResult, problem);
+                       case AbortMethod :
+                               throw new AbortMethod(this.compilationResult, problem);
+                       default :
+                               throw new AbortCompilationUnit(this.compilationResult, problem);
+               }
+       }
+
+       /*
+        * Dispatch code analysis AND request saturation of inner emulation
+        */
+       public void analyseCode() {
+
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       if (types != null) {
+                               for (int i = 0, count = types.length; i < count; i++) {
+                                       types[i].analyseCode(scope);
+                               }
+                       }
+                       // request inner emulation propagation
+                       propagateInnerEmulationForAllLocalTypes();
+               } catch (AbortCompilationUnit e) {
+                       this.ignoreFurtherInvestigation = true;
+                       return;
+               }
+       }
+
+       /*
+        * When unit result is about to be accepted, removed back pointers
+        * to compiler structures.
+        */
+       public void cleanUp() {
+               if (this.types != null) {
+                       for (int i = 0, max = this.types.length; i < max; i++) {
+                               cleanUp(this.types[i]);
+                       }
+                       for (int i = 0, max = this.localTypeCount; i < max; i++) {
+                           LocalTypeBinding localType = localTypes[i];
+                               // null out the type's scope backpointers
+                               localType.scope = null; // local members are already in the list
+                       }
+               }
+               ClassFile[] classFiles = compilationResult.getClassFiles();
+               for (int i = 0, max = classFiles.length; i < max; i++) {
+                       // clear the classFile back pointer to the bindings
+                       ClassFile classFile = classFiles[i];
+                       // null out the classfile backpointer to a type binding
+                       classFile.referenceBinding = null;
+                       classFile.codeStream = null; // codeStream holds onto ast and scopes
+                       classFile.innerClassesBindings = null;
+               }
+       }
+       private void cleanUp(TypeDeclaration type) {
+               if (type.memberTypes != null) {
+                       for (int i = 0, max = type.memberTypes.length; i < max; i++){
+                               cleanUp(type.memberTypes[i]);
+                       }
+               }
+               if (type.binding != null) {
+                       // null out the type's scope backpointers
+                       type.binding.scope = null;
+               }
+       }
+
+       public void checkUnusedImports(){
+               
+               if (this.scope.imports != null){
+                       for (int i = 0, max = this.scope.imports.length; i < max; i++){
+                               ImportBinding importBinding = this.scope.imports[i];
+                               ImportReference importReference = importBinding.reference;
+                               if (importReference != null && !importReference.used){
+                                       scope.problemReporter().unusedImport(importReference);
+                               }
+                       }
+               }
+       }
+       
+       public CompilationResult compilationResult() {
+               return compilationResult;
+       }
+       
+       /*
+        * Finds the matching type amoung this compilation unit types.
+        * Returns null if no type with this name is found.
+        * The type name is a compound name
+        * eg. if we're looking for X.A.B then a type name would be {X, A, B}
+        */
+       public TypeDeclaration declarationOfType(char[][] typeName) {
+
+               for (int i = 0; i < this.types.length; i++) {
+                       TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName);
+                       if (typeDecl != null) {
+                               return typeDecl;
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Bytecode generation
+        */
+       public void generateCode() {
+
+               if (ignoreFurtherInvestigation) {
+                       if (types != null) {
+                               for (int i = 0, count = types.length; i < count; i++) {
+                                       types[i].ignoreFurtherInvestigation = true;
+                                       // propagate the flag to request problem type creation
+                                       types[i].generateCode(scope);
+                               }
+                       }
+                       return;
+               }
+               try {
+                       if (types != null) {
+                               for (int i = 0, count = types.length; i < count; i++)
+                                       types[i].generateCode(scope);
+                       }
+               } catch (AbortCompilationUnit e) {
+                       // ignore
+               }
+       }
+
+       public char[] getFileName() {
+
+               return compilationResult.getFileName();
+       }
+
+       public char[] getMainTypeName() {
+
+               if (compilationResult.compilationUnit == null) {
+                       char[] fileName = compilationResult.getFileName();
+
+                       int start = CharOperation.lastIndexOf('/', fileName) + 1;
+                       if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
+                               start = CharOperation.lastIndexOf('\\', fileName) + 1;
+
+                       int end = CharOperation.lastIndexOf('.', fileName);
+                       if (end == -1)
+                               end = fileName.length;
+
+                       return CharOperation.subarray(fileName, start, end);
+               } else {
+                       return compilationResult.compilationUnit.getMainTypeName();
+               }
+       }
+
+       public boolean isEmpty() {
+
+               return (currentPackage == null) && (imports == null) && (types == null);
+       }
+
+       public boolean hasErrors() {
+               return this.ignoreFurtherInvestigation;
+       }
+
+       public StringBuffer print(int indent, StringBuffer output) {
+
+               if (currentPackage != null) {
+                       printIndent(indent, output).append("package "); //$NON-NLS-1$
+                       currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
+               }
+               if (imports != null)
+                       for (int i = 0; i < imports.length; i++) {
+                               printIndent(indent, output).append("import "); //$NON-NLS-1$
+                               imports[i].print(0, output).append(";\n"); //$NON-NLS-1$ 
+                       }
+
+               if (types != null) {
+                       for (int i = 0; i < types.length; i++) {
+                               types[i].print(indent, output).append("\n"); //$NON-NLS-1$
+                       }
+               }
+               return output;
+       }
+       
+       /*
+        * Force inner local types to update their innerclass emulation
+        */
+       public void propagateInnerEmulationForAllLocalTypes() {
+
+               isPropagatingInnerClassEmulation = true;
+               for (int i = 0, max = this.localTypeCount; i < max; i++) {
+                               
+                       LocalTypeBinding localType = localTypes[i];
+                       // only propagate for reachable local types
+                       if ((localType.scope.referenceType().bits & IsReachableMASK) != 0) {
+                               localType.updateInnerEmulationDependents();
+                       }
+               }
+       }
+
+       /*
+        * Keep track of all local types, so as to update their innerclass
+        * emulation later on.
+        */
+       public void record(LocalTypeBinding localType) {
+
+               if (this.localTypeCount == 0) {
+                       this.localTypes = new LocalTypeBinding[5];
+               } else if (this.localTypeCount == this.localTypes.length) {
+                       System.arraycopy(this.localTypes, 0, (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]), 0, this.localTypeCount);
+               }
+               this.localTypes[this.localTypeCount++] = localType;
+       }
+
+       public void resolve() {
+
+               try {
+                       if (types != null) {
+                               for (int i = 0, count = types.length; i < count; i++) {
+                                       types[i].resolve(scope);
+                               }
+                       }
+                       if (!this.compilationResult.hasSyntaxError()) checkUnusedImports();
+               } catch (AbortCompilationUnit e) {
+                       this.ignoreFurtherInvestigation = true;
+                       return;
+               }
+       }
+
+       public void tagAsHavingErrors() {
+               ignoreFurtherInvestigation = true;
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               CompilationUnitScope unitScope) {
+
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       if (visitor.visit(this, this.scope)) {
+                               if (currentPackage != null) {
+                                       currentPackage.traverse(visitor, this.scope);
+                               }
+                               if (imports != null) {
+                                       int importLength = imports.length;
+                                       for (int i = 0; i < importLength; i++) {
+                                               imports[i].traverse(visitor, this.scope);
+                                       }
+                               }
+                               if (types != null) {
+                                       int typesLength = types.length;
+                                       for (int i = 0; i < typesLength; i++) {
+                                               types[i].traverse(visitor, this.scope);
+                                       }
+                               }
+                       }
+                       visitor.endVisit(this, this.scope);
+               } catch (AbortCompilationUnit e) {
+                       // ignore
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java b/src/java/org/eclipse/jdt/internal/compiler/ast/CompoundAssignment.java
new file mode 100644 (file)
index 0000000..47745f1
--- /dev/null
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CompoundAssignment extends Assignment implements OperatorIds {
+       public int operator;
+       public int assignmentImplicitConversion;
+
+       //  var op exp is equivalent to var = (varType) var op exp
+       // assignmentImplicitConversion stores the cast needed for the assignment
+
+       public CompoundAssignment(Expression lhs, Expression expression,int operator, int sourceEnd) {
+               //lhs is always a reference by construction ,
+               //but is build as an expression ==> the checkcast cannot fail
+       
+               super(lhs, expression, sourceEnd);
+               lhs.bits &= ~IsStrictlyAssignedMASK; // tag lhs as NON assigned - it is also a read access
+               lhs.bits |= IsCompoundAssignedMASK; // tag lhs as assigned by compound
+               this.operator = operator ;
+       }
+       
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+               // record setting a variable: various scenarii are possible, setting an array reference, 
+               // a field reference, a blank final field reference, a field of an enclosing instance or 
+               // just a local variable.
+       
+               return  ((Reference) lhs).analyseAssignment(currentScope, flowContext, flowInfo, this, true).unconditionalInits();
+       }
+       
+       public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+       
+               // various scenarii are possible, setting an array reference, 
+               // a field reference, a blank final field reference, a field of an enclosing instance or 
+               // just a local variable.
+       
+               int pc = codeStream.position;
+                ((Reference) lhs).generateCompoundAssignment(currentScope, codeStream, expression, operator, assignmentImplicitConversion, valueRequired);
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(implicitConversion);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+       
+       public String operatorToString() {
+               switch (operator) {
+                       case PLUS :
+                               return "+="; //$NON-NLS-1$
+                       case MINUS :
+                               return "-="; //$NON-NLS-1$
+                       case MULTIPLY :
+                               return "*="; //$NON-NLS-1$
+                       case DIVIDE :
+                               return "/="; //$NON-NLS-1$
+                       case AND :
+                               return "&="; //$NON-NLS-1$
+                       case OR :
+                               return "|="; //$NON-NLS-1$
+                       case XOR :
+                               return "^="; //$NON-NLS-1$
+                       case REMAINDER :
+                               return "%="; //$NON-NLS-1$
+                       case LEFT_SHIFT :
+                               return "<<="; //$NON-NLS-1$
+                       case RIGHT_SHIFT :
+                               return ">>="; //$NON-NLS-1$
+                       case UNSIGNED_RIGHT_SHIFT :
+                               return ">>>="; //$NON-NLS-1$
+               }
+               return "unknown operator"; //$NON-NLS-1$
+       }
+       
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+       
+               lhs.printExpression(indent, output).append(' ').append(operatorToString()).append(' ');
+               return expression.printExpression(0, output) ; 
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+               constant = NotAConstant;
+               if (!(this.lhs instanceof Reference) || this.lhs.isThis()) {
+                       scope.problemReporter().expressionShouldBeAVariable(this.lhs);
+                       return null;
+               }
+               TypeBinding lhsType = lhs.resolveType(scope);
+               TypeBinding expressionType = expression.resolveType(scope);
+               if (lhsType == null || expressionType == null)
+                       return null;
+       
+               int lhsId = lhsType.id;
+               int expressionId = expressionType.id;
+               if (restrainUsageToNumericTypes() && !lhsType.isNumericType()) {
+                       scope.problemReporter().operatorOnlyValidOnNumericType(this, lhsType, expressionType);
+                       return null;
+               }
+               if (lhsId > 15 || expressionId > 15) {
+                       if (lhsId != T_String) { // String += Thread is valid whereas Thread += String  is not
+                               scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+                               return null;
+                       }
+                       expressionId = T_Object; // use the Object has tag table
+               }
+       
+               // the code is an int
+               // (cast)  left   Op (cast)  rigth --> result 
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8     <<4        <<0
+       
+               // the conversion is stored INTO the reference (info needed for the code gen)
+               int result = OperatorExpression.OperatorSignatures[operator][ (lhsId << 4) + expressionId];
+               if (result == T_undefined) {
+                       scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+                       return null;
+               }
+               if (operator == PLUS){
+                       if(lhsId == T_JavaLangObject) {
+                               // <Object> += <String> is illegal (39248)
+                               scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+                               return null;
+                       } else {
+                               // <int | boolean> += <String> is illegal
+                               if ((lhsType.isNumericType() || lhsId == T_boolean) && !expressionType.isNumericType()){
+                                       scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+                                       return null;
+                               }
+                       }
+               }
+               lhs.implicitConversion = result >>> 12;
+               expression.implicitConversion = (result >>> 4) & 0x000FF;
+               assignmentImplicitConversion = (lhsId << 4) + (result & 0x0000F);
+               return this.resolvedType = lhsType;
+       }
+       
+       public boolean restrainUsageToNumericTypes(){
+               return false ;
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               if (visitor.visit(this, scope)) {
+                       lhs.traverse(visitor, scope);
+                       expression.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
new file mode 100644 (file)
index 0000000..cf86373
--- /dev/null
@@ -0,0 +1,411 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ConditionalExpression extends OperatorExpression {
+
+       public Expression condition, valueIfTrue, valueIfFalse;
+       public Constant optimizedBooleanConstant;
+       public Constant optimizedIfTrueConstant;
+       public Constant optimizedIfFalseConstant;
+       
+       // for local variables table attributes
+       int trueInitStateIndex = -1;
+       int falseInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+       
+       public ConditionalExpression(
+               Expression condition,
+               Expression valueIfTrue,
+               Expression valueIfFalse) {
+               this.condition = condition;
+               this.valueIfTrue = valueIfTrue;
+               this.valueIfFalse = valueIfFalse;
+               sourceStart = condition.sourceStart;
+               sourceEnd = valueIfFalse.sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               Constant cst = this.condition.optimizedBooleanConstant();
+               boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+
+               int mode = flowInfo.reachMode();
+               flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo, cst == NotAConstant);
+               
+               // process the if-true part
+               FlowInfo trueFlowInfo = flowInfo.initsWhenTrue().copy();
+               if (isConditionOptimizedFalse) {
+                       trueFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
+               }
+               trueInitStateIndex = currentScope.methodScope().recordInitializationStates(trueFlowInfo);
+               trueFlowInfo = valueIfTrue.analyseCode(currentScope, flowContext, trueFlowInfo);
+
+               // process the if-false part
+               FlowInfo falseFlowInfo = flowInfo.initsWhenFalse().copy();
+               if (isConditionOptimizedTrue) {
+                       falseFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
+               }
+               falseInitStateIndex = currentScope.methodScope().recordInitializationStates(falseFlowInfo);
+               falseFlowInfo = valueIfFalse.analyseCode(currentScope, flowContext, falseFlowInfo);
+
+               // merge if-true & if-false initializations
+               FlowInfo mergedInfo;
+               if (isConditionOptimizedTrue){
+                       mergedInfo = trueFlowInfo.addPotentialInitializationsFrom(falseFlowInfo);
+               } else if (isConditionOptimizedFalse) {
+                       mergedInfo = falseFlowInfo.addPotentialInitializationsFrom(trueFlowInfo);
+               } else {
+                       // if ((t && (v = t)) ? t : t && (v = f)) r = v;  -- ok
+                       cst = this.optimizedIfTrueConstant;
+                       boolean isValueIfTrueOptimizedTrue = cst != null && cst != NotAConstant && cst.booleanValue() == true;
+                       boolean isValueIfTrueOptimizedFalse = cst != null && cst != NotAConstant && cst.booleanValue() == false;
+                       
+                       cst = this.optimizedIfFalseConstant;
+                       boolean isValueIfFalseOptimizedTrue = cst != null && cst != NotAConstant && cst.booleanValue() == true;
+                       boolean isValueIfFalseOptimizedFalse = cst != null && cst != NotAConstant && cst.booleanValue() == false;
+
+                       UnconditionalFlowInfo trueInfoWhenTrue = trueFlowInfo.initsWhenTrue().copy().unconditionalInits();
+                       if (isValueIfTrueOptimizedFalse) trueInfoWhenTrue.setReachMode(FlowInfo.UNREACHABLE); 
+
+                       UnconditionalFlowInfo falseInfoWhenTrue = falseFlowInfo.initsWhenTrue().copy().unconditionalInits();
+                       if (isValueIfFalseOptimizedFalse) falseInfoWhenTrue.setReachMode(FlowInfo.UNREACHABLE); 
+                       
+                       UnconditionalFlowInfo trueInfoWhenFalse = trueFlowInfo.initsWhenFalse().copy().unconditionalInits();
+                       if (isValueIfTrueOptimizedTrue) trueInfoWhenFalse.setReachMode(FlowInfo.UNREACHABLE); 
+
+                       UnconditionalFlowInfo falseInfoWhenFalse = falseFlowInfo.initsWhenFalse().copy().unconditionalInits();
+                       if (isValueIfFalseOptimizedTrue) falseInfoWhenFalse.setReachMode(FlowInfo.UNREACHABLE); 
+
+                       mergedInfo =
+                               FlowInfo.conditional(
+                                       trueInfoWhenTrue.mergedWith(falseInfoWhenTrue),
+                                       trueInfoWhenFalse.mergedWith(falseInfoWhenFalse));
+               }
+               mergedInitStateIndex =
+                       currentScope.methodScope().recordInitializationStates(mergedInfo);
+               mergedInfo.setReachMode(mode);
+               return mergedInfo;
+       }
+
+       /**
+        * Code generation for the conditional operator ?:
+        *
+        * @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;
+               Label endifLabel, falseLabel;
+               if (constant != NotAConstant) {
+                       if (valueRequired)
+                               codeStream.generateConstant(constant, implicitConversion);
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               Constant cst = condition.constant;
+               Constant condCst = condition.optimizedBooleanConstant();
+               boolean needTruePart =
+                       !(((cst != NotAConstant) && (cst.booleanValue() == false))
+                               || ((condCst != NotAConstant) && (condCst.booleanValue() == false)));
+               boolean needFalsePart =
+                       !(((cst != NotAConstant) && (cst.booleanValue() == true))
+                               || ((condCst != NotAConstant) && (condCst.booleanValue() == true)));
+               endifLabel = new Label(codeStream);
+
+               // Generate code for the condition
+               boolean needConditionValue = (cst == NotAConstant) && (condCst == NotAConstant);
+               condition.generateOptimizedBoolean(
+                       currentScope,
+                       codeStream,
+                       null,
+                       (falseLabel = new Label(codeStream)),
+                       needConditionValue);
+
+               if (trueInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(
+                               currentScope,
+                               trueInitStateIndex);
+                       codeStream.addDefinitelyAssignedVariables(currentScope, trueInitStateIndex);
+               }
+               // Then code generation
+               if (needTruePart) {
+                       valueIfTrue.generateCode(currentScope, codeStream, valueRequired);
+                       if (needFalsePart) {
+                               // Jump over the else part
+                               int position = codeStream.position;
+                               codeStream.goto_(endifLabel);
+                               codeStream.updateLastRecordedEndPC(position);
+                               // Tune codestream stack size
+                               if (valueRequired) {
+                                       codeStream.decrStackSize(this.resolvedType == LongBinding || this.resolvedType == DoubleBinding ? 2 : 1);
+                               }
+                       }
+               }
+               if (needFalsePart) {
+                       falseLabel.place();
+                       if (falseInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(
+                                       currentScope,
+                                       falseInitStateIndex);
+                               codeStream.addDefinitelyAssignedVariables(currentScope, falseInitStateIndex);
+                       }
+                       valueIfFalse.generateCode(currentScope, codeStream, valueRequired);
+                       // End of if statement
+                       endifLabel.place();
+               }
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(
+                               currentScope,
+                               mergedInitStateIndex);
+               }
+               // implicit conversion
+               if (valueRequired)
+                       codeStream.generateImplicitConversion(implicitConversion);
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /**
+        * Optimized boolean code generation for the conditional operator ?:
+       */
+       public void generateOptimizedBoolean(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean) // constant
+                       || (valueIfTrue.implicitConversion >> 4) != T_boolean) { // non boolean values
+                       super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+                       return;
+               }
+               Constant cst = condition.constant;
+               Constant condCst = condition.optimizedBooleanConstant();
+               boolean needTruePart =
+                       !(((cst != NotAConstant) && (cst.booleanValue() == false))
+                               || ((condCst != NotAConstant) && (condCst.booleanValue() == false)));
+               boolean needFalsePart =
+                       !(((cst != NotAConstant) && (cst.booleanValue() == true))
+                               || ((condCst != NotAConstant) && (condCst.booleanValue() == true)));
+
+               Label internalFalseLabel, endifLabel = new Label(codeStream);
+
+               // Generate code for the condition
+               boolean needConditionValue = (cst == NotAConstant) && (condCst == NotAConstant);
+               condition.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               null,
+                               internalFalseLabel = new Label(codeStream),
+                               needConditionValue);
+
+               if (trueInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(
+                               currentScope,
+                               trueInitStateIndex);
+                       codeStream.addDefinitelyAssignedVariables(currentScope, trueInitStateIndex);
+               }
+               // Then code generation
+               if (needTruePart) {
+                       valueIfTrue.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+                       
+                       if (needFalsePart) {
+                               // Jump over the else part
+                               int position = codeStream.position;
+                               codeStream.goto_(endifLabel);
+                               codeStream.updateLastRecordedEndPC(position);
+                               // No need to decrement codestream stack size
+                               // since valueIfTrue was already consumed by branch bytecode
+                       }
+               }
+               if (needFalsePart) {
+                       internalFalseLabel.place();
+                       if (falseInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(
+                                       currentScope,
+                                       falseInitStateIndex);
+                               codeStream.addDefinitelyAssignedVariables(currentScope, falseInitStateIndex);
+                       }
+                       valueIfFalse.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+
+                       // End of if statement
+                       endifLabel.place();
+               }
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(
+                               currentScope,
+                               mergedInitStateIndex);
+               }
+               // no implicit conversion for boolean values
+               codeStream.updateLastRecordedEndPC(codeStream.position);
+       }
+
+       public Constant optimizedBooleanConstant() {
+
+               return this.optimizedBooleanConstant == null ? this.constant : this.optimizedBooleanConstant;
+       }
+       
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+               
+               condition.printExpression(indent, output).append(" ? "); //$NON-NLS-1$
+               valueIfTrue.printExpression(0, output).append(" : "); //$NON-NLS-1$
+               return valueIfFalse.printExpression(0, output);
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+               // specs p.368
+               constant = NotAConstant;
+               TypeBinding conditionType = condition.resolveTypeExpecting(scope, BooleanBinding);
+               
+               if (valueIfTrue instanceof CastExpression) valueIfTrue.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+               TypeBinding valueIfTrueType = valueIfTrue.resolveType(scope);
+
+               if (valueIfFalse instanceof CastExpression) valueIfFalse.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+               TypeBinding valueIfFalseType = valueIfFalse.resolveType(scope);
+
+               if (conditionType == null || valueIfTrueType == null || valueIfFalseType == null)
+                       return null;
+
+               // Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible
+               Constant condConstant, trueConstant, falseConstant;
+               if ((condConstant = condition.constant) != NotAConstant
+                       && (trueConstant = valueIfTrue.constant) != NotAConstant
+                       && (falseConstant = valueIfFalse.constant) != NotAConstant) {
+                       // all terms are constant expression so we can propagate the constant
+                       // from valueIFTrue or valueIfFalse to teh receiver constant
+                       constant = condConstant.booleanValue() ? trueConstant : falseConstant;
+               }
+               if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion 
+                       valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
+                       valueIfFalse.implicitConversion = valueIfTrue.implicitConversion;
+                       if (valueIfTrueType == BooleanBinding) {
+                               this.optimizedIfTrueConstant = valueIfTrue.optimizedBooleanConstant();
+                               this.optimizedIfFalseConstant = valueIfFalse.optimizedBooleanConstant();
+                               if (this.optimizedIfTrueConstant != NotAConstant 
+                                               && this.optimizedIfFalseConstant != NotAConstant
+                                               && this.optimizedIfTrueConstant.booleanValue() == this.optimizedIfFalseConstant.booleanValue()) {
+                                       // a ? true : true  /   a ? false : false
+                                       this.optimizedBooleanConstant = optimizedIfTrueConstant;
+                               } else if ((condConstant = condition.optimizedBooleanConstant()) != NotAConstant) { // Propagate the optimized boolean constant if possible
+                                       this.optimizedBooleanConstant = condConstant.booleanValue()
+                                               ? this.optimizedIfTrueConstant
+                                               : this.optimizedIfFalseConstant;
+                               }
+                       }
+                       return this.resolvedType = valueIfTrueType;
+               }
+               // Determine the return type depending on argument types
+               // Numeric types
+               if (valueIfTrueType.isNumericType() && valueIfFalseType.isNumericType()) {
+                       // (Short x Byte) or (Byte x Short)"
+                       if ((valueIfTrueType == ByteBinding && valueIfFalseType == ShortBinding)
+                               || (valueIfTrueType == ShortBinding && valueIfFalseType == ByteBinding)) {
+                               valueIfTrue.implicitWidening(ShortBinding, valueIfTrueType);
+                               valueIfFalse.implicitWidening(ShortBinding, valueIfFalseType);
+                               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);
+                               return this.resolvedType = valueIfTrueType;
+                       }
+                       if ((valueIfFalseType == ByteBinding
+                                       || valueIfFalseType == ShortBinding
+                                       || valueIfFalseType == CharBinding)
+                                       && (valueIfTrueType == IntBinding
+                                               && valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) {
+                               valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
+                               valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+                               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);
+                               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);
+                               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);
+                               return this.resolvedType = FloatBinding;
+                       }
+                       // double
+                       valueIfTrue.implicitWidening(DoubleBinding, valueIfTrueType);
+                       valueIfFalse.implicitWidening(DoubleBinding, valueIfFalseType);
+                       return this.resolvedType = DoubleBinding;
+               }
+               // Type references (null null is already tested)
+               if ((valueIfTrueType.isBaseType() && valueIfTrueType != NullBinding)
+                               || (valueIfFalseType.isBaseType() && valueIfFalseType != NullBinding)) {
+                       scope.problemReporter().conditionalArgumentsIncompatibleTypes(
+                               this,
+                               valueIfTrueType,
+                               valueIfFalseType);
+                       return null;
+               }
+               if (valueIfFalseType.isCompatibleWith(valueIfTrueType)) {
+                       valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
+                       valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+                       return this.resolvedType = valueIfTrueType;
+               }
+               if (valueIfTrueType.isCompatibleWith(valueIfFalseType)) {
+                       valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
+                       valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+                       return this.resolvedType = valueIfFalseType;
+               }
+               scope.problemReporter().conditionalArgumentsIncompatibleTypes(
+                       this,
+                       valueIfTrueType,
+                       valueIfFalseType);
+               return null;
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               if (visitor.visit(this, scope)) {
+                       condition.traverse(visitor, scope);
+                       valueIfTrue.traverse(visitor, scope);
+                       valueIfFalse.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
new file mode 100644 (file)
index 0000000..7170bbf
--- /dev/null
@@ -0,0 +1,454 @@
+/*******************************************************************************
+ * 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 java.util.ArrayList;
+
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+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 ConstructorDeclaration(CompilationResult compilationResult){
+               super(compilationResult);
+       }
+       
+       public void analyseCode(
+               ClassScope classScope,
+               InitializationFlowContext initializerFlowContext,
+               FlowInfo flowInfo) {
+
+               if (ignoreFurtherInvestigation)
+                       return;
+
+               if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
+                       if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
+                               scope.problemReporter().unusedPrivateConstructor(this);
+                       }
+               }
+                       
+               // check constructor recursion, once all constructor got resolved
+               if (isRecursive(null /*lazy initialized visited list*/)) {                              
+                       this.scope.problemReporter().recursiveConstructorInvocation(this.constructorCall);
+               }
+                       
+               try {
+                       ExceptionHandlingFlowContext constructorContext =
+                               new ExceptionHandlingFlowContext(
+                                       initializerFlowContext.parent,
+                                       this,
+                                       binding.thrownExceptions,
+                                       scope,
+                                       FlowInfo.DEAD_END);
+                       initializerFlowContext.checkInitializerExceptions(
+                               scope,
+                               constructorContext,
+                               flowInfo);
+
+                       // anonymous constructor can gain extra thrown exceptions from unhandled ones
+                       if (binding.declaringClass.isAnonymousType()) {
+                               ArrayList computedExceptions = constructorContext.extendedExceptions;
+                               if (computedExceptions != null){
+                                       int size;
+                                       if ((size = computedExceptions.size()) > 0){
+                                               ReferenceBinding[] actuallyThrownExceptions;
+                                               computedExceptions.toArray(actuallyThrownExceptions = new ReferenceBinding[size]);
+                                               binding.thrownExceptions = actuallyThrownExceptions;
+                                       }
+                               }
+                       }
+                       
+                       // propagate to constructor call
+                       if (constructorCall != null) {
+                               // if calling 'this(...)', then flag all non-static fields as definitely
+                               // set since they are supposed to be set inside other local constructor
+                               if (constructorCall.accessMode == ExplicitConstructorCall.This) {
+                                       FieldBinding[] fields = binding.declaringClass.fields();
+                                       for (int i = 0, count = fields.length; i < count; i++) {
+                                               FieldBinding field;
+                                               if (!(field = fields[i]).isStatic()) {
+                                                       flowInfo.markAsDefinitelyAssigned(field);
+                                               }
+                                       }
+                               }
+                               flowInfo = constructorCall.analyseCode(scope, constructorContext, flowInfo);
+                       }
+                       // propagate to statements
+                       if (statements != null) {
+                               boolean didAlreadyComplain = false;
+                               for (int i = 0, count = statements.length; i < count; i++) {
+                                       Statement stat = statements[i];
+                                       if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
+                                               flowInfo = stat.analyseCode(scope, constructorContext, flowInfo);
+                                       } else {
+                                               didAlreadyComplain = true;
+                                       }
+                               }
+                       }
+                       // check for missing returning path
+                       this.needFreeReturn = flowInfo.isReachable();
+
+                       // check missing blank final field initializations
+                       if ((constructorCall != null)
+                               && (constructorCall.accessMode != ExplicitConstructorCall.This)) {
+                               flowInfo = flowInfo.mergedWith(constructorContext.initsOnReturn);
+                               FieldBinding[] fields = binding.declaringClass.fields();
+                               for (int i = 0, count = fields.length; i < count; i++) {
+                                       FieldBinding field;
+                                       if ((!(field = fields[i]).isStatic())
+                                               && field.isFinal()
+                                               && (!flowInfo.isDefinitelyAssigned(fields[i]))) {
+                                               scope.problemReporter().uninitializedBlankFinalField(
+                                                       field,
+                                                       isDefaultConstructor ? (ASTNode) scope.referenceType() : this);
+                                       }
+                               }
+                       }
+                       // check unreachable catch blocks
+                       constructorContext.complainIfUnusedExceptionHandlers(this);
+               } catch (AbortMethod e) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+       }
+
+       /**
+        * Bytecode generation for a constructor
+        *
+        * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
+        * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+        */
+       public void generateCode(ClassScope classScope, ClassFile classFile) {
+               
+               int problemResetPC = 0;
+               if (ignoreFurtherInvestigation) {
+                       if (this.binding == null)
+                               return; // Handle methods with invalid signature or duplicates
+                       int problemsLength;
+                       IProblem[] problems =
+                               scope.referenceCompilationUnit().compilationResult.getProblems();
+                       IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+                       System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+                       classFile.addProblemConstructor(this, binding, problemsCopy);
+                       return;
+               }
+               try {
+                       problemResetPC = classFile.contentsOffset;
+                       this.internalGenerateCode(classScope, classFile);
+               } catch (AbortMethod e) {
+                       if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
+                               // a branch target required a goto_w, restart code gen in wide mode.
+                               try {
+                                       classFile.contentsOffset = problemResetPC;
+                                       classFile.methodCount--;
+                                       classFile.codeStream.wideMode = true; // request wide mode 
+                                       this.internalGenerateCode(classScope, classFile); // restart method generation
+                               } catch (AbortMethod e2) {
+                                       int problemsLength;
+                                       IProblem[] problems =
+                                               scope.referenceCompilationUnit().compilationResult.getAllProblems();
+                                       IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+                                       System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+                                       classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
+                               }
+                       } else {
+                               int problemsLength;
+                               IProblem[] problems =
+                                       scope.referenceCompilationUnit().compilationResult.getAllProblems();
+                               IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+                               System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+                               classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
+                       }
+               }
+       }
+
+       public void generateSyntheticFieldInitializationsIfNecessary(
+               MethodScope methodScope,
+               CodeStream codeStream,
+               ReferenceBinding declaringClass) {
+                       
+               if (!declaringClass.isNestedType()) return;
+               
+               NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
+
+               SyntheticArgumentBinding[] syntheticArgs = nestedType.syntheticEnclosingInstances();
+               for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) {
+                       SyntheticArgumentBinding syntheticArg;
+                       if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
+                               codeStream.aload_0();
+                               codeStream.load(syntheticArg);
+                               codeStream.putfield(syntheticArg.matchingField);
+                       }
+               }
+               syntheticArgs = nestedType.syntheticOuterLocalVariables();
+               for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) {
+                       SyntheticArgumentBinding syntheticArg;
+                       if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
+                               codeStream.aload_0();
+                               codeStream.load(syntheticArg);
+                               codeStream.putfield(syntheticArg.matchingField);
+                       }
+               }
+       }
+
+       private void internalGenerateCode(ClassScope classScope, ClassFile classFile) {
+               
+               classFile.generateMethodInfoHeader(binding);
+               int methodAttributeOffset = classFile.contentsOffset;
+               int attributeNumber = classFile.generateMethodInfoAttribute(binding);
+               if ((!binding.isNative()) && (!binding.isAbstract())) {
+                       
+                       TypeDeclaration declaringType = classScope.referenceContext;
+                       int codeAttributeOffset = classFile.contentsOffset;
+                       classFile.generateCodeAttributeHeader();
+                       CodeStream codeStream = classFile.codeStream;
+                       codeStream.reset(this, classFile);
+
+                       // initialize local positions - including initializer scope.
+                       ReferenceBinding declaringClass = binding.declaringClass;
+
+                       int argSlotSize = 1; // this==aload0
+                       
+                       if (declaringClass.isNestedType()){
+                               NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
+                               this.scope.extraSyntheticArguments = nestedType.syntheticOuterLocalVariables();
+                               scope.computeLocalVariablePositions(// consider synthetic arguments if any
+                                       nestedType.enclosingInstancesSlotSize + 1,
+                                       codeStream);
+                               argSlotSize += nestedType.enclosingInstancesSlotSize;
+                               argSlotSize += nestedType.outerLocalVariablesSlotSize;
+                       } else {
+                               scope.computeLocalVariablePositions(1,  codeStream);
+                       }
+                               
+                       if (arguments != null) {
+                               for (int i = 0, max = arguments.length; i < max; i++) {
+                                       // arguments initialization for local variable debug attributes
+                                       LocalVariableBinding argBinding;
+                                       codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding);
+                                       argBinding.recordInitializationStartPC(0);
+                                       TypeBinding argType;
+                                       if ((argType = argBinding.type) == LongBinding || (argType == DoubleBinding)) {
+                                               argSlotSize += 2;
+                                       } else {
+                                               argSlotSize++;
+                                       }
+                               }
+                       }
+                       
+                       MethodScope initializerScope = declaringType.initializerScope;
+                       initializerScope.computeLocalVariablePositions(argSlotSize, codeStream); // offset by the argument size (since not linked to method scope)
+
+                       boolean needFieldInitializations = constructorCall == null || constructorCall.accessMode != ExplicitConstructorCall.This;
+
+                       // post 1.4 source level, synthetic initializations occur prior to explicit constructor call
+                       boolean preInitSyntheticFields = scope.environment().options.targetJDK >= ClassFileConstants.JDK1_4;
+
+                       if (needFieldInitializations && preInitSyntheticFields){
+                               generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass);
+                       }                       
+                       // generate constructor call
+                       if (constructorCall != null) {
+                               constructorCall.generateCode(scope, codeStream);
+                       }
+                       // generate field initialization - only if not invoking another constructor call of the same class
+                       if (needFieldInitializations) {
+                               if (!preInitSyntheticFields){
+                                       generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass);
+                               }
+                               // generate user field initialization
+                               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(initializerScope, codeStream);
+                                               }
+                                       }
+                               }
+                       }
+                       // generate statements
+                       if (statements != null) {
+                               for (int i = 0, max = statements.length; i < max; i++) {
+                                       statements[i].generateCode(scope, codeStream);
+                               }
+                       }
+                       if (this.needFreeReturn) {
+                               codeStream.return_();
+                       }
+                       // local variable attributes
+                       codeStream.exitUserScope(scope);
+                       codeStream.recordPositionsFrom(0, this.bodyEnd);
+                       classFile.completeCodeAttribute(codeAttributeOffset);
+                       attributeNumber++;
+               }
+               classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);
+
+               // if a problem got reported during code gen, then trigger problem method creation
+               if (ignoreFurtherInvestigation) {
+                       throw new AbortMethod(scope.referenceCompilationUnit().compilationResult, null);
+               }
+       }
+
+       public boolean isConstructor() {
+
+               return true;
+       }
+
+       public boolean isDefaultConstructor() {
+
+               return this.isDefaultConstructor;
+       }
+
+       public boolean isInitializationMethod() {
+
+               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) {
+
+               if (this.binding == null
+                               || this.constructorCall == null
+                               || this.constructorCall.binding == null
+                               || this.constructorCall.isSuperAccess()
+                               || !this.constructorCall.binding.isValidBinding()) {
+                       return false;
+               }
+               
+               ConstructorDeclaration targetConstructor = 
+                       ((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding));
+               if (this == targetConstructor) return true; // direct case
+
+               if (visited == null) { // lazy allocation
+                       visited = new ArrayList(1);
+               } else {
+                       int index = visited.indexOf(this);
+                       if (index >= 0) return index == 0; // only blame if directly part of the cycle
+               }
+               visited.add(this);
+
+               return targetConstructor.isRecursive(visited);
+       }
+       
+       public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+
+               //fill up the constructor body with its statements
+               if (ignoreFurtherInvestigation)
+                       return;
+               if (isDefaultConstructor){
+                       constructorCall = SuperReference.implicitSuperConstructorCall();
+                       constructorCall.sourceStart = sourceStart;
+                       constructorCall.sourceEnd = sourceEnd; 
+                       return;
+               }
+               parser.parse(this, unit);
+
+       }
+
+       public StringBuffer printBody(int indent, StringBuffer output) {
+
+               output.append(" {"); //$NON-NLS-1$
+               if (constructorCall != null) {
+                       output.append('\n');
+                       constructorCall.printStatement(indent, output); //$NON-NLS-1$ //$NON-NLS-2$
+               }
+               if (statements != null) {
+                       for (int i = 0; i < statements.length; i++) {
+                               output.append('\n');
+                               statements[i].printStatement(indent, output); //$NON-NLS-1$
+                       }
+               }
+               output.append('\n');
+               printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
+               return output;
+       }
+       
+       public void resolveJavadoc() {
+               
+               if (this.binding == null || this.javadoc != null) {
+                       super.resolveJavadoc();
+               } else if (!isDefaultConstructor) {
+                       this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+               }
+       }
+
+       /*
+        * Type checking for constructor, just another method, except for special check
+        * for recursive constructor invocations.
+        */
+       public void resolveStatements() {
+
+               if (!CharOperation.equals(scope.enclosingSourceType().sourceName, selector)){
+                       scope.problemReporter().missingReturnType(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.constructorCall.accessMode != ExplicitConstructorCall.This) {
+                                       if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) {
+                                               scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall);
+                                       }
+                                       this.constructorCall = null;
+                       } else {
+                               this.constructorCall.resolve(this.scope);
+                       }
+               }
+               if ((modifiers & AccSemicolonBody) != 0) {
+                       scope.problemReporter().methodNeedBody(this);           
+               }
+               super.resolveStatements();
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               ClassScope classScope) {
+
+               if (visitor.visit(this, classScope)) {
+                       if (arguments != null) {
+                               int argumentLength = arguments.length;
+                               for (int i = 0; i < argumentLength; i++)
+                                       arguments[i].traverse(visitor, scope);
+                       }
+                       if (thrownExceptions != null) {
+                               int thrownExceptionsLength = thrownExceptions.length;
+                               for (int i = 0; i < thrownExceptionsLength; i++)
+                                       thrownExceptions[i].traverse(visitor, scope);
+                       }
+                       if (constructorCall != null)
+                               constructorCall.traverse(visitor, scope);
+                       if (statements != null) {
+                               int statementsLength = statements.length;
+                               for (int i = 0; i < statementsLength; i++)
+                                       statements[i].traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, classScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ContinueStatement.java
new file mode 100644 (file)
index 0000000..83831b3
--- /dev/null
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ContinueStatement extends BranchStatement {
+
+       public ContinueStatement(char[] l, int s, int e) {
+               
+               super(l, s, e);
+       }
+       
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // here requires to generate a sequence of finally blocks invocations depending corresponding
+               // to each of the traversed try statements, so that execution will terminate properly.
+
+               // lookup the label, this should answer the returnContext
+               FlowContext targetContext = (label == null)
+                               ? flowContext.getTargetContextForDefaultContinue()
+                               : flowContext.getTargetContextForContinueLabel(label);
+
+               if (targetContext == null) {
+                       if (label == null) {
+                               currentScope.problemReporter().invalidContinue(this);
+                       } else {
+                               currentScope.problemReporter().undefinedLabel(this); 
+                       }
+                       return flowInfo; // pretend it did not continue since no actual target                  
+               } 
+
+               if (targetContext == FlowContext.NotContinuableContext) {
+                       currentScope.problemReporter().invalidContinue(this);
+                       return flowInfo; // pretend it did not continue since no actual target
+               }
+               targetLabel = targetContext.continueLabel();
+               FlowContext traversedContext = flowContext;
+               int subIndex = 0, maxSub = 5;
+               subroutines = new SubRoutineStatement[maxSub];
+
+               do {
+                       SubRoutineStatement sub;
+                       if ((sub = traversedContext.subRoutine()) != null) {
+                               if (subIndex == maxSub) {
+                                       System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[maxSub*=2]), 0, subIndex); // grow
+                               }
+                               subroutines[subIndex++] = sub;
+                               if (sub.isSubRoutineEscaping()) {
+                                       break;
+                               }
+                       }
+                       traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+
+                       ASTNode node;
+                       if ((node = traversedContext.associatedNode) instanceof TryStatement) {
+                               TryStatement tryStatement = (TryStatement) node;
+                               flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits                 
+                       } else if (traversedContext == targetContext) {
+                               // only record continue info once accumulated through subroutines, and only against target context
+                               targetContext.recordContinueFrom(flowInfo);
+                               break;
+                       }
+               } while ((traversedContext = traversedContext.parent) != null);
+               
+               // resize subroutines
+               if (subIndex != maxSub) {
+                       System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[subIndex]), 0, subIndex);
+               }
+               return FlowInfo.DEAD_END;
+       }
+
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+
+               printIndent(tab, output).append("continue "); //$NON-NLS-1$
+               if (label != null) output.append(label);
+               return output.append(';');
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               visitor.visit(this, blockScope);
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/DoStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/DoStatement.java
new file mode 100644 (file)
index 0000000..0dc995d
--- /dev/null
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class DoStatement extends Statement {
+
+       public Expression condition;
+       public Statement action;
+
+       private Label breakLabel, continueLabel;
+
+       // for local variables table attributes
+       int mergedInitStateIndex = -1;
+
+       public DoStatement(Expression condition, Statement action, int s, int e) {
+
+               this.sourceStart = s;
+               this.sourceEnd = e;
+               this.condition = condition;
+               this.action = action;
+               // remember useful empty statement
+               if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               breakLabel = new Label();
+               continueLabel = new Label();
+               LoopingFlowContext loopingContext =
+                       new LoopingFlowContext(
+                               flowContext,
+                               this,
+                               breakLabel,
+                               continueLabel,
+                               currentScope);
+
+               Constant cst = condition.constant;
+               boolean isConditionTrue = cst != NotAConstant && cst.booleanValue() == true;
+               cst = condition.optimizedBooleanConstant();
+               boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+
+               int previousMode = flowInfo.reachMode();
+                               
+               if ((action != null) && !action.isEmptyBlock()) {
+                       flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo);
+
+                       // code generation can be optimized when no need to continue in the loop
+                       if (!flowInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
+                               continueLabel = null;
+                       }
+               }
+               /* Reset reach mode, to address following scenario.
+                *   final blank;
+                *   do { if (true) break; else blank = 0; } while(false);
+                *   blank = 1; // may be initialized already 
+                */
+               flowInfo.setReachMode(previousMode);
+               
+               flowInfo =
+                       condition.analyseCode(
+                               currentScope,
+                               loopingContext,
+                               (action == null
+                                       ? flowInfo
+                                       : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
+               if (!isConditionOptimizedFalse && continueLabel != null) {
+                       loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
+               }
+
+               // end of loop
+               FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+                               loopingContext.initsOnBreak, 
+                               isConditionOptimizedTrue, 
+                               flowInfo.initsWhenFalse(), 
+                               false, // never consider opt false case for DO loop, since break can always occur (47776)
+                               !isConditionTrue /*do{}while(true); unreachable(); */);
+               mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+               return mergedInfo;
+       }
+
+       /**
+        * Do statement code generation
+        *
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+               if ((bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               int pc = codeStream.position;
+
+               // labels management
+               Label actionLabel = new Label(codeStream);
+               actionLabel.place();
+               breakLabel.initialize(codeStream);
+               if (continueLabel != null) {
+                       continueLabel.initialize(codeStream);
+               }
+
+               // generate action
+               if (action != null) {
+                       action.generateCode(currentScope, codeStream);
+               }
+               // generate condition
+               if (continueLabel != null) {
+                       continueLabel.place();
+                       condition.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               actionLabel,
+                               null,
+                               true);
+               }
+               breakLabel.place();
+
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               printIndent(indent, output).append("do"); //$NON-NLS-1$
+               if (action == null)
+                       output.append(" ;\n"); //$NON-NLS-1$
+               else {
+                       output.append('\n');
+                       action.printStatement(indent + 1, output).append('\n');
+               }
+               output.append("while ("); //$NON-NLS-1$
+               return condition.printExpression(0, output).append(");"); //$NON-NLS-1$
+       }
+       public void resolve(BlockScope scope) {
+
+               TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
+               condition.implicitWidening(type, type);
+               if (action != null)
+                       action.resolve(scope);
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       if (action != null) {
+                               action.traverse(visitor, scope);
+                       }
+                       condition.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/DoubleLiteral.java
new file mode 100644 (file)
index 0000000..139c813
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+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
+
+       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]){
+                                       case '0' :
+                                       case '.' :
+                                       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
+                       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);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/EmptyStatement.java
new file mode 100644 (file)
index 0000000..bd570e6
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+
+public class EmptyStatement extends Statement {
+
+       public EmptyStatement(int startPosition, int endPosition) {
+               this.sourceStart = startPosition;
+               this.sourceEnd = endPosition;
+       }
+
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+               return flowInfo;
+       }
+
+       // Report an error if necessary
+       public boolean complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, boolean didAlreadyComplain) {
+               
+               // before 1.4, empty statements are tolerated anywhere
+               if (scope.environment().options.complianceLevel < ClassFileConstants.JDK1_4) {
+                       return false;
+               }
+               return super.complainIfUnreachable(flowInfo, scope, didAlreadyComplain);
+       }
+       
+       public void generateCode(BlockScope currentScope, CodeStream codeStream){
+               // no bytecode, no need to check for reachability or recording source positions
+       }
+       
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+               return printIndent(tab, output).append(';');
+       }
+               
+       public void resolve(BlockScope scope) {
+               if ((bits & IsUsefulEmptyStatementMASK) == 0) {
+                       scope.problemReporter().superfluousSemicolon(this.sourceStart, this.sourceEnd);
+               } else {
+                       scope.problemReporter().emptyControlFlowStatement(this.sourceStart, this.sourceEnd);
+               }
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+       
+
+}
+
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
new file mode 100644 (file)
index 0000000..0caeb81
--- /dev/null
@@ -0,0 +1,578 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+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 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);
+               }
+               if (castType.isBaseType()) {
+                       return false;
+               }
+               if (castType.isClass()) { //------(castTb.isClass) expressionTb.isArray --------------- 
+                       if (castType.id == T_Object)
+                               return true;
+                       return false;
+               }
+               if (castType.isInterface()) { //------- (castTb.isInterface) expressionTb.isArray -----------
+                       if (castType.id == T_JavaLangCloneable || castType.id == T_JavaIoSerializable) {
+                               return true;
+                       }
+                       return false;
+               }
+
+               return false;
+       }
+
+       //------------(castType) null--------------
+       if (expressionType == NullBinding) {
+               return !castType.isBaseType();
+       }
+
+       //========BASETYPE==============
+       if (expressionType.isBaseType()) {
+               return false;
+       }
+
+
+       //========REFERENCE TYPE===================
+
+       if (expressionType.isClass()) {
+               if (castType.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
+                       if (expressionType.id == T_Object)
+                               return true;
+               }
+               if (castType.isBaseType()) {
+                       return false;
+               }
+               if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------ 
+                       if (expressionType.isCompatibleWith(castType))
+                               return true;
+                       else {
+                               if (castType.isCompatibleWith(expressionType)) {
+                                       return true;
+                               }
+                               return false;
+                       }
+               }
+               if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isClass -------  
+                       if (expressionType.isCompatibleWith(castType))
+                               return true;                
+                       if (!((ReferenceBinding) expressionType).isFinal()) {
+                               return true;
+                       }
+                       //no subclass for expressionTb, thus compile-time check is valid                        
+               }
+
+               return false;
+       }
+       if (expressionType.isInterface()) {
+               if (castType.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
+                       if (expressionType.id == T_JavaLangCloneable || expressionType.id == T_JavaIoSerializable)
+                               //potential runtime error
+                               {
+                               return true;
+                       }
+                       return false;
+               }
+               if (castType.isBaseType()) {
+                       return false;
+               }
+               if (castType.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
+                       if (castType.id == T_Object)
+                               return true;
+                       if (((ReferenceBinding) castType).isFinal()) { //no subclass for castTb, thus compile-time check is valid
+                               if (castType.isCompatibleWith(expressionType)) {
+                                       return true;
+                               }
+                               return false;
+                       }
+                       return true;
+               }
+               if (castType.isInterface()) { // ----- (castTb.isInterface) expressionTb.isInterface -------
+                       if (expressionType.isCompatibleWith(castType))
+                               return true;
+                       if (!castType.isCompatibleWith(expressionType)) {
+                               MethodBinding[] castTbMethods = ((ReferenceBinding) castType).methods();
+                               int castTbMethodsLength = castTbMethods.length;
+                               MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionType).methods();
+                               int expressionTbMethodsLength = expressionTbMethods.length;
+                               for (int i = 0; i < castTbMethodsLength; i++) {
+                                       for (int j = 0; j < expressionTbMethodsLength; j++) {
+                                               if (CharOperation.equals(castTbMethods[i].selector, expressionTbMethods[j].selector)) {
+                                                       if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
+                                                               if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) {
+                                                                       return false;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       return true;
+               }
+               return false;
+       }
+       return false;
+}
+public final void computeConstant(TypeBinding leftType, TypeBinding rightType) {
+       if ((this.left.constant != NotAConstant) && (this.right.constant != NotAConstant)) {
+               this.constant =
+                       Constant.computeConstantOperationEQUAL_EQUAL(
+                               left.constant,
+                               leftType.id,
+                               EQUAL_EQUAL,
+                               right.constant,
+                               rightType.id);
+               if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
+                       constant = Constant.fromValue(!constant.booleanValue());
+       } else {
+               this.constant = NotAConstant;
+               // no optimization for null == null
+       }
+}
+/**
+ * Normal == or != code generation.
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+       if (constant != NotAConstant) {
+               int pc = codeStream.position;
+               if (valueRequired) 
+                       codeStream.generateConstant(constant, implicitConversion);
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+               return;
+       }
+       Label falseLabel;
+       bits |= OnlyValueRequiredMASK;
+       generateOptimizedBoolean(
+               currentScope, 
+               codeStream, 
+               null, 
+               falseLabel = new Label(codeStream), 
+               valueRequired);
+       if (falseLabel.hasForwardReferences()) {
+               if (valueRequired){
+                       // comparison is TRUE 
+                       codeStream.iconst_1();
+                       if ((bits & ValueForReturnMASK) != 0){
+                               codeStream.ireturn();
+                               // comparison is FALSE
+                               falseLabel.place();
+                               codeStream.iconst_0();
+                       } else {
+                               Label endLabel = new Label(codeStream);
+                               codeStream.goto_(endLabel);
+                               codeStream.decrStackSize(1);
+                               // comparison is FALSE
+                               falseLabel.place();
+                               codeStream.iconst_0();
+                               endLabel.place();
+                       }
+               } else {
+                       falseLabel.place();
+               }       
+       }
+}
+/**
+ * Boolean operator code generation
+ *     Optimized operations are: == and !=
+ */
+public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+       if (constant != Constant.NotAConstant) {
+               super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+               return;
+       }
+       if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+               if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
+                       generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+               } else {
+                       generateOptimizedNonBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+               }
+       } else {
+               if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
+                       generateOptimizedBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
+               } else {
+                       generateOptimizedNonBooleanEqual(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
+               }
+       }
+}
+/**
+ * Boolean generation for == with boolean operands
+ *
+ * Note this code does not optimize conditional constants !!!!
+ */
+public void generateOptimizedBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+       // optimized cases: true == x, false == x
+       if (left.constant != NotAConstant) {
+               boolean inline = left.constant.booleanValue();
+               right.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
+               return;
+       } // optimized cases: x == true, x == false
+       if (right.constant != NotAConstant) {
+               boolean inline = right.constant.booleanValue();
+               left.generateOptimizedBoolean(currentScope, codeStream, (inline ? trueLabel : falseLabel), (inline ? falseLabel : trueLabel), valueRequired);
+               return;
+       }
+       // default case
+       left.generateCode(currentScope, codeStream, valueRequired);
+       right.generateCode(currentScope, codeStream, valueRequired);
+       if (valueRequired) {
+               if (falseLabel == null) {
+                       if (trueLabel != null) {
+                               // implicit falling through the FALSE case
+                               codeStream.if_icmpeq(trueLabel);
+                       }
+               } else {
+                       // implicit falling through the TRUE case
+                       if (trueLabel == null) {
+                               codeStream.if_icmpne(falseLabel);
+                       } else {
+                               // no implicit fall through TRUE/FALSE --> should never occur
+                       }
+               }
+       }
+       // reposition the endPC
+       codeStream.updateLastRecordedEndPC(codeStream.position);                                        
+}
+/**
+ * Boolean generation for == with non-boolean operands
+ *
+ */
+public void generateOptimizedNonBooleanEqual(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+       int pc = codeStream.position;
+       Constant inline;
+       if ((inline = right.constant) != NotAConstant) {
+               // optimized case: x == 0
+               if (((left.implicitConversion >> 4) == T_int) && (inline.intValue() == 0)) {
+                       left.generateCode(currentScope, codeStream, valueRequired);
+                       if (valueRequired) {
+                               if (falseLabel == null) {
+                                       if (trueLabel != null) {
+                                               // implicit falling through the FALSE case
+                                               codeStream.ifeq(trueLabel);
+                                       }
+                               } else {
+                                       // implicit falling through the TRUE case
+                                       if (trueLabel == null) {
+                                               codeStream.ifne(falseLabel);
+                                       } else {
+                                               // no implicit fall through TRUE/FALSE --> should never occur
+                                       }
+                               }
+                       }
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+       }
+       if ((inline = left.constant) != NotAConstant) {
+               // optimized case: 0 == x
+               if (((left.implicitConversion >> 4) == T_int)
+                       && (inline.intValue() == 0)) {
+                       right.generateCode(currentScope, codeStream, valueRequired);
+                       if (valueRequired) {
+                               if (falseLabel == null) {
+                                       if (trueLabel != null) {
+                                               // implicit falling through the FALSE case
+                                               codeStream.ifeq(trueLabel);
+                                       }
+                               } else {
+                                       // implicit falling through the TRUE case
+                                       if (trueLabel == null) {
+                                               codeStream.ifne(falseLabel);
+                                       } else {
+                                               // no implicit fall through TRUE/FALSE --> should never occur
+                                       }
+                               }
+                       }
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+       }
+       // null cases
+       // optimized case: x == null
+       if (right instanceof NullLiteral) {
+               if (left instanceof NullLiteral) {
+                       // null == null
+                       if (valueRequired) {
+                                       if ((bits & OnlyValueRequiredMASK) != 0) {
+                                               if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
+                                                       codeStream.iconst_1();
+                                               } else {
+                                                       codeStream.iconst_0();
+                                               }
+                                       } else {
+                                               if (falseLabel == null) {
+                                                       // implicit falling through the FALSE case
+                                                       if (trueLabel != null) {
+                                                               codeStream.goto_(trueLabel);
+                                                       }
+                                               }
+                               }
+                       }
+               } else {
+                       left.generateCode(currentScope, codeStream, valueRequired);
+                       if (valueRequired) {
+                               if (falseLabel == null) {
+                                       if (trueLabel != null) {
+                                               // implicit falling through the FALSE case
+                                               codeStream.ifnull(trueLabel);
+                                       }
+                               } else {
+                                       // implicit falling through the TRUE case
+                                       if (trueLabel == null) {
+                                               codeStream.ifnonnull(falseLabel);
+                                       } else {
+                                               // no implicit fall through TRUE/FALSE --> should never occur
+                                       }
+                               }
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+               return;
+       } else if (left instanceof NullLiteral) { // optimized case: null == x
+               right.generateCode(currentScope, codeStream, valueRequired);
+               if (valueRequired) {
+                       if (falseLabel == null) {
+                               if (trueLabel != null) {
+                                       // implicit falling through the FALSE case
+                                       codeStream.ifnull(trueLabel);
+                               }
+                       } else {
+                               // implicit falling through the TRUE case
+                               if (trueLabel == null) {
+                                       codeStream.ifnonnull(falseLabel);
+                               } else {
+                                       // no implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+               return;
+       }
+
+       // 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;
+       }
+
+       // 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);
+                       return null;
+               }
+               // check need for operand cast
+               if (leftIsCast || rightIsCast) {
+                       CastExpression.checkNeedForArgumentCasts(scope, EQUAL_EQUAL, operatorSignature, left, leftType.id, leftIsCast, right, rightType.id, rightIsCast);
+               }
+               computeConstant(leftType, rightType);
+               return this.resolvedType = BooleanBinding;
+       }
+
+       // Object references 
+       // spec 15.20.3
+       if (areTypesCastCompatible(scope, rightType, leftType) || areTypesCastCompatible(scope, leftType, rightType)) {
+               // (special case for String)
+               if ((rightType.id == T_String) && (leftType.id == T_String)) {
+                       computeConstant(leftType, rightType);
+               } else {
+                       constant = NotAConstant;
+               }
+               if (rightType.id == T_String) {
+                       right.implicitConversion = String2String;
+               }
+               if (leftType.id == T_String) {
+                       left.implicitConversion = String2String;
+               }
+               // check need for operand cast
+               boolean unnecessaryLeftCast = (left.bits & UnnecessaryCastMask) != 0;
+               boolean unnecessaryRightCast = (right.bits & UnnecessaryCastMask) != 0;
+               if (unnecessaryLeftCast || unnecessaryRightCast) {
+                       TypeBinding alternateLeftType = unnecessaryLeftCast ? ((CastExpression)left).expression.resolvedType : leftType;
+                       TypeBinding alternateRightType = unnecessaryRightCast ? ((CastExpression)right).expression.resolvedType : rightType;
+                       if (areTypesCastCompatible(scope, alternateLeftType, alternateRightType)
+                                       || areTypesCastCompatible(scope, alternateRightType, alternateLeftType)) {
+                               if (unnecessaryLeftCast) scope.problemReporter().unnecessaryCast((CastExpression)left); 
+                               if (unnecessaryRightCast) scope.problemReporter().unnecessaryCast((CastExpression)right);
+                       }
+               }
+               return this.resolvedType = BooleanBinding;
+       }
+       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);
+       }
+       visitor.endVisit(this, scope);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
new file mode 100644 (file)
index 0000000..ec709ff
--- /dev/null
@@ -0,0 +1,340 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ExplicitConstructorCall
+       extends Statement
+       implements InvocationSite {
+               
+       public Expression[] arguments;
+       public Expression qualification;
+       public MethodBinding binding;
+
+       public int accessMode;
+
+       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;
+
+       public ExplicitConstructorCall(int accessMode) {
+               this.accessMode = accessMode;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // must verify that exceptions potentially thrown by this expression are caught in the method.
+
+               try {
+                       ((MethodScope) currentScope).isConstructorCall = true;
+
+                       // process enclosing instance
+                       if (qualification != null) {
+                               flowInfo =
+                                       qualification
+                                               .analyseCode(currentScope, flowContext, flowInfo)
+                                               .unconditionalInits();
+                       }
+                       // process arguments
+                       if (arguments != null) {
+                               for (int i = 0, max = arguments.length; i < max; i++) {
+                                       flowInfo =
+                                               arguments[i]
+                                                       .analyseCode(currentScope, flowContext, flowInfo)
+                                                       .unconditionalInits();
+                               }
+                       }
+
+                       ReferenceBinding[] thrownExceptions;
+                       if ((thrownExceptions = binding.thrownExceptions) != NoExceptions) {
+                               // check exceptions
+                               flowContext.checkExceptionHandlers(
+                                       thrownExceptions,
+                                       (accessMode == ImplicitSuper)
+                                               ? (ASTNode) currentScope.methodScope().referenceContext
+                                               : (ASTNode) this,
+                                       flowInfo,
+                                       currentScope);
+                       }
+                       manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+                       manageSyntheticAccessIfNecessary(currentScope, flowInfo);
+                       return flowInfo;
+               } finally {
+                       ((MethodScope) currentScope).isConstructorCall = false;
+               }
+       }
+
+       /**
+        * Constructor call 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;
+               }
+               try {
+                       ((MethodScope) currentScope).isConstructorCall = true;
+
+                       int pc = codeStream.position;
+                       codeStream.aload_0();
+
+                       // handling innerclass constructor invocation
+                       ReferenceBinding targetType = binding.declaringClass;
+                       // handling innerclass instance allocation - enclosing instance arguments
+                       if (targetType.isNestedType()) {
+                               codeStream.generateSyntheticEnclosingInstanceValues(
+                                       currentScope,
+                                       targetType,
+                                       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);
+                               }
+                       }
+                       // handling innerclass instance allocation - outer local arguments
+                       if (targetType.isNestedType()) {
+                               codeStream.generateSyntheticOuterArgumentValues(
+                                       currentScope,
+                                       targetType,
+                                       this);
+                       }
+                       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;
+                                       i < max;
+                                       i++) {
+                                       codeStream.aconst_null();
+                               }
+                               codeStream.invokespecial(syntheticAccessor);
+                       } else {
+                               codeStream.invokespecial(binding);
+                       }
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+               } finally {
+                       ((MethodScope) currentScope).isConstructorCall = false;
+               }
+       }
+
+       public boolean isImplicitSuper() {
+               //return true if I'm of these compiler added statement super();
+
+               return (accessMode == ImplicitSuper);
+       }
+
+       public boolean isSuperAccess() {
+
+               return accessMode != This;
+       }
+
+       public boolean isTypeAccess() {
+
+               return true;
+       }
+
+       /* Inner emulation consists in either recording a dependency 
+        * link only, or performing one level of propagation.
+        *
+        * Dependency mechanism is used whenever dealing with source target
+        * types, since by the time we reach them, we might not yet know their
+        * exact need.
+        */
+       void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+               ReferenceBinding superType;
+
+               if (!flowInfo.isReachable()) return;
+               // perform some emulation work in case there is some and we are inside a local type only
+               if ((superType = binding.declaringClass).isNestedType()
+                       && currentScope.enclosingSourceType().isLocalType()) {
+
+                       if (superType.isLocalType()) {
+                               ((LocalTypeBinding) superType).addInnerEmulationDependent(currentScope, qualification != null);
+                       } else {
+                               // locally propagate, since we already now the desired shape for sure
+                               currentScope.propagateInnerEmulation(superType, qualification != null);
+                       }
+               }
+       }
+
+       public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               // perform some emulation work in case there is some and we are inside a local type only
+               if (binding.isPrivate() && (accessMode != This)) {
+
+                       if (currentScope
+                               .environment()
+                               .options
+                               .isPrivateConstructorAccessChangingVisibility) {
+                               binding.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);
+                       }
+               }
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               printIndent(indent, output);
+               if (qualification != null) qualification.printExpression(0, output).append('.');
+               if (accessMode == This) {
+                       output.append("this("); //$NON-NLS-1$
+               } else {
+                       output.append("super("); //$NON-NLS-1$
+               }
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               arguments[i].printExpression(0, output);
+                       }
+               }
+               return output.append(");"); //$NON-NLS-1$
+       }
+       
+       public void resolve(BlockScope scope) {
+               // the return type should be void for a constructor.
+               // the test is made into getConstructor
+
+               // mark the fact that we are in a constructor call.....
+               // unmark at all returns
+               MethodScope methodScope = scope.methodScope();
+               try {
+                       AbstractMethodDeclaration methodDeclaration = methodScope.referenceMethod();
+                       if (methodDeclaration == null 
+                                       || !methodDeclaration.isConstructor()
+                                       || ((ConstructorDeclaration) methodDeclaration).constructorCall != this) {
+                               scope.problemReporter().invalidExplicitConstructorCall(this);
+                               return;
+                       }
+                       methodScope.isConstructorCall = true;
+                       ReferenceBinding receiverType = scope.enclosingSourceType();
+                       if (accessMode != This)
+                               receiverType = receiverType.superclass();
+
+                       if (receiverType == null) {
+                               return;
+                       }
+
+                       // qualification should be from the type of the enclosingType
+                       if (qualification != null) {
+                               if (accessMode != Super) {
+                                       scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
+                                               qualification,
+                                               receiverType);
+                               }
+                               ReferenceBinding enclosingType = receiverType.enclosingType();
+                               if (enclosingType == null) {
+                                       scope.problemReporter().unnecessaryEnclosingInstanceSpecification(
+                                               qualification,
+                                               receiverType);
+                                       discardEnclosingInstance = true;
+                               } else {
+                                       TypeBinding qTb = qualification.resolveTypeExpecting(scope, enclosingType);
+                                       qualification.implicitWidening(qTb, qTb);
+                               }
+                       }
+
+                       // arguments buffering for the method lookup
+                       TypeBinding[] argumentTypes = NoParameters;
+                       boolean argsContainCast = false;
+                       if (arguments != null) {
+                               boolean argHasError = false; // typeChecks all arguments
+                               int length = arguments.length;
+                               argumentTypes = new TypeBinding[length];
+                               for (int i = 0; i < length; i++) {
+                                       Expression argument = this.arguments[i];
+                                       if (argument instanceof CastExpression) {
+                                               argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+                                               argsContainCast = true;
+                                       }
+                                       if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
+                                               argHasError = true;
+                                       }
+                               }
+                               if (argHasError) {
+                                       return;
+                               }
+                       }
+                       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 (binding.isPrivate()) {
+                                       binding.modifiers |= AccPrivateUsed;
+                               }                               
+                       } else {
+                               if (binding.declaringClass == null)
+                                       binding.declaringClass = receiverType;
+                               scope.problemReporter().invalidConstructor(this, binding);
+                       }
+               } finally {
+                       methodScope.isConstructorCall = false;
+               }
+       }
+
+       public void setActualReceiverType(ReferenceBinding receiverType) {
+               // ignored
+       }
+
+       public void setDepth(int depth) {
+               // ignore for here
+       }
+
+       public void setFieldIndex(int depth) {
+               // ignore for here
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       if (this.qualification != null) {
+                               this.qualification.traverse(visitor, scope);
+                       }
+                       if (this.arguments != null) {
+                               for (int i = 0, argumentLength = this.arguments.length; i < argumentLength; i++)
+                                       this.arguments[i].traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Expression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Expression.java
new file mode 100644 (file)
index 0000000..ae3b502
--- /dev/null
@@ -0,0 +1,496 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+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,
+               int targetTypeID) {
+
+               //true if there is no loss of precision while casting.
+               // constantTypeID == constant.typeID
+               if (targetTypeID == constantTypeID)
+                       return true;
+               switch (targetTypeID) {
+                       case T_char :
+                               switch (constantTypeID) {
+                                       case T_char :
+                                               return true;
+                                       case T_double :
+                                               return constant.doubleValue() == constant.charValue();
+                                       case T_float :
+                                               return constant.floatValue() == constant.charValue();
+                                       case T_int :
+                                               return constant.intValue() == constant.charValue();
+                                       case T_short :
+                                               return constant.shortValue() == constant.charValue();
+                                       case T_byte :
+                                               return constant.byteValue() == constant.charValue();
+                                       case T_long :
+                                               return constant.longValue() == constant.charValue();
+                                       default :
+                                               return false;//boolean
+                               } 
+
+                       case T_float :
+                               switch (constantTypeID) {
+                                       case T_char :
+                                               return constant.charValue() == constant.floatValue();
+                                       case T_double :
+                                               return constant.doubleValue() == constant.floatValue();
+                                       case T_float :
+                                               return true;
+                                       case T_int :
+                                               return constant.intValue() == constant.floatValue();
+                                       case T_short :
+                                               return constant.shortValue() == constant.floatValue();
+                                       case T_byte :
+                                               return constant.byteValue() == constant.floatValue();
+                                       case T_long :
+                                               return constant.longValue() == constant.floatValue();
+                                       default :
+                                               return false;//boolean
+                               } 
+                               
+                       case T_double :
+                               switch (constantTypeID) {
+                                       case T_char :
+                                               return constant.charValue() == constant.doubleValue();
+                                       case T_double :
+                                               return true;
+                                       case T_float :
+                                               return constant.floatValue() == constant.doubleValue();
+                                       case T_int :
+                                               return constant.intValue() == constant.doubleValue();
+                                       case T_short :
+                                               return constant.shortValue() == constant.doubleValue();
+                                       case T_byte :
+                                               return constant.byteValue() == constant.doubleValue();
+                                       case T_long :
+                                               return constant.longValue() == constant.doubleValue();
+                                       default :
+                                               return false; //boolean
+                               } 
+                               
+                       case T_byte :
+                               switch (constantTypeID) {
+                                       case T_char :
+                                               return constant.charValue() == constant.byteValue();
+                                       case T_double :
+                                               return constant.doubleValue() == constant.byteValue();
+                                       case T_float :
+                                               return constant.floatValue() == constant.byteValue();
+                                       case T_int :
+                                               return constant.intValue() == constant.byteValue();
+                                       case T_short :
+                                               return constant.shortValue() == constant.byteValue();
+                                       case T_byte :
+                                               return true;
+                                       case T_long :
+                                               return constant.longValue() == constant.byteValue();
+                                       default :
+                                               return false; //boolean
+                               } 
+                               
+                       case T_short :
+                               switch (constantTypeID) {
+                                       case T_char :
+                                               return constant.charValue() == constant.shortValue();
+                                       case T_double :
+                                               return constant.doubleValue() == constant.shortValue();
+                                       case T_float :
+                                               return constant.floatValue() == constant.shortValue();
+                                       case T_int :
+                                               return constant.intValue() == constant.shortValue();
+                                       case T_short :
+                                               return true;
+                                       case T_byte :
+                                               return constant.byteValue() == constant.shortValue();
+                                       case T_long :
+                                               return constant.longValue() == constant.shortValue();
+                                       default :
+                                               return false; //boolean
+                               } 
+                               
+                       case T_int :
+                               switch (constantTypeID) {
+                                       case T_char :
+                                               return constant.charValue() == constant.intValue();
+                                       case T_double :
+                                               return constant.doubleValue() == constant.intValue();
+                                       case T_float :
+                                               return constant.floatValue() == constant.intValue();
+                                       case T_int :
+                                               return true;
+                                       case T_short :
+                                               return constant.shortValue() == constant.intValue();
+                                       case T_byte :
+                                               return constant.byteValue() == constant.intValue();
+                                       case T_long :
+                                               return constant.longValue() == constant.intValue();
+                                       default :
+                                               return false; //boolean
+                               } 
+                               
+                       case T_long :
+                               switch (constantTypeID) {
+                                       case T_char :
+                                               return constant.charValue() == constant.longValue();
+                                       case T_double :
+                                               return constant.doubleValue() == constant.longValue();
+                                       case T_float :
+                                               return constant.floatValue() == constant.longValue();
+                                       case T_int :
+                                               return constant.intValue() == constant.longValue();
+                                       case T_short :
+                                               return constant.shortValue() == constant.longValue();
+                                       case T_byte :
+                                               return constant.byteValue() == constant.longValue();
+                                       case T_long :
+                                               return true;
+                                       default :
+                                               return false; //boolean
+                               } 
+                               
+                       default :
+                               return false; //boolean
+               } 
+       }
+
+       /**
+        * Expression statements are plain expressions, however they generate like
+        * normal expressions with no value required.
+        *
+        * @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;
+               }
+               generateCode(currentScope, codeStream, false);
+       }
+
+       /**
+        * Every expression is responsible for generating its implicit conversion when necessary.
+        *
+        * @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) {
+                       // generate a constant expression
+                       int pc = codeStream.position;
+                       codeStream.generateConstant(constant, implicitConversion);
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+               } else {
+                       // actual non-constant code generation
+                       throw new ShouldNotImplement(Util.bind("ast.missingCode")); //$NON-NLS-1$
+               }
+       }
+
+       /**
+        * Default generation of a boolean value
+        * @param currentScope
+        * @param codeStream
+        * @param trueLabel
+        * @param falseLabel
+        * @param valueRequired
+        */
+       public void generateOptimizedBoolean(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               // a label valued to nil means: by default we fall through the case... 
+               // both nil means we leave the value on the stack
+
+               if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
+                       int pc = codeStream.position;
+                       if (constant.booleanValue() == true) {
+                               // constant == true
+                               if (valueRequired) {
+                                       if (falseLabel == null) {
+                                               // implicit falling through the FALSE case
+                                               if (trueLabel != null) {
+                                                       codeStream.goto_(trueLabel);
+                                               }
+                                       }
+                               }
+                       } else {
+                               if (valueRequired) {
+                                       if (falseLabel != null) {
+                                               // implicit falling through the TRUE case
+                                               if (trueLabel == null) {
+                                                       codeStream.goto_(falseLabel);
+                                               }
+                                       }
+                               }
+                       }
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               generateCode(currentScope, codeStream, valueRequired);
+               // branching
+               int position = codeStream.position;
+               if (valueRequired) {
+                       if (falseLabel == null) {
+                               if (trueLabel != null) {
+                                       // Implicit falling through the FALSE case
+                                       codeStream.ifne(trueLabel);
+                               }
+                       } else {
+                               if (trueLabel == null) {
+                                       // Implicit falling through the TRUE case
+                                       codeStream.ifeq(falseLabel);
+                               } else {
+                                       // No implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+               // reposition the endPC
+               codeStream.updateLastRecordedEndPC(position);
+       }
+
+       /* 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.
+        * By default: no optimization.
+        */
+       public void generateOptimizedStringBuffer(
+               BlockScope blockScope,
+               org.eclipse.jdt.internal.compiler.codegen.CodeStream codeStream,
+               int typeID) {
+
+               if (typeID == T_String && this.constant != NotAConstant && this.constant.stringValue().length() == 0) {
+                       return; // optimize str + ""
+               }
+               generateCode(blockScope, codeStream, true);
+               codeStream.invokeStringBufferAppendForType(typeID);
+       }
+
+       /* 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(
+               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.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 {
+                               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;
+                               break;
+                       default : //nothing on regular object ref
+               }
+       }
+
+       public boolean isCompactableOperation() {
+
+               return false;
+       }
+
+       //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
+       //(this request some work d be done by the VM on signed numbers)
+       public boolean isConstantValueOfTypeAssignableToType(
+               TypeBinding constantType,
+               TypeBinding targetType) {
+
+               if (constant == Constant.NotAConstant)
+                       return false;
+               if (constantType == targetType)
+                       return true;
+               if (constantType.isBaseType() && targetType.isBaseType()) {
+                       //No free assignment conversion from anything but to integral ones.
+                       if ((constantType == IntBinding
+                               || BaseTypeBinding.isWidening(T_int, constantType.id))
+                               && (BaseTypeBinding.isNarrowing(targetType.id, T_int))) {
+                               //use current explicit conversion in order to get some new value to compare with current one
+                               return isConstantValueRepresentable(constant, constantType.id, targetType.id);
+                       }
+               }
+               return false;
+       }
+
+       public boolean isTypeReference() {
+               return false;
+       }
+
+       public void resolve(BlockScope scope) {
+               // drops the returning expression's type whatever the type is.
+
+               this.resolveType(scope);
+               return;
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+               // by default... subclasses should implement a better TC if required.
+
+               return null;
+       }
+
+       public TypeBinding resolveType(ClassScope classScope) {
+               // by default... subclasses should implement a better TB if required.
+               return null;
+       }
+
+       public TypeBinding resolveTypeExpecting(
+               BlockScope scope,
+               TypeBinding expectedType) {
+
+               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;
+               }
+               return expressionType;
+       }
+
+       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 Expression toTypeReference() {
+               //by default undefined
+
+               //this method is meanly used by the parser in order to transform
+               //an expression that is used as a type reference in a cast ....
+               //--appreciate the fact that castExpression and ExpressionWithParenthesis
+               //--starts with the same pattern.....
+
+               return this;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ExtendedStringLiteral.java
new file mode 100644 (file)
index 0000000..68b8fde
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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;
+
+public class ExtendedStringLiteral extends StringLiteral {
+
+       /** 
+        *  Build a string+char literal
+        */
+       public ExtendedStringLiteral(StringLiteral str, CharLiteral character) {
+
+               super(str.source, str.sourceStart, str.sourceEnd);
+               extendWith(character);
+       }
+
+       /**     
+        * Build a two-strings literal
+        * */
+       public ExtendedStringLiteral(StringLiteral str1, StringLiteral str2) {
+
+               super(str1.source, str1.sourceStart, str1.sourceEnd);
+               extendWith(str2);
+       }
+
+       /**
+        * Add the lit source to mine, just as if it was mine
+        */
+       public ExtendedStringLiteral extendWith(CharLiteral lit) {
+
+               //update the source
+               int length = source.length;
+               System.arraycopy(source, 0, (source = new char[length + 1]), 0, length);
+               source[length] = lit.value;
+               //position at the end of all literals
+               sourceEnd = lit.sourceEnd;
+               return this;
+       }
+
+       /**
+        *  Add the lit source to mine, just as if it was mine
+        */
+       public ExtendedStringLiteral extendWith(StringLiteral lit) {
+
+               //uddate the source
+               int length = source.length;
+               System.arraycopy(
+                       source,
+                       0,
+                       source = new char[length + lit.source.length],
+                       0,
+                       length);
+               System.arraycopy(lit.source, 0, source, length, lit.source.length);
+               //position at the end of all literals
+               sourceEnd = lit.sourceEnd;
+               return this;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               return output.append("ExtendedStringLiteral{").append(source).append('}'); //$NON-NLS-1$
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/FalseLiteral.java
new file mode 100644 (file)
index 0000000..82bc72d
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.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.*;
+
+public class FalseLiteral extends MagicLiteral {
+       static final char[] source = {'f', 'a', 'l', 's', 'e'};
+public FalseLiteral(int s , int e) {
+       super(s,e);
+}
+public void computeConstant() {
+
+       constant = Constant.fromValue(false);}
+/**
+ * Code generation for false 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.iconst_0();
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+       // falseLabel being not nil means that we will not fall through into the FALSE case
+
+       int pc = codeStream.position;
+       if (valueRequired) {
+               if (falseLabel != null) {
+                       // implicit falling through the TRUE case
+                       if (trueLabel == null) {
+                               codeStream.goto_(falseLabel);
+                       }
+               }
+       }
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public TypeBinding literalType(BlockScope scope) {
+       return BooleanBinding;
+}
+/**
+ * 
+ */
+public char[] source() {
+       return source;
+}
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+       visitor.visit(this, scope);
+       visitor.endVisit(this, scope);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
new file mode 100644 (file)
index 0000000..7f001c3
--- /dev/null
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+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;
+
+       //allows to retrieve both the "type" part of the declaration (part1)
+       //and also the part that decribe the name and the init and optionally
+       //some other dimension ! .... 
+       //public int[] a, b[] = X, c ;
+       //for b that would give for 
+       // - part1 : public int[]
+       // - part2 : b[] = X,
+
+       public int endPart1Position;
+       public int endPart2Position;
+
+       public FieldDeclaration() {
+               // for subtypes or conversion
+       }
+
+       public FieldDeclaration(
+               char[] name,
+               int sourceStart,
+               int sourceEnd) {
+
+               this.name = name;
+
+               //due to some declaration like 
+               // int x, y = 3, z , x ;
+               //the sourceStart and the sourceEnd is ONLY on  the name
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               MethodScope initializationScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
+                       if (!initializationScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
+                               initializationScope.problemReporter().unusedPrivateField(this);
+                       }
+               }
+               // 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()) {
+                       initializationScope.problemReporter().unexpectedStaticModifierForField(
+                               (SourceTypeBinding) this.binding.declaringClass,
+                               this);
+               }
+
+               if (this.initialization != null) {
+                       flowInfo =
+                               this.initialization
+                                       .analyseCode(initializationScope, flowContext, flowInfo)
+                                       .unconditionalInits();
+                       flowInfo.markAsDefinitelyAssigned(this.binding);
+               }
+               return flowInfo;
+       }
+
+       /**
+        * Code generation for a field declaration:
+        *         standard assignment to a field 
+        *
+        * @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 ((this.bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               // do not generate initialization code if final and static (constant is then
+               // recorded inside the field itself).
+               int pc = codeStream.position;
+               boolean isStatic;
+               if (this.initialization != null
+                       && !((isStatic = this.binding.isStatic()) && this.binding.constant != NotAConstant)) {
+                       // non-static field, need receiver
+                       if (!isStatic)
+                               codeStream.aload_0();
+                       // generate initialization value
+                       this.initialization.generateCode(currentScope, codeStream, true);
+                       // store into field
+                       if (isStatic) {
+                               codeStream.putstatic(this.binding);
+                       } else {
+                               codeStream.putfield(this.binding);
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public TypeBinding getTypeBinding(Scope scope) {
+
+               return this.type.getTypeBinding(scope);
+       }
+
+       public boolean isField() {
+
+               return true;
+       }
+
+       public boolean isStatic() {
+
+               if (this.binding != null)
+                       return this.binding.isStatic();
+               return (this.modifiers & AccStatic) != 0;
+       }
+       
+       public void resolve(MethodScope initializationScope) {
+
+               // the two <constant = Constant.NotAConstant> could be regrouped into
+               // a single line but it is clearer to have two lines while the reason of their
+               // existence is not at all the same. See comment for the second one.
+
+               //--------------------------------------------------------
+               if (!this.hasBeenResolved && this.binding != null && this.binding.isValidBinding()) {
+
+                       this.hasBeenResolved = true;
+
+                       // 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();
+                       
+                       if (classScope != null) {
+                               SourceTypeBinding declaringType = classScope.enclosingSourceType();
+                               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()){
+                                               initializationScope.problemReporter().fieldHiding(this, existingVariable);
+                                               checkLocal = false; // already found a matching field
+                                       }
+                               }
+                               if (checkLocal) {
+                                       Scope outerScope = classScope.parent;
+                                       // only corner case is: lookup of outer field through static declaringType, which isn't detected by #getBinding as lookup starts
+                                       // from outer scope. Subsequent static contexts are detected for free.
+                                       Binding existingVariable = outerScope.getBinding(this.name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+                                       if (existingVariable != null && existingVariable.isValidBinding()
+                                                       && (!(existingVariable instanceof FieldBinding)
+                                                                       || ((FieldBinding) existingVariable).isStatic() 
+                                                                       || !declaringType.isStatic())) {
+                                               initializationScope.problemReporter().fieldHiding(this, existingVariable);
+                                       }
+                               }
+                       }
+                       
+                       this.type.resolvedType = this.binding.type; // update binding for type reference
+
+                       FieldBinding previousField = initializationScope.initializedField;
+                       int previousFieldID = initializationScope.lastVisibleFieldID;
+                       try {
+                               initializationScope.initializedField = this.binding;
+                               initializationScope.lastVisibleFieldID = this.binding.id;
+
+                               if (isTypeUseDeprecated(this.binding.type, initializationScope)) {
+                                       initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
+                               }
+                               // the resolution of the initialization hasn't been done
+                               if (this.initialization == null) {
+                                       this.binding.constant = Constant.NotAConstant;
+                               } else {
+                                       // break dead-lock cycles by forcing constant to NotAConstant
+                                       this.binding.constant = Constant.NotAConstant;
+                                       
+                                       TypeBinding typeBinding = this.binding.type;
+                                       TypeBinding initializationTypeBinding;
+                                       
+                                       if (this.initialization instanceof ArrayInitializer) {
+
+                                               if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
+                                                       ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
+                                                       this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+                                               }
+                                       } else if ((initializationTypeBinding = 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 {
+                                                       initializationScope.problemReporter().typeMismatchError(initializationTypeBinding, typeBinding, 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());
+                                               }
+                                       } else {
+                                               this.binding.constant = NotAConstant;
+                                       }
+                               }
+                               // Resolve Javadoc comment if one is present
+                               if (this.javadoc != null) {
+                                       /*
+                                       if (classScope != null) {
+                                               this.javadoc.resolve(classScope);
+                                       }
+                                       */
+                                       this.javadoc.resolve(initializationScope);
+                               } else if (this.binding != null && this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
+                                       initializationScope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+                               }
+                       } finally {
+                               initializationScope.initializedField = previousField;
+                               initializationScope.lastVisibleFieldID = previousFieldID;
+                               if (this.binding.constant == null)
+                                       this.binding.constant = Constant.NotAConstant;
+                       }
+               }
+       }
+
+       public void traverse(ASTVisitor visitor, MethodScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       this.type.traverse(visitor, scope);
+                       if (this.initialization != null)
+                               this.initialization.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
new file mode 100644 (file)
index 0000000..9c4a86d
--- /dev/null
@@ -0,0 +1,559 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class FieldReference extends Reference implements InvocationSite {
+
+       public Expression receiver;
+       public char[] token;
+       public FieldBinding binding, codegenBinding;
+       public long nameSourcePosition; //(start<<32)+end
+       MethodBinding syntheticReadAccessor, syntheticWriteAccessor;
+       public TypeBinding receiverType;
+
+       public FieldReference(char[] source, long pos) {
+
+               token = source;
+               nameSourcePosition = pos;
+               //by default the position are the one of the field (not true for super access)
+               sourceStart = (int) (pos >>> 32);
+               sourceEnd = (int) (pos & 0x00000000FFFFFFFFL);
+               bits |= BindingIds.FIELD;
+
+       }
+
+       public FlowInfo analyseAssignment(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo,
+               Assignment assignment,
+               boolean isCompound) {
+
+               // compound assignment extra work
+               if (isCompound) { // check the variable part is initialized if blank final
+                       if (binding.isBlankFinal()
+                               && receiver.isThis()
+                               && currentScope.allowBlankFinalFieldAssignment(binding)
+                               && (!flowInfo.isDefinitelyAssigned(binding))) {
+                               currentScope.problemReporter().uninitializedBlankFinalField(binding, this);
+                               // we could improve error msg here telling "cannot use compound assignment on final blank field"
+                       }
+                       manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+               }
+               flowInfo =
+                       receiver
+                               .analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic())
+                               .unconditionalInits();
+               if (assignment.expression != null) {
+                       flowInfo =
+                               assignment
+                                       .expression
+                                       .analyseCode(currentScope, flowContext, flowInfo)
+                                       .unconditionalInits();
+               }
+               manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+
+               // check if assigning a final field 
+               if (binding.isFinal()) {
+                       // in a context where it can be assigned?
+                       if (binding.isBlankFinal()
+                               && !isCompound
+                               && receiver.isThis()
+                               && !(receiver instanceof QualifiedThisReference)
+                               && ((receiver.bits & ParenthesizedMASK) == 0) // (this).x is forbidden
+                               && currentScope.allowBlankFinalFieldAssignment(binding)) {
+                               if (flowInfo.isPotentiallyAssigned(binding)) {
+                                       currentScope.problemReporter().duplicateInitializationOfBlankFinalField(
+                                               binding,
+                                               this);
+                               } else {
+                                       flowContext.recordSettingFinal(binding, this, flowInfo);
+                               }
+                               flowInfo.markAsDefinitelyAssigned(binding);
+                       } else {
+                               // assigning a final field outside an initializer or constructor or wrong reference
+                               currentScope.problemReporter().cannotAssignToFinalField(binding, this);
+                       }
+               }
+               return flowInfo;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return analyseCode(currentScope, flowContext, flowInfo, true);
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo,
+               boolean valueRequired) {
+
+               receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic());
+               if (valueRequired) {
+                       manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+               }
+               return flowInfo;
+       }
+
+       public FieldBinding fieldBinding() {
+
+               return binding;
+       }
+
+       public void generateAssignment(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Assignment assignment,
+               boolean valueRequired) {
+
+               receiver.generateCode(
+                       currentScope,
+                       codeStream,
+                       !this.codegenBinding.isStatic());
+               assignment.expression.generateCode(currentScope, codeStream, true);
+               fieldStore(
+                       codeStream,
+                       this.codegenBinding,
+                       syntheticWriteAccessor,
+                       valueRequired);
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(assignment.implicitConversion);
+               }
+       }
+
+       /**
+        * Field reference code generation
+        *
+        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+        * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+        * @param valueRequired boolean
+        */
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+
+               int pc = codeStream.position;
+               if (constant != NotAConstant) {
+                       if (valueRequired) {
+                               codeStream.generateConstant(constant, implicitConversion);
+                       }
+               } else {
+                       boolean isStatic = this.codegenBinding.isStatic();
+                       receiver.generateCode(currentScope, codeStream, !isStatic);
+                       if (valueRequired) {
+                               if (this.codegenBinding.constant == NotAConstant) {
+                                       if (this.codegenBinding.declaringClass == null) { // array length
+                                               codeStream.arraylength();
+                                       } else {
+                                               if (syntheticReadAccessor == null) {
+                                                       if (isStatic) {
+                                                               codeStream.getstatic(this.codegenBinding);
+                                                       } else {
+                                                               codeStream.getfield(this.codegenBinding);
+                                                       }
+                                               } else {
+                                                       codeStream.invokestatic(syntheticReadAccessor);
+                                               }
+                                       }
+                                       codeStream.generateImplicitConversion(implicitConversion);
+                               } else {
+                                       if (!isStatic) {
+                                               codeStream.invokeObjectGetClass(); // perform null check
+                                               codeStream.pop();
+                                       }
+                                       codeStream.generateConstant(this.codegenBinding.constant, implicitConversion);
+                               }
+                       } else {
+                               if (!isStatic){
+                                       codeStream.invokeObjectGetClass(); // perform null check
+                                       codeStream.pop();
+                               }
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public void generateCompoundAssignment(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Expression expression,
+               int operator,
+               int assignmentImplicitConversion,
+               boolean valueRequired) {
+
+               boolean isStatic;
+               receiver.generateCode(
+                       currentScope,
+                       codeStream,
+                       !(isStatic = this.codegenBinding.isStatic()));
+               if (isStatic) {
+                       if (syntheticReadAccessor == null) {
+                               codeStream.getstatic(this.codegenBinding);
+                       } else {
+                               codeStream.invokestatic(syntheticReadAccessor);
+                       }
+               } else {
+                       codeStream.dup();
+                       if (syntheticReadAccessor == null) {
+                               codeStream.getfield(this.codegenBinding);
+                       } else {
+                               codeStream.invokestatic(syntheticReadAccessor);
+                       }
+               }
+               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);
+               }
+               fieldStore(
+                       codeStream,
+                       this.codegenBinding,
+                       syntheticWriteAccessor,
+                       valueRequired);
+       }
+
+       public void generatePostIncrement(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               CompoundAssignment postIncrement,
+               boolean valueRequired) {
+
+               boolean isStatic;
+               receiver.generateCode(
+                       currentScope,
+                       codeStream,
+                       !(isStatic = this.codegenBinding.isStatic()));
+               if (isStatic) {
+                       if (syntheticReadAccessor == null) {
+                               codeStream.getstatic(this.codegenBinding);
+                       } else {
+                               codeStream.invokestatic(syntheticReadAccessor);
+                       }
+               } else {
+                       codeStream.dup();
+                       if (syntheticReadAccessor == null) {
+                               codeStream.getfield(this.codegenBinding);
+                       } else {
+                               codeStream.invokestatic(syntheticReadAccessor);
+                       }
+               }
+               if (valueRequired) {
+                       if (isStatic) {
+                               if ((this.codegenBinding.type == LongBinding)
+                                       || (this.codegenBinding.type == DoubleBinding)) {
+                                       codeStream.dup2();
+                               } else {
+                                       codeStream.dup();
+                               }
+                       } else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
+                               if ((this.codegenBinding.type == LongBinding)
+                                       || (this.codegenBinding.type == DoubleBinding)) {
+                                       codeStream.dup2_x1();
+                               } else {
+                                       codeStream.dup_x1();
+                               }
+                       }
+               }
+               codeStream.generateConstant(
+                       postIncrement.expression.constant,
+                       implicitConversion);
+               codeStream.sendOperator(postIncrement.operator, this.codegenBinding.type.id);
+               codeStream.generateImplicitConversion(
+                       postIncrement.assignmentImplicitConversion);
+               fieldStore(codeStream, this.codegenBinding, syntheticWriteAccessor, false);
+       }
+
+       public static final Constant getConstantFor(
+               FieldBinding binding,
+               Reference reference,
+               boolean isImplicit,
+               Scope referenceScope) {
+
+               //propagation of the constant.
+
+               //ref can be a FieldReference, a SingleNameReference or a QualifiedNameReference
+               //indexInQualification may have a value greater than zero only for QualifiednameReference
+               //if ref==null then indexInQualification==0 AND implicitReceiver == false. This case is a 
+               //degenerated case where a fake reference field (null) 
+               //is associted to a real FieldBinding in order 
+               //to allow its constant computation using the regular path (in other words, find the fieldDeclaration
+               //and proceed to its type resolution). As implicitReceiver is false, no error reporting
+               //against ref will be used ==> no nullPointerException risk .... 
+
+               //special treatment for langage-built-in  field (their declaring class is null)
+               if (binding.declaringClass == null) {
+                       //currently only one field "length" : the constant computation is never done
+                       return NotAConstant;
+               }
+               if (!binding.isFinal()) {
+                       return binding.constant = NotAConstant;
+               }
+               if (binding.constant != null) {
+                       if (isImplicit || (reference instanceof QualifiedNameReference
+                                       && binding == ((QualifiedNameReference)reference).binding)) {
+                               return binding.constant;
+                       }
+                       return NotAConstant;
+               }
+
+               //The field has not been yet type checked.
+               //It also means that the field is not coming from a class that
+               //has already been compiled. It can only be from a class within
+               //compilation units to process. Thus the field is NOT from a BinaryTypeBinbing
+
+               SourceTypeBinding typeBinding = (SourceTypeBinding) binding.declaringClass;
+               TypeDeclaration typeDecl = typeBinding.scope.referenceContext;
+               FieldDeclaration fieldDecl = typeDecl.declarationOf(binding);
+
+               fieldDecl.resolve(binding.isStatic() //side effect on binding 
+                               ? typeDecl.staticInitializerScope
+                               : typeDecl.initializerScope); 
+
+               if (isImplicit || (reference instanceof QualifiedNameReference
+                               && binding == ((QualifiedNameReference)reference).binding)) {
+                       return binding.constant;
+               }
+               return NotAConstant;
+       }
+
+       public boolean isSuperAccess() {
+
+               return receiver.isSuper();
+       }
+
+       public boolean isTypeAccess() {
+
+               return receiver != null && receiver.isTypeReference();
+       }
+
+       /*
+        * No need to emulate access to protected fields since not implicitly accessed
+        */
+       public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               if (binding.isPrivate()) {
+                       if ((currentScope.enclosingSourceType() != binding.declaringClass)
+                               && (binding.constant == NotAConstant)) {
+                               syntheticReadAccessor =
+                                       ((SourceTypeBinding) binding.declaringClass).addSyntheticMethod(binding, true);
+                               currentScope.problemReporter().needToEmulateFieldReadAccess(binding, this);
+                               return;
+                       }
+
+               } else if (receiver instanceof QualifiedSuperReference) { // qualified super
+
+                       // qualified super need emulation always
+                       SourceTypeBinding destinationType =
+                               (SourceTypeBinding) (((QualifiedSuperReference) receiver)
+                                       .currentCompatibleType);
+                       syntheticReadAccessor = destinationType.addSyntheticMethod(binding, true);
+                       currentScope.problemReporter().needToEmulateFieldReadAccess(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);
+                               syntheticReadAccessor = currentCompatibleType.addSyntheticMethod(binding, true);
+                               currentScope.problemReporter().needToEmulateFieldReadAccess(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);
+               }
+       }
+
+       /*
+        * 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) {
+
+               return receiver.printExpression(0, output).append('.').append(token);
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+
+               // Answer the signature type of the field.
+               // constants are propaged when the field is final
+               // and initialized with a (compile time) constant 
+
+               //always ignore receiver cast, since may affect constant pool reference
+               boolean receiverCast = false;
+               if (this.receiver instanceof CastExpression) {
+                       this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+                       receiverCast = true;
+               }
+               this.receiverType = receiver.resolveType(scope);
+               if (this.receiverType == null) {
+                       constant = NotAConstant;
+                       return null;
+               }
+               if (receiverCast) {
+                        // due to change of declaring class with receiver type, only identity cast should be notified
+                       if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) { 
+                                               scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);         
+                       }
+               }               
+               // the case receiverType.isArrayType and token = 'length' is handled by the scope API
+               this.codegenBinding = this.binding = scope.getField(this.receiverType, token, this);
+               if (!binding.isValidBinding()) {
+                       constant = NotAConstant;
+                       scope.problemReporter().invalidField(this, this.receiverType);
+                       return null;
+               }
+
+               if (isFieldUseDeprecated(binding, scope, (this.bits & IsStrictlyAssignedMASK) !=0)) {
+                       scope.problemReporter().deprecatedField(binding, this);
+               }
+               boolean isImplicitThisRcv = receiver.isImplicitThis();
+               constant = FieldReference.getConstantFor(binding, this, isImplicitThisRcv, scope);
+               if (!isImplicitThisRcv) {
+                       constant = NotAConstant;
+               }
+               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))) {
+                               scope.problemReporter().nonStaticAccessToStaticField(this, binding);
+                       }
+                       if (!isImplicitThisRcv && binding.declaringClass != receiverType) {
+                               scope.problemReporter().indirectAccessToStaticField(this, binding);
+                       }
+               }
+               return this.resolvedType = binding.type;
+       }
+
+       public void setActualReceiverType(ReferenceBinding receiverType) {
+               // ignored
+       }
+
+       public void setDepth(int depth) {
+
+               bits &= ~DepthMASK; // flush previous depth if any                      
+               if (depth > 0) {
+                       bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+               }
+       }
+
+       public void setFieldIndex(int index) {
+               // ignored
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       receiver.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/FloatLiteral.java
new file mode 100644 (file)
index 0000000..c7d53d6
--- /dev/null
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+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
+       }
+       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
+                       }
+               }
+       }
+       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
+                       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);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
new file mode 100644 (file)
index 0000000..51c5db6
--- /dev/null
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ForStatement extends Statement {
+       
+       public Statement[] initializations;
+       public Expression condition;
+       public Statement[] increments;
+       public Statement action;
+
+       //when there is no local declaration, there is no need of a new scope
+       //scope is positionned either to a new scope, or to the "upper"scope (see resolveType)
+       public boolean neededScope;
+       public BlockScope scope;
+
+       private Label breakLabel, continueLabel;
+
+       // for local variables table attributes
+       int preCondInitStateIndex = -1;
+       int condIfTrueInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+
+       public ForStatement(
+               Statement[] initializations,
+               Expression condition,
+               Statement[] increments,
+               Statement action,
+               boolean neededScope,
+               int s,
+               int e) {
+
+               this.sourceStart = s;
+               this.sourceEnd = e;
+               this.initializations = initializations;
+               this.condition = condition;
+               this.increments = increments;
+               this.action = action;
+               // remember useful empty statement
+               if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
+               this.neededScope = neededScope;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+                       
+               breakLabel = new Label();
+               continueLabel = new Label();
+
+               // process the initializations
+               if (initializations != null) {
+                       for (int i = 0, count = initializations.length; i < count; i++) {
+                               flowInfo = initializations[i].analyseCode(scope, flowContext, flowInfo);
+                       }
+               }
+               preCondInitStateIndex =
+                       currentScope.methodScope().recordInitializationStates(flowInfo);
+
+               Constant cst = this.condition == null ? null : this.condition.constant;
+               boolean isConditionTrue = cst == null || (cst != NotAConstant && cst.booleanValue() == true);
+               boolean isConditionFalse = cst != null && (cst != NotAConstant && cst.booleanValue() == false);
+
+               cst = this.condition == null ? null : this.condition.optimizedBooleanConstant();
+               boolean isConditionOptimizedTrue = cst == null ||  (cst != NotAConstant && cst.booleanValue() == true);
+               boolean isConditionOptimizedFalse = cst != null && (cst != NotAConstant && cst.booleanValue() == false);
+               
+               // process the condition
+               LoopingFlowContext condLoopContext = null;
+               if (condition != null) {
+                       if (!isConditionTrue) {
+                               flowInfo =
+                                       condition.analyseCode(
+                                               scope,
+                                               (condLoopContext =
+                                                       new LoopingFlowContext(flowContext, this, null, null, scope)),
+                                               flowInfo);
+                       }
+               }
+
+               // process the action
+               LoopingFlowContext loopingContext;
+               FlowInfo actionInfo;
+               if (action == null 
+                       || (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
+                       if (condLoopContext != null)
+                               condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+                       if (isConditionTrue) {
+                               return FlowInfo.DEAD_END;
+                       } else {
+                               if (isConditionFalse){
+                                       continueLabel = null; // for(;false;p());
+                               }
+                               actionInfo = flowInfo.initsWhenTrue().copy();
+                               loopingContext =
+                                       new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
+                       }
+               } else {
+                       loopingContext =
+                               new LoopingFlowContext(flowContext, this, breakLabel, continueLabel, scope);
+                       FlowInfo initsWhenTrue = flowInfo.initsWhenTrue();
+                       condIfTrueInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(initsWhenTrue);
+
+                               if (isConditionFalse) {
+                                       actionInfo = FlowInfo.DEAD_END;
+                               } else {
+                                       actionInfo = initsWhenTrue.copy();
+                                       if (isConditionOptimizedFalse){
+                                               actionInfo.setReachMode(FlowInfo.UNREACHABLE);
+                                       }
+                               }
+                       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
+                       if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
+                               continueLabel = null;
+                       } else {
+                               if (condLoopContext != null)
+                                       condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+                               actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
+                               loopingContext.complainOnFinalAssignmentsInLoop(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);
+                       }
+                       loopContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
+               }
+
+               //end of loop
+               FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+                               loopingContext.initsOnBreak, 
+                               isConditionOptimizedTrue, 
+                               flowInfo.initsWhenFalse(), 
+                               isConditionOptimizedFalse, 
+                               !isConditionTrue /*for(;;){}while(true); unreachable(); */);
+               mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+               return mergedInfo;
+       }
+
+       /**
+        * 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;
+
+               // generate the initializations
+               if (initializations != null) {
+                       for (int i = 0, max = initializations.length; i < max; i++) {
+                               initializations[i].generateCode(scope, codeStream);
+                       }
+               }
+
+               // label management
+               Label actionLabel = new Label(codeStream);
+               Label conditionLabel = new Label(codeStream);
+               breakLabel.initialize(codeStream);
+               if (continueLabel != null) {
+                       continueLabel.initialize(codeStream);
+               }
+               // jump over the actionBlock
+               if ((condition != null)
+                       && (condition.constant == NotAConstant)
+                       && !((action == null || action.isEmptyBlock()) && (increments == null))) {
+                       int jumpPC = codeStream.position;
+                       codeStream.goto_(conditionLabel);
+                       codeStream.recordPositionsFrom(jumpPC, condition.sourceStart);
+               }
+               // generate the loop action
+               actionLabel.place();
+               if (action != null) {
+                       // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
+                       if (condIfTrueInitStateIndex != -1) {
+                               // insert all locals initialized inside the condition into the action generated prior to the condition
+                               codeStream.addDefinitelyAssignedVariables(
+                                       currentScope,
+                                       condIfTrueInitStateIndex);
+                       }
+                       action.generateCode(scope, codeStream);
+               }
+               // continuation point
+               if (continueLabel != null) {
+                       continueLabel.place();
+                       // generate the increments for next iteration
+                       if (increments != null) {
+                               for (int i = 0, max = increments.length; i < max; i++) {
+                                       increments[i].generateCode(scope, codeStream);
+                               }
+                       }
+               }
+
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (preCondInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(
+                               currentScope,
+                               preCondInitStateIndex);
+               }
+
+               // generate the condition
+               conditionLabel.place();
+               if ((condition != null) && (condition.constant == NotAConstant)) {
+                       condition.generateOptimizedBoolean(scope, codeStream, actionLabel, null, true);
+               } else {
+                       if (continueLabel != null) {
+                               codeStream.goto_(actionLabel);
+                       }
+               }
+               breakLabel.place();
+
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (neededScope) {
+                       codeStream.exitUserScope(scope);
+               }
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+
+               printIndent(tab, output).append("for ("); //$NON-NLS-1$
+               //inits
+               if (initializations != null) {
+                       for (int i = 0; i < initializations.length; i++) {
+                               //nice only with expressions
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               initializations[i].print(0, output);
+                       }
+               }
+               output.append("; "); //$NON-NLS-1$
+               //cond
+               if (condition != null) condition.printExpression(0, output);
+               output.append("; "); //$NON-NLS-1$
+               //updates
+               if (increments != null) {
+                       for (int i = 0; i < increments.length; i++) {
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               increments[i].print(0, output);
+                       }
+               }
+               output.append(") "); //$NON-NLS-1$
+               //block
+               if (action == null)
+                       output.append(';');
+               else {
+                       output.append('\n');
+                       action.printStatement(tab + 1, output); //$NON-NLS-1$
+               }
+               return output.append(';');
+       }
+
+       public void resolve(BlockScope upperScope) {
+
+               // use the scope that will hold the init declarations
+               scope = neededScope ? new BlockScope(upperScope) : upperScope;
+               if (initializations != null)
+                       for (int i = 0, length = initializations.length; i < length; i++)
+                               initializations[i].resolve(scope);
+               if (condition != null) {
+                       TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
+                       condition.implicitWidening(type, type);
+               }
+               if (increments != null)
+                       for (int i = 0, length = increments.length; i < length; i++)
+                               increments[i].resolve(scope);
+               if (action != null)
+                       action.resolve(scope);
+       }
+       
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       if (initializations != null) {
+                               int initializationsLength = initializations.length;
+                               for (int i = 0; i < initializationsLength; i++)
+                                       initializations[i].traverse(visitor, scope);
+                       }
+
+                       if (condition != null)
+                               condition.traverse(visitor, scope);
+
+                       if (increments != null) {
+                               int incrementsLength = increments.length;
+                               for (int i = 0; i < incrementsLength; i++)
+                                       increments[i].traverse(visitor, scope);
+                       }
+
+                       if (action != null)
+                               action.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/IfStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/IfStatement.java
new file mode 100644 (file)
index 0000000..a262104
--- /dev/null
@@ -0,0 +1,244 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class IfStatement extends Statement {
+       
+       //this class represents the case of only one statement in 
+       //either else and/or then branches.
+
+       public Expression condition;
+       public Statement thenStatement;
+       public Statement elseStatement;
+
+       boolean thenExit;
+
+       // for local variables table attributes
+       int thenInitStateIndex = -1;
+       int elseInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+
+       public IfStatement(Expression condition, Statement thenStatement,       int sourceStart, int sourceEnd) {
+
+               this.condition = condition;
+               this.thenStatement = thenStatement;
+               // remember useful empty statement
+               if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatementMASK;
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       public IfStatement(Expression condition, Statement thenStatement, Statement elseStatement, int sourceStart, int sourceEnd) {
+
+               this.condition = condition;
+               this.thenStatement = thenStatement;
+               // remember useful empty statement
+               if (thenStatement instanceof EmptyStatement) thenStatement.bits |= IsUsefulEmptyStatementMASK;
+               this.elseStatement = elseStatement;
+               if (elseStatement instanceof IfStatement) elseStatement.bits |= IsElseIfStatement;
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // process the condition
+               flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
+
+               Constant cst = this.condition.optimizedBooleanConstant();
+               boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+               
+               // process the THEN part
+               FlowInfo thenFlowInfo = flowInfo.initsWhenTrue().copy();
+               if (isConditionOptimizedFalse) {
+                       thenFlowInfo.setReachMode(FlowInfo.UNREACHABLE); 
+               }
+               if (this.thenStatement != null) {
+                       // Save info for code gen
+                       thenInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(thenFlowInfo);
+                       if (!thenStatement.complainIfUnreachable(thenFlowInfo, currentScope, false)) {
+                               thenFlowInfo =
+                                       thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
+                       }
+               }
+               // code gen: optimizing the jump around the ELSE part
+               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 
+                           && (this.bits & IsElseIfStatement) == 0     // else of an else-if
+                           && !(this.elseStatement instanceof IfStatement)) {
+                       currentScope.problemReporter().unnecessaryElse(this.elseStatement);
+                   }
+                       // Save info for code gen
+                       elseInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(elseFlowInfo);
+                       if (!elseStatement.complainIfUnreachable(elseFlowInfo, currentScope, false)) {
+                               elseFlowInfo =
+                                       elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
+                       }
+               }
+
+               // merge THEN & ELSE initializations
+               FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+                               thenFlowInfo, 
+                               isConditionOptimizedTrue, 
+                               elseFlowInfo, 
+                               isConditionOptimizedFalse,
+                               true /*if(true){ return; }  fake-reachable(); */);
+               mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+               return mergedInfo;
+       }
+
+       /**
+        * If 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 ((this.bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               int pc = codeStream.position;
+               Label endifLabel = new Label(codeStream);
+
+               // optimizing the then/else part code gen
+               Constant cst;
+               boolean hasThenPart = 
+                       !(((cst = this.condition.optimizedBooleanConstant()) != NotAConstant
+                                       && cst.booleanValue() == false)
+                               || this.thenStatement == null
+                               || this.thenStatement.isEmptyBlock());
+               boolean hasElsePart =
+                       !((cst != NotAConstant && cst.booleanValue() == true)
+                               || this.elseStatement == null
+                               || this.elseStatement.isEmptyBlock());
+
+               if (hasThenPart) {
+                       Label falseLabel;
+                       // generate boolean condition
+                       this.condition.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               null,
+                               (falseLabel = new Label(codeStream)),
+                               true);
+                       // May loose some local variable initializations : affecting the local variable attributes
+                       if (thenInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(
+                                       currentScope,
+                                       thenInitStateIndex);
+                               codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
+                       }
+                       // generate then statement
+                       this.thenStatement.generateCode(currentScope, codeStream);
+                       // jump around the else statement
+                       if (hasElsePart && !thenExit) {
+                               this.thenStatement.branchChainTo(endifLabel);
+                               int position = codeStream.position;
+                               codeStream.goto_(endifLabel);
+                               codeStream.updateLastRecordedEndPC(position);
+                               //goto is tagged as part of the thenAction block
+                       }
+                       falseLabel.place();
+               } else {
+                       if (hasElsePart) {
+                               // generate boolean condition
+                               this.condition.generateOptimizedBoolean(
+                                       currentScope,
+                                       codeStream,
+                                       endifLabel,
+                                       null,
+                                       true);
+                       } else {
+                               // generate condition side-effects
+                               this.condition.generateCode(currentScope, codeStream, false);
+                               codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       }
+               }
+               // generate else statement
+               if (hasElsePart) {
+                       // May loose some local variable initializations : affecting the local variable attributes
+                       if (elseInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(
+                                       currentScope,
+                                       elseInitStateIndex);
+                               codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
+                       }
+                       this.elseStatement.generateCode(currentScope, codeStream);
+               }
+               endifLabel.place();
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(
+                               currentScope,
+                               mergedInitStateIndex);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               printIndent(indent, output).append("if ("); //$NON-NLS-1$
+               condition.printExpression(0, output).append(")\n");     //$NON-NLS-1$ 
+               thenStatement.printStatement(indent + 2, output);
+               if (elseStatement != null) {
+                       output.append('\n');
+                       printIndent(indent, output);
+                       output.append("else\n"); //$NON-NLS-1$
+                       elseStatement.printStatement(indent + 2, output);
+               }
+               return output;
+       }
+
+       public void resolve(BlockScope scope) {
+
+               TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
+               condition.implicitWidening(type, type);
+               if (thenStatement != null)
+                       thenStatement.resolve(scope);
+               if (elseStatement != null)
+                       elseStatement.resolve(scope);
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       condition.traverse(visitor, blockScope);
+                       if (thenStatement != null)
+                               thenStatement.traverse(visitor, blockScope);
+                       if (elseStatement != null)
+                               elseStatement.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ImplicitDocTypeReference.java
new file mode 100644 (file)
index 0000000..9dda67e
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class ImplicitDocTypeReference extends TypeReference {
+       
+       public char[] token;
+
+       public ImplicitDocTypeReference(char[] name, int pos) {
+               super();
+               this.token = name;
+               this.sourceStart = pos;
+               this.sourceEnd = pos;
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int)
+        */
+       public TypeReference copyDims(int dim) {
+               return null;
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
+        */
+       public TypeBinding getTypeBinding(Scope scope) {
+               this.constant = NotAConstant;
+               return this.resolvedType = scope.enclosingSourceType();
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeName()
+        */
+       public char[][] getTypeName() {
+               if (this.token != null) {
+                       char[][] tokens = { this.token };
+                       return tokens;
+               }
+               return null;
+       }
+       public boolean isThis() {
+               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.ClassScope)
+        */
+       public void traverse(ASTVisitor visitor, ClassScope classScope) {
+               // Do nothing
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#printExpression(int, java.lang.StringBuffer)
+        */
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+               return new StringBuffer();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ImportReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ImportReference.java
new file mode 100644 (file)
index 0000000..4623b2d
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.*;
+
+public class ImportReference extends ASTNode {
+
+       public char[][] tokens;
+       public long[] sourcePositions; //each entry is using the code : (start<<32) + end
+       public boolean onDemand = true; //most of the time
+       public int declarationEnd; // doesn't include an potential trailing comment
+       public int declarationSourceStart;
+       public int declarationSourceEnd;
+       public boolean used;
+       public int modifiers; // 1.5 addition for static imports
+
+       public ImportReference(
+                       char[][] tokens,
+                       long[] sourcePositions,
+                       boolean onDemand,
+                       int modifiers) {
+
+               this.tokens = tokens;
+               this.sourcePositions = sourcePositions;
+               this.onDemand = onDemand;
+               this.sourceEnd = (int) (sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFF);
+               this.sourceStart = (int) (sourcePositions[0] >>> 32);
+               this.modifiers = modifiers;
+       }
+
+       /**
+        * @return char[][]
+        */
+       public char[][] getImportName() {
+
+               return tokens;
+       }
+
+       public StringBuffer print(int indent, StringBuffer output) {
+
+               return print(indent, output, true);
+       }
+
+       public StringBuffer print(int tab, StringBuffer output, boolean withOnDemand) {
+
+               /* when withOnDemand is false, only the name is printed */
+               for (int i = 0; i < tokens.length; i++) {
+                       if (i > 0) output.append('.');
+                       output.append(tokens[i]);
+               }
+               if (withOnDemand && onDemand) {
+                       output.append(".*"); //$NON-NLS-1$
+               }
+               return output;
+       }
+
+       public void traverse(ASTVisitor visitor, CompilationUnitScope scope) {
+
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Initializer.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Initializer.java
new file mode 100644 (file)
index 0000000..ff53718
--- /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.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+
+public class Initializer extends FieldDeclaration {
+       
+       public Block block;
+       public int lastVisibleFieldID;
+       public int bodyStart;
+       public int bodyEnd;
+       
+       public boolean errorInSignature = false; 
+       
+       public Initializer(Block block, int modifiers) {
+               this.block = block;
+               this.modifiers = modifiers;
+
+               declarationSourceStart = sourceStart = block.sourceStart;
+       }
+
+       public FlowInfo analyseCode(
+               MethodScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return block.analyseCode(currentScope, flowContext, flowInfo);
+       }
+
+       /**
+        * Code generation for a non-static initializer: 
+        *    standard block code gen
+        *
+        * @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;
+               block.generateCode(currentScope, codeStream);
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public boolean isField() {
+
+               return false;
+       }
+
+       public boolean isStatic() {
+
+               return (modifiers & AccStatic) != 0;
+       }
+
+       public void parseStatements(
+               Parser parser,
+               TypeDeclaration typeDeclaration,
+               CompilationUnitDeclaration unit) {
+
+               //fill up the method body with statement
+               parser.parse(this, typeDeclaration, unit);
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               if (modifiers != 0) {
+                       printIndent(indent, output);
+                       printModifiers(modifiers, output).append("{\n"); //$NON-NLS-1$
+                       block.printBody(indent, output);
+                       printIndent(indent, output).append('}'); 
+                       return output;
+               } else {
+                       return block.printStatement(indent, output);
+               }
+       }
+       
+       public void resolve(MethodScope scope) {
+
+           FieldBinding previousField = scope.initializedField;
+               int previousFieldID = scope.lastVisibleFieldID;
+               try {
+                   scope.initializedField = null;
+                       scope.lastVisibleFieldID = lastVisibleFieldID;
+                       if (isStatic()) {
+                               ReferenceBinding declaringType = scope.enclosingSourceType();
+                               if (declaringType.isNestedType() && !declaringType.isStatic())
+                                       scope.problemReporter().innerTypesCannotDeclareStaticInitializers(
+                                               declaringType,
+                                               this);
+                       }
+                       block.resolve(scope);
+               } finally {
+                   scope.initializedField = previousField;
+                       scope.lastVisibleFieldID = previousFieldID;
+               }
+       }
+
+       public void traverse(ASTVisitor visitor, MethodScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       block.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
new file mode 100644 (file)
index 0000000..feacdaf
--- /dev/null
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * 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.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class InstanceOfExpression extends OperatorExpression {
+
+       public Expression expression;
+       public TypeReference type;
+
+       public InstanceOfExpression(
+               Expression expression,
+               TypeReference type,
+               int operator) {
+
+               this.expression = expression;
+               this.type = type;
+               this.bits |= operator << OperatorSHIFT;
+               this.sourceStart = expression.sourceStart;
+               this.sourceEnd = type.sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return expression
+                       .analyseCode(currentScope, flowContext, flowInfo)
+                       .unconditionalInits();
+       }
+       /**
+        * 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
+        *
+        * @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;
+               expression.generateCode(currentScope, codeStream, true);
+               codeStream.instance_of(type.resolvedType);
+               if (!valueRequired)
+                       codeStream.pop();
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+               expression.printExpression(indent, output).append(" instanceof "); //$NON-NLS-1$
+               return type.print(0, output);
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+
+               constant = NotAConstant;
+               TypeBinding expressionType = expression.resolveType(scope);
+               TypeBinding checkType = type.resolveType(scope);
+               if (expressionType == null || checkType == null)
+                       return null;
+
+               boolean necessary = checkCastTypesCompatibility(scope, checkType, expressionType);
+               if (!necessary) {
+                       scope.problemReporter().unnecessaryInstanceof(this, checkType);
+               }
+               return this.resolvedType = BooleanBinding;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       expression.traverse(visitor, scope);
+                       type.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/IntLiteral.java
new file mode 100644 (file)
index 0000000..46a2172
--- /dev/null
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class IntLiteral extends NumberLiteral {
+       public int value;
+       
+       public static final IntLiteral
+               One = new IntLiteral(new char[]{'1'},0,0,1);//used for ++ and -- 
+
+       static final Constant FORMAT_ERROR = new DoubleConstant(1.0/0.0); // NaN;
+public IntLiteral(char[] token, int s, int e) {
+       super(token, s,e);
+}
+public IntLiteral(char[] token, int s,int e, int value) {
+       this(token, s,e);
+       this.value = value;
+}
+public IntLiteral(int intValue) {
+       //special optimized constructor : the cst is the argument 
+
+       //value that should not be used
+       //      tokens = null ;
+       //      sourceStart = 0;
+       //      sourceEnd = 0;
+       super(null,0,0);
+       constant = Constant.fromValue(intValue);
+       value = intValue;
+       
+}
+public void computeConstant() {
+       //a special constant is use for the potential Integer.MAX_VALUE+1
+       //which is legal if used with a - as prefix....cool....
+       //notice that Integer.MIN_VALUE  == -2147483648
+
+       long MAX = Integer.MAX_VALUE;
+       if (this == One) {      constant = Constant.One; return ;}
+       
+       int length = source.length;
+       long computedValue = 0L;
+       if (source[0] == '0')
+       {       MAX = 0xFFFFFFFFL ; //a long in order to be positive !  
+               if (length == 1) {      constant = Constant.fromValue(0); return ;}
+               final int shift,radix;
+               int j ;
+               if ( (source[1] == 'x') | (source[1] == 'X') )
+               {       shift = 4 ; j = 2; radix = 16;}
+               else
+               {       shift = 3 ; j = 1; radix = 8;}
+               while (source[j]=='0') 
+               {       j++; //jump over redondant zero
+                       if (j == length)
+                       {       //watch for 000000000000000000
+                               constant = Constant.fromValue(value = (int)computedValue);
+                               return ;}}
+               
+               while (j<length)
+               {       int digitValue ;
+                       if ((digitValue = Character.digit(source[j++],radix))   < 0 )   
+                       {       constant = FORMAT_ERROR; return ;}
+                       computedValue = (computedValue<<shift) | digitValue ;
+                       if (computedValue > MAX) return /*constant stays null*/ ;}}
+       else
+       {       //-----------regular case : radix = 10-----------
+               for (int i = 0 ; i < length;i++)
+               {       int digitValue ;
+                       if ((digitValue = Character.digit(source[i],10))        < 0 ) 
+                       {       constant = FORMAT_ERROR; return ;}
+                       computedValue = 10*computedValue + digitValue;
+                       if (computedValue > MAX) return /*constant stays null*/ ; }}
+
+       constant = Constant.fromValue(value = (int)computedValue);
+               
+}
+/**
+ * Code generation for int 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_int)
+                       codeStream.generateInlinedValue(value);
+               else
+                       codeStream.generateConstant(constant, implicitConversion);
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public TypeBinding literalType(BlockScope scope) {
+       return IntBinding;
+}
+public final boolean mayRepresentMIN_VALUE(){
+       //a special autorized int literral is 2147483648
+       //which is ONE over the limit. This special case 
+       //only is used in combinaison with - to denote
+       //the minimal value of int -2147483648
+
+       return ((source.length == 10) &&
+                       (source[0] == '2') &&
+                       (source[1] == '1') &&
+                       (source[2] == '4') &&
+                       (source[3] == '7') &&                   
+                       (source[4] == '4') &&
+                       (source[5] == '8') &&
+                       (source[6] == '3') &&
+                       (source[7] == '6') &&                   
+                       (source[8] == '4') &&
+                       (source[9] == '8'));}
+public TypeBinding resolveType(BlockScope scope) {
+       // the format may be incorrect while the scanner could detect
+       // such an error only on painfull tests...easier and faster here
+
+       TypeBinding tb = super.resolveType(scope);
+       if (constant == FORMAT_ERROR) {
+               constant = NotAConstant;
+               scope.problemReporter().constantOutOfFormat(this);
+               this.resolvedType = null;
+               return null;
+       }
+       return tb;
+}
+public StringBuffer printExpression(int indent, StringBuffer output){
+
+       if (source == null) {
+       /* special optimized IntLiteral that are created by the compiler */
+               return output.append(String.valueOf(value));
+       }
+       return super.printExpression(indent, output);
+}
+       
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+       visitor.visit(this, scope);
+       visitor.endVisit(this, scope);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/IntLiteralMinValue.java b/src/java/org/eclipse/jdt/internal/compiler/ast/IntLiteralMinValue.java
new file mode 100644 (file)
index 0000000..9700282
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.impl.*;
+
+public class IntLiteralMinValue extends IntLiteral {
+
+       final static char[] CharValue = new char[]{'-','2','1','4','7','4','8','3','6','4','8'};
+       final static Constant MIN_VALUE = Constant.fromValue(Integer.MIN_VALUE) ; 
+
+public IntLiteralMinValue() {
+       super(CharValue,0,0,Integer.MIN_VALUE);
+       constant = MIN_VALUE;
+}
+public void computeConstant(){
+       
+       /*precomputed at creation time*/ }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
new file mode 100644 (file)
index 0000000..f683964
--- /dev/null
@@ -0,0 +1,469 @@
+/*******************************************************************************
+ * 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.lookup.*;
+
+/**
+ * Node representing a structured Javadoc comment
+ */
+public class Javadoc extends ASTNode {
+
+       public JavadocSingleNameReference[] parameters; // @param
+       public TypeReference[] thrownExceptions; // @throws, @exception
+       public JavadocReturnStatement returnStatement; // @return
+       public Expression[] references; // @see
+       public boolean inherited = false;
+       // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=51600
+       // Store param references for tag with invalid syntax
+       public JavadocSingleNameReference[] invalidParameters; // @param
+
+       public Javadoc(int sourceStart, int sourceEnd) {
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+       
+       /*
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#print(int, java.lang.StringBuffer)
+        */
+       public StringBuffer print(int indent, StringBuffer output) {
+               printIndent(indent, output).append("/**\n"); //$NON-NLS-1$
+               if (this.parameters != null) {
+                       for (int i = 0, length = this.parameters.length; i < length; i++) {
+                               printIndent(indent + 1, output).append(" * @param "); //$NON-NLS-1$             
+                               this.parameters[i].print(indent, output).append('\n');
+                       }
+               }
+               if (this.returnStatement != null) {
+                       printIndent(indent + 1, output).append(" * @return\n"); //$NON-NLS-1$           
+               }
+               if (this.thrownExceptions != null) {
+                       for (int i = 0, length = this.thrownExceptions.length; i < length; i++) {
+                               printIndent(indent + 1, output).append(" * @throws "); //$NON-NLS-1$            
+                               this.thrownExceptions[i].print(indent, output).append('\n');
+                       }
+               }
+               if (this.references != null) {
+                       for (int i = 0, length = this.references.length; i < length; i++) {
+                               printIndent(indent + 1, output).append(" * @see"); //$NON-NLS-1$                
+                               this.references[i].print(indent, output).append('\n');
+                       }
+               }
+               printIndent(indent, output).append(" */\n"); //$NON-NLS-1$
+               return output;
+       }
+
+       /*
+        * Resolve type javadoc while a class scope
+        */
+       public void resolve(ClassScope classScope) {
+               
+
+               // @param tags
+               int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+               for (int i = 0; i < paramTagsSize; i++) {
+                       JavadocSingleNameReference param = this.parameters[i];
+                       classScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+               }
+
+               // @return tags
+               if (this.returnStatement != null) {
+                       classScope.problemReporter().javadocUnexpectedTag(this.returnStatement.sourceStart, this.returnStatement.sourceEnd);
+               }
+
+               // @throws/@exception tags
+               int throwsTagsLength = this.thrownExceptions == null ? 0 : this.thrownExceptions.length;
+               for (int i = 0; i < throwsTagsLength; i++) {
+                       TypeReference typeRef = this.thrownExceptions[i];
+                       int start, end;
+                       if (typeRef instanceof JavadocSingleTypeReference) {
+                               JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
+                               start = singleRef.tagSourceStart;
+                               end = singleRef.tagSourceEnd;
+                       } else if (typeRef instanceof JavadocQualifiedTypeReference) {
+                               JavadocQualifiedTypeReference qualifiedRef = (JavadocQualifiedTypeReference) typeRef;
+                               start = qualifiedRef.tagSourceStart;
+                               end = qualifiedRef.tagSourceEnd;
+                       } else {
+                               start = typeRef.sourceStart;
+                               end = typeRef.sourceEnd;
+                       }
+                       classScope.problemReporter().javadocUnexpectedTag(start, end);
+               }
+
+               // @see tags
+               int seeTagsLength = this.references == null ? 0 : this.references.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;
+                               }
+                       }
+               }
+       }
+       
+       /*
+        * Resolve method javadoc while a method scope
+        */
+       public void resolve(MethodScope methScope) {
+               
+               // get method declaration
+               AbstractMethodDeclaration methDecl = methScope.referenceMethod();
+               boolean overriding = methDecl == null ? false : (methDecl.binding.modifiers & (AccImplementing+AccOverriding)) != 0;
+
+               // @see tags
+               int seeTagsLength = this.references == null ? 0 : this.references.length;
+               boolean superRef = false;
+               for (int i = 0; i < seeTagsLength; i++) {
+                       
+                       // Resolve reference
+                       this.references[i].resolveType(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 binding is valid then look if we have a reference to an overriden method/constructor
+                                               if (messageSend.binding != null && messageSend.binding.isValidBinding()) {
+                                                       if (methDecl.binding.declaringClass.isCompatibleWith(messageSend.receiverType) &&
+                                                               CharOperation.equals(messageSend.selector, methDecl.selector) &&
+                                                               (messageSend.binding.returnType == methDecl.binding.returnType)) {
+                                                               if (messageSend.arguments == null && methDecl.arguments == null) {
+                                                                       superRef = true;
+                                                               }
+                                                               else if (messageSend.arguments != null && methDecl.arguments != null) {
+                                                                       superRef = methDecl.binding.areParametersEqual(messageSend.binding);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       else if (this.references[i] instanceof JavadocAllocationExpression) {
+                                               JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.references[i];
+                                               // if binding is valid then look if we have a reference to an overriden method/constructor
+                                               if (allocationExpr.binding != null && allocationExpr.binding.isValidBinding()) {
+                                                       if (methDecl.binding.declaringClass.isCompatibleWith(allocationExpr.resolvedType)) {
+                                                               if (allocationExpr.arguments == null && methDecl.arguments == null) {
+                                                                       superRef = true;
+                                                               }
+                                                               else if (allocationExpr.arguments != null && methDecl.arguments != null) {
+                                                                       superRef = methDecl.binding.areParametersEqual(allocationExpr.binding);
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       catch (Exception e) {
+                               // Something wrong happen, forget super ref...
+                       }
+               }
+               
+               // Store if a reference exists to an overriden method/constructor or the method is in a local type,
+               boolean reportMissing = methDecl == null || !((overriding && this.inherited) || superRef || (methDecl.binding.declaringClass != null && methDecl.binding.declaringClass.isLocalType()));
+
+               // @param tags
+               resolveParamTags(methScope, reportMissing);
+
+               // @return tags
+               if (this.returnStatement == null) {
+                       if (reportMissing && methDecl != null) {
+                               if (!methDecl.isConstructor() && !methDecl.isClinit()) {
+                                       MethodDeclaration meth = (MethodDeclaration) methDecl;
+                                       if (meth.binding.returnType != VoidBinding) {
+                                               // method with return should have @return tag
+                                               methScope.problemReporter().javadocMissingReturnTag(meth.returnType.sourceStart, meth.returnType.sourceEnd, methDecl.binding.modifiers);
+                                       }
+                               }
+                       }
+               } else {
+                       this.returnStatement.resolve(methScope);
+               }
+
+               // @throws/@exception tags
+               resolveThrowsTags(methScope, reportMissing);
+
+               // Resolve param tags with invalid syntax
+               int length = this.invalidParameters == null ? 0 : this.invalidParameters.length;
+               for (int i = 0; i < length; i++) {
+                       this.invalidParameters[i].resolve(methScope, false);
+               }
+       }
+       
+       /*
+        * Resolve @param tags while method scope
+        */
+       private void resolveParamTags(MethodScope methScope, boolean reportMissing) {
+               AbstractMethodDeclaration md = methScope.referenceMethod();
+               int paramTagsSize = this.parameters == null ? 0 : this.parameters.length;
+
+               // If no referenced method (field initializer for example) then report a problem for each param tag
+               if (md == null) {
+                       for (int i = 0; i < paramTagsSize; i++) {
+                               JavadocSingleNameReference param = this.parameters[i];
+                               methScope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
+                       }
+                       return;
+               }
+               
+               // If no param tags then report a problem for each method argument
+               int argumentsSize = md.arguments == null ? 0 : md.arguments.length;
+               if (paramTagsSize == 0) {
+                       if (reportMissing) {
+                               for (int i = 0; i < argumentsSize; i++) {
+                                       Argument arg = md.arguments[i];
+                                       methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+                               }
+                       }
+               } else {
+                       LocalVariableBinding[] bindings = new LocalVariableBinding[paramTagsSize];
+                       int maxBindings = 0;
+
+                       // Scan all @param tags
+                       for (int i = 0; i < paramTagsSize; i++) {
+                               JavadocSingleNameReference param = this.parameters[i];
+                               param.resolve(methScope);
+                               if (param.binding != null && param.binding.isValidBinding()) {
+                                       // Verify duplicated tags
+                                       boolean found = false;
+                                       for (int j = 0; j < maxBindings && !found; j++) {
+                                               if (bindings[j] == param.binding) {
+                                                       methScope.problemReporter().javadocDuplicatedParamTag(param, md.binding.modifiers);
+                                                       found = true;
+                                               }
+                                       }
+                                       if (!found) {
+                                               bindings[maxBindings++] = (LocalVariableBinding) param.binding;
+                                       }
+                               }
+                       }
+
+                       // Look for undocumented arguments
+                       if (reportMissing) {
+                               for (int i = 0; i < argumentsSize; i++) {
+                                       Argument arg = md.arguments[i];
+                                       boolean found = false;
+                                       for (int j = 0; j < maxBindings && !found; j++) {
+                                               LocalVariableBinding binding = bindings[j];
+                                               if (arg.binding == binding) {
+                                                       found = true;
+                                               }
+                                       }
+                                       if (!found) {
+                                               methScope.problemReporter().javadocMissingParamTag(arg, md.binding.modifiers);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /*
+        * Resolve @throws/@exception tags while method scope
+        */
+       private void resolveThrowsTags(MethodScope methScope, boolean reportMissing) {
+               AbstractMethodDeclaration md = methScope.referenceMethod();
+               int throwsTagsLength = this.thrownExceptions == null ? 0 : this.thrownExceptions.length;
+
+               // If no referenced method (field initializer for example) then report a problem for each throws tag
+               if (md == null) {
+                       for (int i = 0; i < throwsTagsLength; i++) {
+                               TypeReference typeRef = this.thrownExceptions[i];
+                               int start = typeRef.sourceStart;
+                               int end = typeRef.sourceEnd;
+                               if (typeRef instanceof JavadocQualifiedTypeReference) {
+                                       start = ((JavadocQualifiedTypeReference) typeRef).tagSourceStart;
+                                       end = ((JavadocQualifiedTypeReference) typeRef).tagSourceEnd;
+                               } else if (typeRef instanceof JavadocSingleTypeReference) {
+                                       start = ((JavadocSingleTypeReference) typeRef).tagSourceStart;
+                                       end = ((JavadocSingleTypeReference) typeRef).tagSourceEnd;
+                               }
+                               methScope.problemReporter().javadocUnexpectedTag(start, end);
+                       }
+                       return;
+               }
+
+               // If no throws tags then report a problem for each method thrown exception
+               int boundExceptionLength = (md.binding == null || md.binding.thrownExceptions == null) ? 0 : md.binding.thrownExceptions.length;
+               int thrownExceptionLength = md.thrownExceptions == null ? 0 : md.thrownExceptions.length;
+               if (throwsTagsLength == 0) {
+                       if (reportMissing) {
+                               for (int i = 0; i < boundExceptionLength; i++) {
+                                       ReferenceBinding exceptionBinding = md.binding.thrownExceptions[i];
+                                       if (exceptionBinding != null && exceptionBinding.isValidBinding()) { // flag only valid class name
+                                               int j=i;
+                                               while (j<thrownExceptionLength && exceptionBinding != md.thrownExceptions[j].resolvedType) j++;
+                                               if (j<thrownExceptionLength) {
+                                                       methScope.problemReporter().javadocMissingThrowsTag(md.thrownExceptions[j], md.binding.modifiers);
+                                               }
+                                       }
+                               }
+                       }
+               } else {
+                       int maxRef = 0;
+                       TypeReference[] typeReferences = new TypeReference[throwsTagsLength];
+
+                       // Scan all @throws tags
+                       for (int i = 0; i < throwsTagsLength; i++) {
+                               TypeReference typeRef = this.thrownExceptions[i];
+                               typeRef.resolve(methScope);
+                               TypeBinding typeBinding = typeRef.resolvedType;
+
+                               if (typeBinding != null && typeBinding.isValidBinding() && typeBinding.isClass()) {
+                                       typeReferences[maxRef++] = typeRef;
+                               }
+                       }
+
+                       // Look for undocumented thrown exception
+                       for (int i = 0; i < boundExceptionLength; i++) {
+                               ReferenceBinding exceptionBinding = md.binding.thrownExceptions[i];
+                               boolean found = false;
+                               for (int j = 0; j < maxRef && !found; j++) {
+                                       if (typeReferences[j] != null) {
+                                               TypeBinding typeBinding = typeReferences[j].resolvedType;
+                                               if (exceptionBinding == typeBinding) {
+                                                       found = true;
+                                                       typeReferences[j] = null;
+                                               }
+                                       }
+                               }
+                               if (!found && reportMissing) {
+                                       if (exceptionBinding != null && exceptionBinding.isValidBinding()) { // flag only valid class name
+                                               int k=i;
+                                               while (k<thrownExceptionLength && exceptionBinding != md.thrownExceptions[k].resolvedType) k++;
+                                               if (k<thrownExceptionLength) {
+                                                       methScope.problemReporter().javadocMissingThrowsTag(md.thrownExceptions[k], md.binding.modifiers);
+                                               }
+                                       }
+                               }
+                       }
+
+                       // Verify additional @throws tags
+                       for (int i = 0; i < maxRef; i++) {
+                               TypeReference typeRef = typeReferences[i];
+                               if (typeRef != null) {
+                                       boolean compatible = false;
+                                       // thrown exceptions subclasses are accepted
+                                       for (int j = 0; j<thrownExceptionLength && !compatible; j++) {
+                                               TypeBinding exceptionBinding = md.thrownExceptions[j].resolvedType;
+                                               if (exceptionBinding != null) {
+                                                       compatible = typeRef.resolvedType.isCompatibleWith(exceptionBinding);
+                                               }
+                                       }
+                       
+                                       //  If not compatible only complain on unchecked exception
+                                       if (!compatible &&
+                                                !typeRef.resolvedType.isCompatibleWith(methScope.getJavaLangRuntimeException()) &&
+                                                !typeRef.resolvedType.isCompatibleWith(methScope.getJavaLangError())) {
+                                               methScope.problemReporter().javadocInvalidThrowsClassName(typeRef, md.binding.modifiers);
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       /*
+        * Search node with a given staring position in javadoc objects arrays.
+        */
+       public ASTNode getNodeStartingAt(int start) {
+               // parameters array
+               if (this.parameters != null) {
+                       for (int i=0; i<this.parameters.length; i++) {
+                               JavadocSingleNameReference param = this.parameters[i];
+                               if (param.sourceStart==start) {
+                                       return param;
+                               }
+                       }
+               }
+               // array of invalid syntax tags parameters
+               if (this.invalidParameters != null) {
+                       for (int i=0; i<this.invalidParameters.length; i++) {
+                               JavadocSingleNameReference param = this.invalidParameters[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 (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 (expression.sourceStart==start) {
+                                       return expression;
+                               } else if (expression instanceof JavadocAllocationExpression) {
+                                       JavadocAllocationExpression allocationExpr = (JavadocAllocationExpression) this.references[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++) {
+                                                               if (allocationExpr.arguments[j].sourceStart == start) {
+                                                                       return allocationExpr.arguments[j];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               } else if (expression instanceof JavadocMessageSend) {
+                                       JavadocMessageSend messageSend = (JavadocMessageSend) this.references[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++) {
+                                                               if (messageSend.arguments[j].sourceStart == start) {
+                                                                       return messageSend.arguments[j];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               return null;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
new file mode 100644 (file)
index 0000000..6c7ff1f
--- /dev/null
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class JavadocAllocationExpression extends AllocationExpression {
+
+       public int tagSourceStart, tagSourceEnd;
+       public boolean superAccess = false;
+       
+       public JavadocAllocationExpression(long pos) {
+               this.sourceStart = (int) (pos >>> 32);
+               this.sourceEnd = (int) pos;
+               this.bits |= InsideJavadoc;
+       }
+
+       /*
+        * Resolves type on a Block or Class scope.
+        */
+       private TypeBinding internalResolveType(Scope scope) {
+
+               // Propagate the type checking to the arguments, and check if the constructor is defined.
+               this.constant = NotAConstant;
+               if (this.type == null) {
+                       this.resolvedType = scope.enclosingSourceType();
+               } else if (scope.kind == Scope.CLASS_SCOPE) {
+                       this.resolvedType = this.type.resolveType((ClassScope)scope);
+               } else {
+                       this.resolvedType = this.type.resolveType((BlockScope)scope);
+               }
+
+               // buffering the arguments' types
+               TypeBinding[] argumentTypes = NoParameters;
+               if (this.arguments != null) {
+                       boolean argHasError = false;
+                       int length = this.arguments.length;
+                       argumentTypes = new TypeBinding[length];
+                       for (int i = 0; i < length; i++) {
+                               Expression argument = this.arguments[i];
+                               if (scope.kind == Scope.CLASS_SCOPE) {
+                                       argumentTypes[i] = argument.resolveType((ClassScope)scope);
+                               } else {
+                                       argumentTypes[i] = argument.resolveType((BlockScope)scope);
+                               }
+                               if (argumentTypes[i] == null) {
+                                       argHasError = true;
+                               }
+                       }
+                       if (argHasError) {
+                               return null;
+                       }
+               }
+
+               // check resolved type
+               if (this.resolvedType == null) {
+                       return null;
+               }
+               this.superAccess = scope.enclosingSourceType().isCompatibleWith(this.resolvedType);
+
+               ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
+               this.binding = scope.getConstructor(allocationType, argumentTypes, this);
+               if (!this.binding.isValidBinding()) {
+                       MethodBinding methodBinding = scope.getMethod(this.resolvedType, this.resolvedType.sourceName(), argumentTypes, this);
+                       if (methodBinding.isValidBinding()) {
+                               this.binding = methodBinding;
+                       } else {
+                               if (this.binding.declaringClass == null) {
+                                       this.binding.declaringClass = allocationType;
+                               }
+                               scope.problemReporter().javadocInvalidConstructor(this, this.binding, scope.getDeclarationModifiers());
+                       }
+                       return this.resolvedType;
+               }
+               if (isMethodUseDeprecated(this.binding, scope)) {
+                       scope.problemReporter().javadocDeprecatedMethod(this.binding, this, scope.getDeclarationModifiers());
+               }
+
+               return allocationType;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+        */
+       public boolean isSuperAccess() {
+               return this.superAccess;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public TypeBinding resolveType(BlockScope scope) {
+               return internalResolveType(scope);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public TypeBinding resolveType(ClassScope scope) {
+               return internalResolveType(scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArgumentExpression.java
new file mode 100644 (file)
index 0000000..57be26e
--- /dev/null
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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.env.IConstants;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+
+public class JavadocArgumentExpression extends Expression {
+       public char[] token;
+       public Argument argument;
+
+       public JavadocArgumentExpression(char[] name, int startPos, int endPos, TypeReference typeRef) {
+               this.token = name;
+               this.sourceStart = startPos;
+               this.sourceEnd = endPos;
+               long pos = (((long) startPos) << 32) + endPos;
+               this.argument = new Argument(name, pos, typeRef, IConstants.AccDefault);
+               this.bits |= InsideJavadoc;
+       }
+
+       /*
+        * Resolves type on a Block or Class scope.
+        */
+       private TypeBinding internalResolveType(Scope scope) {
+               this.constant = NotAConstant;
+               if (this.resolvedType != null) { // is a shared type reference which was already resolved
+                       if (!this.resolvedType.isValidBinding()) {
+                               return null; // already reported error
+                       }
+               }
+               else {
+                       if (this.argument != null) {
+                               TypeReference typeRef = this.argument.type;
+                               if (typeRef != null) {
+                                       this.resolvedType = typeRef.getTypeBinding(scope);
+                                       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;
+                               }
+                       }
+               }
+               return null;
+       }
+       
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+               if (this.argument == null) {
+                       if (this.token != null) {
+                               output.append(this.token);
+                       }
+               }
+               else {
+                       this.argument.print(indent, output);
+               }
+               return output;
+       }
+
+       public void resolve(BlockScope scope) {
+               if (this.argument != null) {
+                       this.argument.resolve(scope);
+               }
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+               return internalResolveType(scope);
+       }
+
+       public TypeBinding resolveType(ClassScope scope) {
+               return internalResolveType(scope);
+       }
+       
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+               if (visitor.visit(this, blockScope)) {
+                       if (this.argument != null) {
+                               this.argument.traverse(visitor, blockScope);
+                       }
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArrayQualifiedTypeReference.java
new file mode 100644 (file)
index 0000000..86b4d0e
--- /dev/null
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.Scope;
+
+
+
+public class JavadocArrayQualifiedTypeReference extends ArrayQualifiedTypeReference {
+
+       public int tagSourceStart, tagSourceEnd;
+
+       public JavadocArrayQualifiedTypeReference(JavadocQualifiedTypeReference typeRef, int dim) {
+               super(typeRef.tokens, dim, typeRef.sourcePositions);
+       }
+
+       protected void reportInvalidType(Scope scope) {
+               scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+       }
+       protected void reportDeprecatedType(Scope scope) {
+               scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocArraySingleTypeReference.java
new file mode 100644 (file)
index 0000000..8395065
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.Scope;
+
+
+public class JavadocArraySingleTypeReference extends ArrayTypeReference {
+
+       public JavadocArraySingleTypeReference(char[] name, int dim, long pos) {
+               super(name, dim, pos);
+               this.bits |= InsideJavadoc;
+       }
+
+       protected void reportInvalidType(Scope scope) {
+               scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+       }
+       protected void reportDeprecatedType(Scope scope) {
+               scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocFieldReference.java
new file mode 100644 (file)
index 0000000..04f1016
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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.*;
+
+public class JavadocFieldReference extends FieldReference {
+
+       public int tagSourceStart, tagSourceEnd;
+
+       public JavadocFieldReference(char[] source, long pos) {
+               super(source, pos);
+               this.bits |= InsideJavadoc;
+       }
+
+       /*
+        * Resolves type on a Block or Class scope.
+        */
+       private TypeBinding internalResolveType(Scope scope) {
+
+               this.constant = NotAConstant;
+               if (this.receiver == null) {
+                       this.receiverType = scope.enclosingSourceType();
+               } else if (scope.kind == Scope.CLASS_SCOPE) {
+                       this.receiverType = this.receiver.resolveType((ClassScope) scope);
+               } else {
+                       this.receiverType = this.receiver.resolveType((BlockScope)scope);
+               }
+               if (this.receiverType == null) {
+                       return null;
+               }
+
+               Binding fieldBinding = (this.receiver != null && this.receiver.isThis())
+                       ? scope.classScope().getBinding(this.token, this.bits & RestrictiveFlagMASK, this, true /*resolve*/)
+                       : scope.getField(this.receiverType, this.token, this);
+               if (!fieldBinding.isValidBinding()) {
+                       // implicit lookup may discover issues due to static/constructor contexts. javadoc must be resilient
+                       switch (fieldBinding.problemId()) {
+                               case ProblemReasons.NonStaticReferenceInConstructorInvocation:
+                               case ProblemReasons.NonStaticReferenceInStaticContext:
+                               case ProblemReasons.InheritedNameHidesEnclosingName : 
+                                       FieldBinding closestMatch = ((ProblemFieldBinding)fieldBinding).closestMatch;
+                                       if (closestMatch != null) {
+                                               fieldBinding = closestMatch; // ignore problem if can reach target field through it
+                                       }
+                       }
+               }                       
+               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) {
+                                       scope.problemReporter().javadocInvalidField(this.sourceStart, this.sourceEnd, fieldBinding, this.receiverType, scope.getDeclarationModifiers());
+                               } else {
+                                       switch (bindings.length) {
+                                               case 0:
+                                                       scope.problemReporter().javadocInvalidField(this.sourceStart, this.sourceEnd, fieldBinding, this.receiverType, scope.getDeclarationModifiers());
+                                                       break;
+                                               case 1:
+                                                       this.binding = null;
+                                                       break;
+                                               default:
+                                                       scope.problemReporter().javadocAmbiguousMethodReference(this.sourceStart, this.sourceEnd, fieldBinding, scope.getDeclarationModifiers());
+                                                       break;
+                                       }
+                               }
+                       }
+                       return null;
+               }
+               this.binding = (FieldBinding) fieldBinding;
+
+               if (isFieldUseDeprecated(this.binding, scope, (this.bits & IsStrictlyAssignedMASK) != 0)) {
+                       scope.problemReporter().javadocDeprecatedField(this.binding, this, scope.getDeclarationModifiers());
+               }
+               return this.resolvedType = this.binding.type;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+        */
+       public boolean isSuperAccess() {
+               return false;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               if (this.receiver != null) {
+                       this.receiver.printExpression(0, output);
+               }
+               output.append('#').append(this.token);
+               return output;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public TypeBinding resolveType(BlockScope scope) {
+               return internalResolveType(scope);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public TypeBinding resolveType(ClassScope scope) {
+               return internalResolveType(scope);
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       if (this.receiver != null) {
+                               this.receiver.traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocImportReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocImportReference.java
new file mode 100644 (file)
index 0000000..2f6d5b0
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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;
+       }
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
new file mode 100644 (file)
index 0000000..ec69136
--- /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.lookup.*;
+
+
+public class JavadocMessageSend extends MessageSend {
+
+       public int tagSourceStart, tagSourceEnd;
+       public boolean superAccess = false;
+
+       public JavadocMessageSend(char[] name, long pos) {
+               this.selector = name;
+               this.nameSourcePosition = pos;
+               this.sourceStart = (int) (this.nameSourcePosition >>> 32);
+               this.sourceEnd = (int) this.nameSourcePosition;
+               this.bits |= InsideJavadoc;
+       }
+       public JavadocMessageSend(char[] name, long pos, JavadocArgumentExpression[] arguments) {
+               this(name, pos);
+               this.arguments = arguments;
+       }
+
+       /*
+        * Resolves type on a Block or Class scope.
+        */
+       private TypeBinding internalResolveType(Scope scope) {
+               // Answer the signature return type
+               // Base type promotion
+               this.constant = NotAConstant;
+               if (this.receiver == null) {
+                       this.receiverType = scope.enclosingSourceType();
+               } else if (scope.kind == Scope.CLASS_SCOPE) {
+                       this.receiverType = this.receiver.resolveType((ClassScope) scope);
+               } else {
+                       this.receiverType = this.receiver.resolveType((BlockScope) scope);
+               }
+
+               // will check for null after args are resolved
+               TypeBinding[] argumentTypes = NoParameters;
+               if (this.arguments != null) {
+                       boolean argHasError = false; // typeChecks all arguments 
+                       int length = this.arguments.length;
+                       argumentTypes = new TypeBinding[length];
+                       for (int i = 0; i < length; i++){
+                               Expression argument = this.arguments[i];
+                               if (scope.kind == Scope.CLASS_SCOPE) {
+                                       argumentTypes[i] = argument.resolveType((ClassScope)scope);
+                               } else {
+                                       argumentTypes[i] = argument.resolveType((BlockScope)scope);
+                               }
+                               if (argumentTypes[i] == null) {
+                                       argHasError = true;
+                               }
+                       }
+                       if (argHasError) {
+                               return null;
+                       }
+               }
+
+               // check receiver type
+               if (this.receiverType == null) {
+                       return null;
+               }
+               this.qualifyingType = this.receiverType;
+               this.superAccess = scope.enclosingSourceType().isCompatibleWith(this.receiverType);
+
+               // base type cannot receive any message
+               if (this.receiverType.isBaseType()) {
+                       scope.problemReporter().javadocErrorNoMethodFor(this, this.receiverType, argumentTypes, scope.getDeclarationModifiers());
+                       return null;
+               }
+               this.binding = (this.receiver != null && this.receiver.isThis())
+                       ? scope.getImplicitMethod(this.selector, argumentTypes, this)
+                       : scope.getMethod(this.receiverType, 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()) {
+                               case ProblemReasons.NonStaticReferenceInConstructorInvocation:
+                               case ProblemReasons.NonStaticReferenceInStaticContext:
+                               case ProblemReasons.InheritedNameHidesEnclosingName : 
+                                       MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
+                                       if (closestMatch != null) {
+                                               this.binding = closestMatch; // ignore problem if can reach target method through it
+                                       }
+                       }
+               }
+               if (!this.binding.isValidBinding()) {
+                       if (this.binding.declaringClass == null) {
+                               if (this.receiverType instanceof ReferenceBinding) {
+                                       this.binding.declaringClass = (ReferenceBinding) this.receiverType;
+                               } else { 
+                                       scope.problemReporter().javadocErrorNoMethodFor(this, this.receiverType, argumentTypes, scope.getDeclarationModifiers());
+                                       return null;
+                               }
+                       }
+                       scope.problemReporter().javadocInvalidMethod(this, this.binding, scope.getDeclarationModifiers());
+                       // record the closest match, for clients who may still need hint about possible method match
+                       if (this.binding instanceof ProblemMethodBinding){
+                               MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch;
+                               if (closestMatch != null) this.codegenBinding = this.binding = closestMatch;
+                       }
+                       return this.resolvedType = this.binding == null ? null : this.binding.returnType;
+               }
+               if (isMethodUseDeprecated(this.binding, scope)) {
+                       scope.problemReporter().javadocDeprecatedMethod(this.binding, this, scope.getDeclarationModifiers());
+               }
+
+               return this.resolvedType = this.binding.returnType;
+       }
+       
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#isSuperAccess()
+        */
+       public boolean isSuperAccess() {
+               return this.superAccess;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output){
+       
+               if (this.receiver != null) {
+                       this.receiver.printExpression(0, output);
+               }
+               output.append('#').append(this.selector).append('(');
+               if (this.arguments != null) {
+                       for (int i = 0; i < this.arguments.length ; i ++) {     
+                               if (i > 0) output.append(", "); //$NON-NLS-1$
+                               this.arguments[i].printExpression(0, output);
+                       }
+               }
+               return output.append(')');
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+               return internalResolveType(scope);
+       }
+
+       public TypeBinding resolveType(ClassScope scope) {
+               return internalResolveType(scope);
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+               if (visitor.visit(this, blockScope)) {
+                       if (this.receiver != null) {
+                               this.receiver.traverse(visitor, blockScope);
+                       }
+                       if (this.arguments != null) {
+                               int argumentsLength = this.arguments.length;
+                               for (int i = 0; i < argumentsLength; i++)
+                                       this.arguments[i].traverse(visitor, blockScope);
+                       }
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
new file mode 100644 (file)
index 0000000..388f8ef
--- /dev/null
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+
+
+public class JavadocQualifiedTypeReference extends QualifiedTypeReference {
+
+       public int tagSourceStart, tagSourceEnd;
+       public PackageBinding packageBinding;
+
+       public JavadocQualifiedTypeReference(char[][] sources, long[] pos, int tagStart, int tagEnd) {
+               super(sources, pos);
+               this.tagSourceStart = tagStart;
+               this.tagSourceEnd = tagEnd;
+               this.bits |= InsideJavadoc;
+       }
+
+       protected void reportInvalidType(Scope scope) {
+               scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+       }
+       protected void reportDeprecatedType(Scope scope) {
+               scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+
+       /*
+        * 
+        */
+       private 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()) {
+                               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);
+                       }
+               }
+               return 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);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+        * We need to override to handle package references
+        */
+       public TypeBinding resolveType(ClassScope classScope) {
+               return internalResolveType(classScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocReturnStatement.java
new file mode 100644 (file)
index 0000000..8a53e1b
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+
+public class JavadocReturnStatement extends ReturnStatement {
+       public char[] description;
+
+       public JavadocReturnStatement(int s, int e, char[] descr) {
+               super(null, s, e);
+               this.description = descr;
+               this.bits |= InsideJavadoc;
+       }
+
+       public void resolve(BlockScope scope) {
+               MethodScope methodScope = scope.methodScope();
+               MethodBinding methodBinding;
+               TypeBinding methodType =
+                       (methodScope.referenceContext instanceof AbstractMethodDeclaration)
+                               ? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null 
+                                       ? null 
+                                       : methodBinding.returnType)
+                               : VoidBinding;
+               if (methodType == null || methodType == VoidBinding) {
+                       scope.problemReporter().javadocUnexpectedTag(this.sourceStart, this.sourceEnd);
+               }
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocSingleNameReference.java
new file mode 100644 (file)
index 0000000..5661217
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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.*;
+
+public class JavadocSingleNameReference extends SingleNameReference {
+
+       public int tagSourceStart, tagSourceEnd;
+
+       public JavadocSingleNameReference(char[] name, int startPosition, int endPosition) {
+               super(name, (((long) startPosition) << 32) + endPosition);
+               this.bits |= InsideJavadoc;
+       }
+
+       public void resolve(BlockScope scope) {
+               resolve(scope, true);
+       }
+
+       /**
+        * Resolve without warnings
+        */
+       public void resolve(BlockScope scope, boolean warn) {
+               
+               LocalVariableBinding variableBinding = scope.findVariable(this.token);
+               if (variableBinding != null && variableBinding.isValidBinding() && variableBinding.isArgument) {
+                       this.binding = variableBinding;
+                       return;
+               }
+               if (warn) {
+                       try {
+                               MethodScope methScope = (MethodScope) scope;
+                               scope.problemReporter().javadocInvalidParamName(this, methScope.referenceMethod().modifiers);
+                       }
+                       catch (Exception e) {
+                               scope.problemReporter().javadocInvalidParamName(this, -1);
+                       }
+               }
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
new file mode 100644 (file)
index 0000000..541f099
--- /dev/null
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+
+public class JavadocSingleTypeReference extends SingleTypeReference {
+       
+       public int tagSourceStart, tagSourceEnd;
+       public PackageBinding packageBinding;
+
+       public JavadocSingleTypeReference(char[] source, long pos, int tagStart, int tagEnd) {
+               super(source, pos);
+               this.tagSourceStart = tagStart;
+               this.tagSourceEnd = tagEnd;
+               this.bits |= InsideJavadoc;
+       }
+
+       protected void reportInvalidType(Scope scope) {
+               scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
+       }
+       protected void reportDeprecatedType(Scope scope) {
+               scope.problemReporter().javadocDeprecatedType(this.resolvedType, this, scope.getDeclarationModifiers());
+       }
+
+       /* (non-Javadoc)
+        * Redefine to capture javadoc specific signatures
+        * @see org.eclipse.jdt.internal.compiler.ast.ASTNode#traverse(org.eclipse.jdt.internal.compiler.ASTVisitor, org.eclipse.jdt.internal.compiler.lookup.BlockScope)
+        */
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+
+       /*
+        * 
+        */
+       private 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);
+                       }
+               }
+               return 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);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.Expression#resolveType(org.eclipse.jdt.internal.compiler.lookup.ClassScope)
+        * We need to override to handle package references
+        */
+       public TypeBinding resolveType(ClassScope classScope) {
+               return internalResolveType(classScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/LabeledStatement.java
new file mode 100644 (file)
index 0000000..b24cde3
--- /dev/null
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class LabeledStatement extends Statement {
+       
+       public Statement statement;
+       public char[] label;
+       public Label targetLabel;
+
+       // for local variables table attributes
+       int mergedInitStateIndex = -1;
+       
+       /**
+        * LabeledStatement constructor comment.
+        */
+       public LabeledStatement(char[] label, Statement statement, int sourceStart, int sourceEnd) {
+               
+               this.statement = statement;
+               // remember useful empty statement
+               if (statement instanceof EmptyStatement) statement.bits |= IsUsefulEmptyStatementMASK;
+               this.label = label;
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+       
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // need to stack a context to store explicit label, answer inits in case of normal completion merged
+               // with those relative to the exit path from break statement occurring inside the labeled statement.
+               if (statement == null) {
+                       return flowInfo;
+               } else {
+                       LabelFlowContext labelContext;
+                       FlowInfo mergedInfo =
+                               statement
+                                       .analyseCode(
+                                               currentScope,
+                                               (labelContext =
+                                                       new LabelFlowContext(
+                                                               flowContext,
+                                                               this,
+                                                               label,
+                                                               (targetLabel = new Label()),
+                                                               currentScope)),
+                                               flowInfo)
+                                       .mergedWith(labelContext.initsOnBreak);
+                       mergedInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(mergedInfo);
+                       return mergedInfo;
+               }
+       }
+       
+       public ASTNode concreteStatement() {
+               
+               // return statement.concreteStatement(); // for supporting nested labels:   a:b:c: someStatement (see 21912)
+               return statement;
+       }
+       
+       /**
+        * Code generation for labeled statement
+        *
+        * may not need actual source positions recording
+        *
+        * @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) {
+               
+               int pc = codeStream.position;
+               if (targetLabel != null) {
+                       targetLabel.initialize(codeStream);
+                       if (statement != null) {
+                               statement.generateCode(currentScope, codeStream);
+                       }
+                       targetLabel.place();
+               }
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+       
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+
+               printIndent(tab, output).append(label).append(": "); //$NON-NLS-1$
+               if (this.statement == null) 
+                       output.append(';');
+               else 
+                       this.statement.printStatement(0, output); 
+               return output;
+       }
+       
+       public void resolve(BlockScope scope) {
+               
+               if (this.statement != null) {
+                       this.statement.resolve(scope);
+               }
+       }
+
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       if (this.statement != null) this.statement.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Literal.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Literal.java
new file mode 100644 (file)
index 0000000..32aa623
--- /dev/null
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public abstract class Literal extends Expression {
+
+       public Literal(int s, int e) {
+
+               sourceStart = s;
+               sourceEnd = e;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+                       
+               return flowInfo;
+       }
+
+       public abstract void computeConstant();
+
+       public abstract TypeBinding literalType(BlockScope scope);
+
+       public StringBuffer printExpression(int indent, StringBuffer output){
+       
+               return output.append(source());
+        }
+        
+       public TypeBinding resolveType(BlockScope scope) {
+               // compute the real value, which must range its type's range
+               this.resolvedType = literalType(scope);
+
+               // in case of error, constant did remain null
+               computeConstant();
+               if (constant == null) {
+                       scope.problemReporter().constantOutOfRange(this, this.resolvedType);
+                       constant = Constant.NotAConstant;
+               }
+               return this.resolvedType;
+       }
+
+       public abstract char[] source();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
new file mode 100644 (file)
index 0000000..353fc00
--- /dev/null
@@ -0,0 +1,221 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.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.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class LocalDeclaration extends AbstractVariableDeclaration {
+
+       public LocalVariableBinding binding;
+       
+       public LocalDeclaration(
+               char[] name,
+               int sourceStart,
+               int sourceEnd) {
+
+               this.name = name;
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+               this.declarationEnd = sourceEnd;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // record variable initialization if any
+               if (flowInfo.isReachable()) {
+                       bits |= IsLocalDeclarationReachableMASK; // only set if actually reached
+               }
+               if (initialization == null) 
+                       return flowInfo;
+                       
+               flowInfo =
+                       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);
+               return flowInfo;
+       }
+
+       public void checkModifiers() {
+
+               //only potential valid modifier is <<final>>
+               if (((modifiers & AccJustFlag) & ~AccFinal) != 0)
+                       //AccModifierProblem -> other (non-visibility problem)
+                       //AccAlternateModifierProblem -> duplicate modifier
+                       //AccModifierProblem | AccAlternateModifierProblem -> visibility problem"
+
+                       modifiers = (modifiers & ~AccAlternateModifierProblem) | AccModifierProblem;
+       }
+
+       /**
+        * Code generation for a local declaration:
+        *      i.e.&nbsp;normal assignment to a local variable + unused variable handling 
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+               // even if not reachable, variable must be added to visible if allocated (28298)
+               if (binding.resolvedPosition != -1) {
+                       codeStream.addVisibleLocalVariable(binding);
+               }
+               if ((bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               int pc = codeStream.position;
+               Constant inlinedValue;
+
+               // something to initialize?
+               if (initialization != null) {
+                       // initialize to constant value?
+                       if ((inlinedValue = initialization.constant) != NotAConstant) {
+                               // forget initializing unused or final locals set to constant value (final ones are inlined)
+                               if (binding.resolvedPosition != -1) { // may need to preserve variable
+                                       int initPC = codeStream.position;
+                                       codeStream.generateConstant(inlinedValue, initialization.implicitConversion);
+                                       codeStream.recordPositionsFrom(initPC, initialization.sourceStart);
+                                       codeStream.store(binding, false);
+                                       binding.recordInitializationStartPC(codeStream.position);
+                                       //                              codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index 
+                                       //                              codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index            
+                               }
+                       } else { // initializing to non-constant value
+                               initialization.generateCode(currentScope, codeStream, true);
+                               // if binding unused generate then discard the value
+                               if (binding.resolvedPosition != -1) {
+                                       // 26903, need extra cast to store null in array local var      
+                                       if (binding.type.isArrayType() 
+                                               && (initialization.resolvedType == NullBinding  // arrayLoc = null
+                                                       || ((initialization instanceof CastExpression)  // arrayLoc = (type[])null
+                                                               && (((CastExpression)initialization).innermostCastedExpression().resolvedType == NullBinding)))){
+                                               codeStream.checkcast(binding.type); 
+                                       }                                       
+                                       codeStream.store(binding, false);
+                                       if (binding.initializationCount == 0) {
+                                               /* Variable may have been initialized during the code initializing it
+                                                       e.g. int i = (i = 1);
+                                               */
+                                               binding.recordInitializationStartPC(codeStream.position);
+                                               //                                      codeStream.lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index 
+                                               //                                      codeStream.lastInitStateIndexWhenAddingInits = -2; // reinitialize add index 
+                                       }
+                               } else {
+                                       if ((binding.type == LongBinding) || (binding.type == DoubleBinding)) {
+                                               codeStream.pop2();
+                                       } else {
+                                               codeStream.pop();
+                                       }
+                               }
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public void resolve(BlockScope scope) {
+
+               // create a binding and add it to the scope
+               TypeBinding typeBinding = type.resolveType(scope);
+
+               checkModifiers();
+
+               if (typeBinding != null) {
+                       if (typeBinding == VoidBinding) {
+                               scope.problemReporter().variableTypeCannotBeVoid(this);
+                               return;
+                       }
+                       if (typeBinding.isArrayType() && ((ArrayBinding) typeBinding).leafComponentType == VoidBinding) {
+                               scope.problemReporter().variableTypeCannotBeVoidArray(this);
+                               return;
+                       }
+               }
+               
+               Binding existingVariable = scope.getBinding(name, BindingIds.VARIABLE, this, false /*do not resolve hidden field*/);
+               boolean shouldInsertInScope = true;
+               if (existingVariable != null && existingVariable.isValidBinding()){
+                       if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) {
+                               shouldInsertInScope = false;
+                               scope.problemReporter().redefineLocal(this);
+                       } else {
+                               scope.problemReporter().localVariableHiding(this, existingVariable, false);
+                       }
+               }
+                               
+               if (shouldInsertInScope) {
+                       if ((modifiers & AccFinal)!= 0 && this.initialization == null) {
+                               modifiers |= AccBlankFinal;
+                       }
+                       binding = new LocalVariableBinding(this, typeBinding, modifiers, false);
+                       scope.addLocalVariable(binding);
+                       binding.constant = NotAConstant;
+                       // allow to recursivelly target the binding....
+                       // the correct constant is harmed if correctly computed at the end of this method
+               }
+
+               if (typeBinding == null) {
+                       if (initialization != null)
+                               initialization.resolveType(scope); // want to report all possible errors
+                       return;
+               }
+
+               // store the constant for final locals  
+               if (initialization != null) {
+                       if (initialization instanceof ArrayInitializer) {
+                               TypeBinding initializationType = initialization.resolveTypeExpecting(scope, typeBinding);
+                               if (initializationType != null) {
+                                       ((ArrayInitializer) initialization).binding = (ArrayBinding) initializationType;
+                                       initialization.implicitWidening(typeBinding, initializationType);
+                               }
+                       } else {
+                               TypeBinding initializationType = initialization.resolveType(scope);
+                               if (initializationType != null) {
+                                       if (initialization.isConstantValueOfTypeAssignableToType(initializationType, typeBinding)
+                                               || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationType.id))
+                                               || initializationType.isCompatibleWith(typeBinding))
+                                               initialization.implicitWidening(typeBinding, initializationType);
+                                       else
+                                               scope.problemReporter().typeMismatchError(initializationType, typeBinding, this);
+                               }
+                       }
+
+                       // change the constant in the binding when it is final
+                       // (the optimization of the constant propagation will be done later on)
+                       // cast from constant actual type to variable type
+                       if (binding != null) {
+                               binding.constant =
+                                       binding.isFinal()
+                                               ? initialization.constant.castTo((typeBinding.id << 4) + initialization.constant.typeID())
+                                               : NotAConstant;
+                       }
+               }
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       type.traverse(visitor, scope);
+                       if (initialization != null)
+                               initialization.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/LongLiteral.java
new file mode 100644 (file)
index 0000000..70294b5
--- /dev/null
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class LongLiteral extends NumberLiteral {
+       long value;
+       
+       static final Constant FORMAT_ERROR = new DoubleConstant(1.0/0.0); // NaN;       
+               
+public LongLiteral(char[] token, int s,int e) {
+       super(token, s,e);
+}
+public LongLiteral(char[] token, int s,int e, long value) {
+       this(token, s,e);
+       this.value = value;
+}
+public void computeConstant() {
+       //the overflow (when radix=10) is tested using the fact that
+       //the value should always grow during its computation
+
+       int length = source.length - 1; //minus one because the last char is 'l' or 'L'
+       
+       long computedValue ;
+       if (source[0] == '0')
+       {       if (length == 1) {      constant = Constant.fromValue(0L);      return; }
+               final int shift,radix;
+               int j ;
+               if ( (source[1] == 'x') | (source[1] == 'X') )
+               {       shift = 4 ; j = 2; radix = 16;}
+               else
+               {       shift = 3 ; j = 1; radix = 8;}
+               int nbDigit = 0;
+               while (source[j]=='0') 
+               {       j++; //jump over redondant zero
+                       if ( j == length)
+                       {       //watch for 0000000000000L
+                               constant = Constant.fromValue(value = 0L);
+                               return ;}}
+                               
+               int digitValue ;
+               if ((digitValue = Character.digit(source[j++],radix))   < 0 )   
+               {       constant = FORMAT_ERROR; return ;}
+               if (digitValue >= 8) nbDigit = 4;
+               else    if (digitValue >= 4) nbDigit = 3;
+                               else    if (digitValue >= 2) nbDigit = 2;
+                                               else nbDigit = 1; //digitValue is not 0
+               computedValue = digitValue ;
+               while (j<length)
+               {       if ((digitValue = Character.digit(source[j++],radix))   < 0 )   
+                       {       constant = FORMAT_ERROR; return ;}
+                       if ((nbDigit += shift) > 64) return /*constant stays null*/ ;
+                       computedValue = (computedValue<<shift) | digitValue ;}}
+
+       else
+       {       //-----------case radix=10-----------------
+               long previous = computedValue = 0;
+               for (int i = 0 ; i < length; i++) 
+               {       int digitValue ;        
+                       if ((digitValue = Character.digit(source[i], 10)) < 0 ) return /*constant stays null*/ ;
+                       previous = computedValue;
+                       computedValue = 10 * computedValue + digitValue ;
+                       if (previous > computedValue) return /*constant stays null*/;}}
+       
+       constant = Constant.fromValue(value = computedValue);
+}
+/**
+ * Code generation for long 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_long)
+                       codeStream.generateInlinedValue(value);
+               else
+                       codeStream.generateConstant(constant, implicitConversion);
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public TypeBinding literalType(BlockScope scope) {
+       return LongBinding;
+}
+public final boolean mayRepresentMIN_VALUE(){
+       //a special autorized int literral is 9223372036854775808L
+       //which is ONE over the limit. This special case 
+       //only is used in combinaison with - to denote
+       //the minimal value of int -9223372036854775808L
+
+       return ((source.length == 20) &&
+                       (source[0] == '9') &&
+                       (source[1] == '2') &&
+                       (source[2] == '2') &&
+                       (source[3] == '3') &&                   
+                       (source[4] == '3') &&
+                       (source[5] == '7') &&
+                       (source[6] == '2') &&
+                       (source[7] == '0') &&                   
+                       (source[8] == '3') &&
+                       (source[9] == '6') &&
+                       (source[10] == '8') &&
+                       (source[11] == '5') &&
+                       (source[12] == '4') &&                  
+                       (source[13] == '7') &&
+                       (source[14] == '7') &&
+                       (source[15] == '5') &&
+                       (source[16] == '8') &&                  
+                       (source[17] == '0') &&
+                       (source[18] == '8'));}
+public TypeBinding resolveType(BlockScope scope) {
+       // the format may be incorrect while the scanner could detect
+       // such error only on painfull tests...easier and faster here
+
+       TypeBinding tb = super.resolveType(scope);
+       if (constant == FORMAT_ERROR) {
+               constant = NotAConstant;
+               scope.problemReporter().constantOutOfFormat(this);
+               this.resolvedType = null;
+               return null;
+       }
+       return tb;
+}
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+       visitor.visit(this, scope);
+       visitor.endVisit(this, scope);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/LongLiteralMinValue.java b/src/java/org/eclipse/jdt/internal/compiler/ast/LongLiteralMinValue.java
new file mode 100644 (file)
index 0000000..e24da63
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.impl.*;
+
+public class LongLiteralMinValue extends LongLiteral {
+
+       final static char[] CharValue = new char[]{'-', '9','2','2','3','3','7','2','0','3','6','8','5','4','7','7','5','8','0','8','L'};
+       final static Constant MIN_VALUE = Constant.fromValue(Long.MIN_VALUE) ; 
+
+public LongLiteralMinValue(){
+       super(CharValue,0,0,Long.MIN_VALUE);
+       constant = MIN_VALUE;
+}
+public void computeConstant() {
+
+       /*precomputed at creation time*/}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/MagicLiteral.java
new file mode 100644 (file)
index 0000000..ed9b597
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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 abstract class  MagicLiteral extends Literal {
+       
+       public MagicLiteral(int start , int end) {
+               
+               super(start,end);
+       }
+       
+       public boolean isValidJavaStatement(){
+               
+               return false ;
+       }
+       
+       public char[] source() {
+       
+               return null;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/src/java/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
new file mode 100644 (file)
index 0000000..a9a2e9d
--- /dev/null
@@ -0,0 +1,318 @@
+/*******************************************************************************
+ * 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
+ *     Nick Teryaev - fix for bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=40752)
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class MessageSend extends Expression implements InvocationSite {
+       public Expression receiver ;
+       public char[] selector ;
+       public Expression[] arguments ;
+       public MethodBinding binding, codegenBinding;
+
+       public long nameSourcePosition ; //(start<<32)+end
+
+       MethodBinding syntheticAccessor;
+
+       public TypeBinding receiverType, qualifyingType;
+       
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+       flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic()).unconditionalInits();
+       if (arguments != null) {
+               int length = arguments.length;
+               for (int i = 0; i < length; i++) {
+                       flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+               }
+       }
+       ReferenceBinding[] thrownExceptions;
+       if ((thrownExceptions = binding.thrownExceptions) != NoExceptions) {
+               // must verify that exceptions potentially thrown by this expression are caught in the method
+               flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo, currentScope);
+       }
+       manageSyntheticAccessIfNecessary(currentScope, flowInfo);       
+       return flowInfo;
+}
+
+/**
+ * MessageSend code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */ 
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+       int pc = codeStream.position;
+
+       // generate receiver/enclosing instance access
+       boolean isStatic = codegenBinding.isStatic();
+       // outer access ?
+       if (!isStatic && ((bits & DepthMASK) != 0) && receiver.isImplicitThis()){
+               // outer method can be reached through emulation if implicit access
+               ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);             
+               Object[] path = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+               codeStream.generateOuterAccess(path, this, targetType, currentScope);
+       } else {
+               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);
+               }
+       }
+       // actual message invocation
+       if (syntheticAccessor == null){
+               if (isStatic){
+                       codeStream.invokestatic(codegenBinding);
+               } else {
+                       if( (receiver.isSuper()) || codegenBinding.isPrivate()){
+                               codeStream.invokespecial(codegenBinding);
+                       } else {
+                               if (codegenBinding.declaringClass.isInterface()){
+                                       codeStream.invokeinterface(codegenBinding);
+                               } else {
+                                       codeStream.invokevirtual(codegenBinding);
+                               }
+                       }
+               }
+       } else {
+               codeStream.invokestatic(syntheticAccessor);
+       }
+       // operation on the returned value
+       if (valueRequired){
+               // implicit conversion if necessary
+               codeStream.generateImplicitConversion(implicitConversion);
+       } else {
+               // pop return value if any
+               switch(binding.returnType.id){
+                       case T_long :
+                       case T_double :
+                               codeStream.pop2();
+                               break;
+                       case T_void :
+                               break;
+                       default:
+                               codeStream.pop();
+               }
+       }
+       codeStream.recordPositionsFrom(pc, (int)(this.nameSourcePosition >>> 32)); // highlight selector
+}
+public boolean isSuperAccess() {       
+       return receiver.isSuper();
+}
+public boolean isTypeAccess() {        
+       return receiver != null && receiver.isTypeReference();
+}
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){
+
+       if (!flowInfo.isReachable()) return;
+       if (binding.isPrivate()){
+
+               // depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy)           
+               if (currentScope.enclosingSourceType() != binding.declaringClass){
+               
+                       syntheticAccessor = ((SourceTypeBinding)binding.declaringClass).addSyntheticMethod(binding, isSuperAccess());
+                       currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+                       return;
+               }
+
+       } else if (receiver instanceof QualifiedSuperReference){ // qualified super
+
+               // qualified super need emulation always
+               SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)receiver).currentCompatibleType);
+               syntheticAccessor = destinationType.addSyntheticMethod(binding, isSuperAccess());
+               currentScope.problemReporter().needToEmulateMethodAccess(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);
+                       syntheticAccessor = currentCompatibleType.addSyntheticMethod(binding, isSuperAccess());
+                       currentScope.problemReporter().needToEmulateMethodAccess(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, 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()
+               && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+                               && (!receiver.isImplicitThis() || !binding.isStatic())
+                               && binding.declaringClass.id != T_Object) // no change for Object methods
+                       || !binding.declaringClass.canBeSeenBy(currentScope))) {
+
+               this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding(binding, (ReferenceBinding) this.qualifyingType);
+
+               // Post 1.4.0 target, array clone() invocations are qualified with array type 
+               // This is handled in array type #clone method binding resolution (see Scope and UpdatedMethodBinding)
+       }
+}
+
+public StringBuffer printExpression(int indent, StringBuffer output){
+       
+       if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.');
+       output.append(selector).append('(') ; //$NON-NLS-1$
+       if (arguments != null) {
+               for (int i = 0; i < arguments.length ; i ++) {  
+                       if (i > 0) output.append(", "); //$NON-NLS-1$
+                       arguments[i].printExpression(0, output);
+               }
+       }
+       return output.append(')');
+}
+
+public TypeBinding resolveType(BlockScope scope) {
+       // Answer the signature return type
+       // Base type promotion
+
+       constant = NotAConstant;
+       boolean receiverCast = false, argumentsCast = false; 
+       if (this.receiver instanceof CastExpression) {
+               this.receiver.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+               receiverCast = true;
+       }
+       this.qualifyingType = this.receiverType = receiver.resolveType(scope); 
+       if (receiverCast && this.receiverType != null) {
+                // due to change of declaring class with receiver type, only identity cast should be notified
+               if (((CastExpression)this.receiver).expression.resolvedType == this.receiverType) { 
+                                       scope.problemReporter().unnecessaryCast((CastExpression)this.receiver);         
+               }
+       }
+       // will check for null after args are resolved
+       TypeBinding[] argumentTypes = NoParameters;
+       if (arguments != null) {
+               boolean argHasError = false; // typeChecks all arguments 
+               int length = arguments.length;
+               argumentTypes = new TypeBinding[length];
+               for (int i = 0; i < length; i++){
+                       Expression argument = arguments[i];
+                       if (argument instanceof CastExpression) {
+                               argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+                               argumentsCast = true;
+                       }
+                       if ((argumentTypes[i] = argument.resolveType(scope)) == null){
+                               argHasError = true;
+                       }
+               }
+               if (argHasError) {
+                       if(receiverType instanceof ReferenceBinding) {
+                               // record any selector match, for clients who may still need hint about possible method match
+                               this.codegenBinding = this.binding = scope.findMethod((ReferenceBinding)receiverType, selector, new TypeBinding[]{}, this);
+                       }                       
+                       return null;
+               }
+       }
+       if (this.receiverType == null)
+               return null;
+
+       // base type cannot receive any message
+       if (this.receiverType.isBaseType()) {
+               scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+               return null;
+       }
+       this.codegenBinding = this.binding = 
+               receiver.isImplicitThis()
+                       ? scope.getImplicitMethod(selector, argumentTypes, this)
+                       : scope.getMethod(this.receiverType, selector, argumentTypes, this); 
+       if (!binding.isValidBinding()) {
+               if (binding.declaringClass == null) {
+                       if (this.receiverType instanceof ReferenceBinding) {
+                               binding.declaringClass = (ReferenceBinding) this.receiverType;
+                       } else { 
+                               scope.problemReporter().errorNoMethodFor(this, this.receiverType, argumentTypes);
+                               return null;
+                       }
+               }
+               scope.problemReporter().invalidMethod(this, binding);
+               // record the closest match, for clients who may still need hint about possible method match
+               if (binding instanceof ProblemMethodBinding){
+                       MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch;
+                       if (closestMatch != null) this.codegenBinding = this.binding = closestMatch;
+               }
+               return this.resolvedType = this.binding == null ? null : this.binding.returnType;
+       }
+       if (!binding.isStatic()) {
+               // the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type
+               if (receiver instanceof NameReference 
+                               && (((NameReference) receiver).bits & BindingIds.TYPE) != 0) {
+                       scope.problemReporter().mustUseAStaticMethod(this, binding);
+               }
+       } 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))) {
+                       scope.problemReporter().nonStaticAccessToStaticMethod(this, binding);
+               }
+               if (!receiver.isImplicitThis() && binding.declaringClass != receiverType) {
+                       scope.problemReporter().indirectAccessToStaticMethod(this, binding);
+               }               
+       }
+       if (arguments != null) {
+               for (int i = 0; i < arguments.length; i++) {
+                       arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+               }
+               if (argumentsCast) {
+                       CastExpression.checkNeedForArgumentCasts(scope, this.receiver, receiverType, binding, this.arguments, argumentTypes, this);
+               }
+       }
+       //-------message send that are known to fail at compile time-----------
+       if (binding.isAbstract()) {
+               if (receiver.isSuper()) {
+                       scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, binding);
+               }
+               // abstract private methods cannot occur nor abstract static............
+       }
+       if (isMethodUseDeprecated(binding, scope))
+               scope.problemReporter().deprecatedMethod(binding, this);
+
+       return this.resolvedType = binding.returnType;
+}
+public void setActualReceiverType(ReferenceBinding receiverType) {
+       this.qualifyingType = receiverType;
+}
+public void setDepth(int depth) {
+       bits &= ~DepthMASK; // flush previous depth if any
+       if (depth > 0) {
+               bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+       }
+}
+public void setFieldIndex(int depth) {
+       // ignore for here
+}
+
+public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+       if (visitor.visit(this, blockScope)) {
+               receiver.traverse(visitor, blockScope);
+               if (arguments != null) {
+                       int argumentsLength = arguments.length;
+                       for (int i = 0; i < argumentsLength; i++)
+                               arguments[i].traverse(visitor, blockScope);
+               }
+       }
+       visitor.endVisit(this, blockScope);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
new file mode 100644 (file)
index 0000000..b738665
--- /dev/null
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
+
+public class MethodDeclaration extends AbstractMethodDeclaration {
+       
+       public TypeReference returnType;
+
+       /**
+        * MethodDeclaration constructor comment.
+        */
+       public MethodDeclaration(CompilationResult compilationResult) {
+               super(compilationResult);
+       }
+
+       public void analyseCode(
+               ClassScope classScope,
+               InitializationFlowContext initializationContext,
+               FlowInfo flowInfo) {
+
+               // starting of the code analysis for methods
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       if (binding == null)
+                               return;
+                               
+                       if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
+                               if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
+                                       scope.problemReporter().unusedPrivateMethod(this);
+                               }
+                       }
+                               
+                       // 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,
+                                       this,
+                                       binding.thrownExceptions,
+                                       scope,
+                                       FlowInfo.DEAD_END);
+
+                       // propagate to statements
+                       if (statements != null) {
+                               boolean didAlreadyComplain = false;
+                               for (int i = 0, count = statements.length; i < count; i++) {
+                                       Statement stat = statements[i];
+                                       if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
+                                               flowInfo = stat.analyseCode(scope, methodContext, flowInfo);
+                                       } else {
+                                               didAlreadyComplain = true;
+                                       }
+                               }
+                       }
+                       // check for missing returning path
+                       TypeBinding returnTypeBinding = binding.returnType;
+                       if ((returnTypeBinding == VoidBinding) || isAbstract()) {
+                               this.needFreeReturn = flowInfo.isReachable();
+                       } else {
+                               if (flowInfo != FlowInfo.DEAD_END) { 
+                                       scope.problemReporter().shouldReturn(returnTypeBinding, this);
+                               }
+                       }
+                       // check unreachable catch blocks
+                       methodContext.complainIfUnusedExceptionHandlers(this);
+               } catch (AbortMethod e) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+       }
+
+       public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+
+               //fill up the method body with statement
+               if (ignoreFurtherInvestigation)
+                       return;
+               parser.parse(this, unit);
+       }
+
+       public StringBuffer printReturnType(int indent, StringBuffer output) {
+
+               if (returnType == null) return output;
+               return returnType.printExpression(0, output).append(' ');
+       }
+
+       public void resolveStatements() {
+
+               // ========= abort on fatal error =============
+               if (this.returnType != null && this.binding != null) {
+                       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);
+               }
+               
+               // 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);
+                       }
+               }
+               super.resolveStatements(); 
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               ClassScope classScope) {
+
+               if (visitor.visit(this, classScope)) {
+                       if (returnType != null)
+                               returnType.traverse(visitor, scope);
+                       if (arguments != null) {
+                               int argumentLength = arguments.length;
+                               for (int i = 0; i < argumentLength; i++)
+                                       arguments[i].traverse(visitor, scope);
+                       }
+                       if (thrownExceptions != null) {
+                               int thrownExceptionsLength = thrownExceptions.length;
+                               for (int i = 0; i < thrownExceptionsLength; i++)
+                                       thrownExceptions[i].traverse(visitor, scope);
+                       }
+                       if (statements != null) {
+                               int statementsLength = statements.length;
+                               for (int i = 0; i < statementsLength; i++)
+                                       statements[i].traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, classScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/NameReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/NameReference.java
new file mode 100644 (file)
index 0000000..98a3f30
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.lookup.*;
+
+public abstract class NameReference extends Reference implements InvocationSite, BindingIds {
+
+       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
+       //some name reference are build as name reference but
+       //only used as type reference. When it happens, instead of
+       //creating a new objet (aTypeReference) we just flag a boolean
+       //This concesion is valuable while their are cases when the NameReference
+       //will be a TypeReference (static message sends.....) and there is
+       //no changeClass in java.
+public NameReference() {
+       super();
+       bits |= TYPE | VARIABLE; // restrictiveFlag
+       
+}
+public FieldBinding fieldBinding() {
+       //this method should be sent ONLY after a check against isFieldReference()
+       //check its use doing senders.........
+
+       return (FieldBinding) binding ;
+}
+public boolean isSuperAccess() {
+       return false;
+}
+public boolean isTypeAccess() {
+       // null is acceptable when we are resolving the first part of a reference
+       return binding == null || binding instanceof ReferenceBinding;
+}
+public boolean isTypeReference() {
+       return binding instanceof ReferenceBinding;
+}
+public void setActualReceiverType(ReferenceBinding receiverType) {
+       this.actualReceiverType = receiverType;
+}
+public void setDepth(int depth) {
+       bits &= ~DepthMASK; // flush previous depth if any                      
+       if (depth > 0) {
+               bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+       }
+}
+public void setFieldIndex(int index){
+       // ignored
+}
+
+public abstract String unboundReferenceErrorName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/NullLiteral.java
new file mode 100644 (file)
index 0000000..d79b252
--- /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.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class NullLiteral extends MagicLiteral {
+
+       static final char[] source = {'n' , 'u' , 'l' , 'l'};
+
+       public NullLiteral(int s , int e) {
+
+               super(s,e);
+       }
+
+       public void computeConstant() {
+       
+               constant = NotAConstant; 
+       }
+
+       /**
+        * Code generation for the null 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.aconst_null();
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+       public TypeBinding literalType(BlockScope scope) {
+               return NullBinding;
+       }
+
+       /**
+        * 
+        */
+       public char[] source() {
+               return source;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/NumberLiteral.java
new file mode 100644 (file)
index 0000000..62bea22
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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 abstract class NumberLiteral extends Literal {
+
+       char[] source;
+       
+       public NumberLiteral(char[] token, int s, int e) {
+               
+               this(s,e) ;
+               source = token ;
+       }
+       
+       public NumberLiteral(int s, int e) {
+               super (s,e) ;
+       }
+       
+       public boolean isValidJavaStatement(){
+
+               return false ;
+       }
+       
+       public char[] source(){
+
+               return source;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
new file mode 100644 (file)
index 0000000..a544e53
--- /dev/null
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+//dedicated treatment for the ||
+public class OR_OR_Expression extends BinaryExpression {
+
+       int rightInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+
+       public OR_OR_Expression(Expression left, Expression right, int operator) {
+               super(left, right, operator);
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               Constant cst = this.left.optimizedBooleanConstant();
+               boolean isLeftOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isLeftOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+
+               if (isLeftOptimizedFalse) {
+                       // FALSE || anything
+                        // need to be careful of scenario:
+                       //              (x || y) || !z, if passing the left info to the right, it would be swapped by the !
+                       FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+                       mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
+                       mergedInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(mergedInfo);
+                       return mergedInfo;
+               }
+
+               FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
+       
+                // need to be careful of scenario:
+               //              (x || y) || !z, if passing the left info to the right, it would be swapped by the !
+               FlowInfo rightInfo = leftInfo.initsWhenFalse().unconditionalInits().copy();
+               rightInitStateIndex =
+                       currentScope.methodScope().recordInitializationStates(rightInfo);
+
+               int previousMode = rightInfo.reachMode();
+               if (isLeftOptimizedTrue){
+                       rightInfo.setReachMode(FlowInfo.UNREACHABLE); 
+               }
+               rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
+               FlowInfo falseMergedInfo = rightInfo.initsWhenFalse().copy();
+               rightInfo.setReachMode(previousMode); // reset after falseMergedInfo got extracted
+
+               FlowInfo mergedInfo = FlowInfo.conditional(
+                                       // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b; // b may not have been initialized
+                                       leftInfo.initsWhenTrue().copy().unconditionalInits().mergedWith(
+                                               rightInfo.initsWhenTrue().copy().unconditionalInits()),
+                                       falseMergedInfo);
+               mergedInitStateIndex =
+                       currentScope.methodScope().recordInitializationStates(mergedInfo);
+               return mergedInfo;
+       }
+
+       /**
+        * Code generation for a binary operation
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+               int pc = codeStream.position;
+               if (constant != Constant.NotAConstant) {
+                       // inlined value
+                       if (valueRequired)
+                               codeStream.generateConstant(constant, implicitConversion);
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               Constant cst = right.constant;
+               if (cst != NotAConstant) {
+                       // <expr> || true --> true
+                       if (cst.booleanValue() == true) {
+                               this.left.generateCode(currentScope, codeStream, false);
+                               if (valueRequired) codeStream.iconst_1();
+                       } else {
+                               // <expr>|| false --> <expr>
+                               this.left.generateCode(currentScope, codeStream, valueRequired);
+                       }
+                       if (mergedInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       }                       
+                       codeStream.generateImplicitConversion(implicitConversion);
+                       codeStream.updateLastRecordedEndPC(codeStream.position);
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               
+               Label trueLabel = new Label(codeStream), endLabel;
+               cst = left.optimizedBooleanConstant();
+               boolean leftIsConst = cst != NotAConstant;
+               boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
+
+               cst = right.optimizedBooleanConstant();
+               boolean rightIsConst = cst != NotAConstant;
+               boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
+               generateOperands : {
+                       if (leftIsConst) {
+                               left.generateCode(currentScope, codeStream, false);
+                               if (leftIsTrue) {
+                                       break generateOperands; // no need to generate right operand
+                               }
+                       } else {
+                               left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true); 
+                               // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1 
+                       }
+                       if (rightInitStateIndex != -1) {
+                               codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+                       }
+                       if (rightIsConst) {
+                               right.generateCode(currentScope, codeStream, false);
+                       } else {
+                               right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired);
+                       }
+               }
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+               /*
+                * improving code gen for such a case: boolean b = i < 0 || true since
+                * the label has never been used, we have the inlined value on the
+                * stack.
+                */
+               if (valueRequired) {
+                       if (leftIsConst && leftIsTrue) {
+                               codeStream.iconst_1();
+                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                       } else {
+                               if (rightIsConst && rightIsTrue) {
+                                       codeStream.iconst_1();
+                                       codeStream.updateLastRecordedEndPC(codeStream.position);
+                               } else {
+                                       codeStream.iconst_0();
+                               }
+                               if (trueLabel.hasForwardReferences()) {
+                                       if ((bits & ValueForReturnMASK) != 0) {
+                                               codeStream.ireturn();
+                                               trueLabel.place();
+                                               codeStream.iconst_1();
+                                       } else {
+                                               codeStream.goto_(endLabel = new Label(codeStream));
+                                               codeStream.decrStackSize(1);
+                                               trueLabel.place();
+                                               codeStream.iconst_1();
+                                               endLabel.place();
+                                       }
+                               } else {
+                                       trueLabel.place();
+                               }
+                       }
+                       codeStream.generateImplicitConversion(implicitConversion);
+                       codeStream.updateLastRecordedEndPC(codeStream.position);
+               } else {
+                       trueLabel.place();
+               }
+       }
+
+       /**
+        * Boolean operator code generation Optimized operations are: ||
+        */
+       public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+               if (constant != Constant.NotAConstant) {
+                       super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+                       return;
+               }
+
+               // <expr> || false --> <expr>
+               Constant cst = right.constant;
+               if (cst != NotAConstant && cst.booleanValue() == false) {
+                       int pc = codeStream.position;
+                       this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+                       if (mergedInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       }                       
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+       
+               cst = left.optimizedBooleanConstant();
+               boolean leftIsConst = cst != NotAConstant;
+               boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
+
+               cst = right.optimizedBooleanConstant();
+               boolean rightIsConst = cst != NotAConstant;
+               boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
+
+               // default case
+               generateOperands : {
+                       if (falseLabel == null) {
+                               if (trueLabel != null) {
+                                       // implicit falling through the FALSE case
+                                       left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, !leftIsConst); 
+                                       // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1
+                                       if (leftIsConst && leftIsTrue) {
+                                               codeStream.goto_(trueLabel);
+                                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                                               break generateOperands; // no need to generate right operand
+                                       }
+                                       if (rightInitStateIndex != -1) {
+                                               codeStream
+                                                               .addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+                                       }
+                                       right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired && !rightIsConst);
+                                       if (valueRequired && rightIsConst && rightIsTrue) {
+                                               codeStream.goto_(trueLabel);
+                                               codeStream.updateLastRecordedEndPC(codeStream.position);
+                                       }
+                               }
+                       } else {
+                               // implicit falling through the TRUE case
+                               if (trueLabel == null) {
+                                       Label internalTrueLabel = new Label(codeStream);
+                                       left.generateOptimizedBoolean(currentScope, codeStream, internalTrueLabel, null, !leftIsConst); 
+                                       // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1
+                                       if (leftIsConst && leftIsTrue) {
+                                               internalTrueLabel.place();
+                                               break generateOperands; // no need to generate right operand
+                                       }
+                                       if (rightInitStateIndex != -1) {
+                                               codeStream
+                                                               .addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+                                       }
+                                       right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired && !rightIsConst);
+                                       if (valueRequired && rightIsConst) {
+                                               if (!rightIsTrue) {
+                                                       codeStream.goto_(falseLabel);
+                                                       codeStream.updateLastRecordedEndPC(codeStream.position);
+                                               }
+                                       }
+                                       internalTrueLabel.place();
+                               } else {
+                                       // no implicit fall through TRUE/FALSE --> should never occur
+                               }
+                       }
+               }
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+       }
+       
+       public boolean isCompactableOperation() {
+               return false;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               if (visitor.visit(this, scope)) {
+                       left.traverse(visitor, scope);
+                       right.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/OperatorExpression.java
new file mode 100644 (file)
index 0000000..4574e0b
--- /dev/null
@@ -0,0 +1,1564 @@
+/*******************************************************************************
+ * 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 abstract class OperatorExpression extends Expression implements OperatorIds {
+
+       public static int[][] OperatorSignatures = new int[NumberOfTables][];
+
+       static {classInitialize();}
+
+       /**
+        * OperatorExpression constructor comment.
+        */
+       public OperatorExpression() {
+               super();
+       }
+       public static final void classInitialize() {
+               OperatorSignatures[AND] = get_AND();
+               OperatorSignatures[AND_AND] = get_AND_AND();
+               OperatorSignatures[DIVIDE] = get_DIVIDE();
+               OperatorSignatures[EQUAL_EQUAL] = get_EQUAL_EQUAL();
+               OperatorSignatures[GREATER] = get_GREATER();
+               OperatorSignatures[GREATER_EQUAL] = get_GREATER_EQUAL();
+               OperatorSignatures[LEFT_SHIFT] = get_LEFT_SHIFT();
+               OperatorSignatures[LESS] = get_LESS();
+               OperatorSignatures[LESS_EQUAL] = get_LESS_EQUAL();
+               OperatorSignatures[MINUS] = get_MINUS();
+               OperatorSignatures[MULTIPLY] = get_MULTIPLY();
+               OperatorSignatures[OR] = get_OR();
+               OperatorSignatures[OR_OR] = get_OR_OR();
+               OperatorSignatures[PLUS] = get_PLUS();
+               OperatorSignatures[REMAINDER] = get_REMAINDER();
+               OperatorSignatures[RIGHT_SHIFT] = get_RIGHT_SHIFT();
+               OperatorSignatures[UNSIGNED_RIGHT_SHIFT] = get_UNSIGNED_RIGHT_SHIFT();
+               OperatorSignatures[XOR] = get_XOR();
+       }
+
+       public static final String generateTableTestCase(){
+               //return a String which is a java method allowing to test
+               //the non zero entries of all tables
+       
+               /*
+               org.eclipse.jdt.internal.compiler.ast.
+               OperatorExpression.generateTableTestCase();
+               */
+       
+               int[] operators = new int[]{AND,AND_AND,DIVIDE,GREATER,GREATER_EQUAL,
+                               LEFT_SHIFT,LESS,LESS_EQUAL,MINUS,MULTIPLY,OR,OR_OR,PLUS,REMAINDER,
+                               RIGHT_SHIFT,UNSIGNED_RIGHT_SHIFT,XOR};
+       
+               class Decode {
+                       public  final String constant(int code){
+                               switch(code){ 
+                                       case T_boolean  : return "true"; //$NON-NLS-1$
+                                       case T_byte             : return "((byte) 3)"; //$NON-NLS-1$
+                                       case T_char             : return "'A'"; //$NON-NLS-1$
+                                       case T_double   : return "300.0d"; //$NON-NLS-1$
+                                       case T_float    : return "100.0f"; //$NON-NLS-1$
+                                       case T_int              : return "1"; //$NON-NLS-1$
+                                       case T_long             : return "7L"; //$NON-NLS-1$
+                                       case T_String   : return "\"hello-world\""; //$NON-NLS-1$
+                                       case T_null             : return "null"; //$NON-NLS-1$
+                                       case T_short    : return "((short) 5)"; //$NON-NLS-1$
+                                       case T_Object   : return "null";} //$NON-NLS-1$
+                               return "";} //$NON-NLS-1$
+       
+                       public  final String type(int code){
+                               switch(code){ 
+                                       case T_boolean  : return "z"; //$NON-NLS-1$
+                                       case T_byte             : return "b"; //$NON-NLS-1$
+                                       case T_char             : return "c"; //$NON-NLS-1$
+                                       case T_double   : return "d"; //$NON-NLS-1$
+                                       case T_float    : return "f"; //$NON-NLS-1$
+                                       case T_int              : return "i"; //$NON-NLS-1$
+                                       case T_long             : return "l"; //$NON-NLS-1$
+                                       case T_String   : return "str"; //$NON-NLS-1$
+                                       case T_null             : return "null"; //$NON-NLS-1$
+                                       case T_short    : return "s"; //$NON-NLS-1$
+                                       case T_Object   : return "obj";} //$NON-NLS-1$
+                               return "xxx";} //$NON-NLS-1$
+                       
+                       public  final String operator(int operator){
+                                       switch (operator) {
+                                       case EQUAL_EQUAL :      return "=="; //$NON-NLS-1$
+                                       case LESS_EQUAL :       return "<="; //$NON-NLS-1$
+                                       case GREATER_EQUAL :return ">="; //$NON-NLS-1$
+                                       case LEFT_SHIFT :       return "<<"; //$NON-NLS-1$
+                                       case RIGHT_SHIFT :      return ">>"; //$NON-NLS-1$
+                                       case UNSIGNED_RIGHT_SHIFT :     return ">>>"; //$NON-NLS-1$
+                                       case OR_OR :return "||"; //$NON-NLS-1$
+                                       case AND_AND :          return "&&"; //$NON-NLS-1$
+                                       case PLUS :                     return "+"; //$NON-NLS-1$
+                                       case MINUS :            return "-"; //$NON-NLS-1$
+                                       case NOT :                      return "!"; //$NON-NLS-1$
+                                       case REMAINDER :        return "%"; //$NON-NLS-1$
+                                       case XOR :                      return "^"; //$NON-NLS-1$
+                                       case AND :                      return "&"; //$NON-NLS-1$
+                                       case MULTIPLY :         return "*"; //$NON-NLS-1$
+                                       case OR :                       return "|"; //$NON-NLS-1$
+                                       case TWIDDLE :          return "~"; //$NON-NLS-1$
+                                       case DIVIDE :           return "/"; //$NON-NLS-1$
+                                       case GREATER :          return ">"; //$NON-NLS-1$
+                                       case LESS :                     return "<";     } //$NON-NLS-1$
+                               return "????";} //$NON-NLS-1$
+               }
+       
+                       
+               Decode decode = new Decode();
+               String s;
+       
+               s = "\tpublic static void binaryOperationTablesTestCase(){\n" + //$NON-NLS-1$
+       
+                       "\t\t//TC test : all binary operation (described in tables)\n"+ //$NON-NLS-1$
+                       "\t\t//method automatically generated by\n"+ //$NON-NLS-1$
+                       "\t\t//org.eclipse.jdt.internal.compiler.ast.OperatorExpression.generateTableTestCase();\n"+ //$NON-NLS-1$
+               
+                       "\t\tString str0;\t String str\t= "+decode.constant(T_String)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+                       "\t\tint i0;\t int i\t= "+decode.constant(T_int)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+                       "\t\tboolean z0;\t boolean z\t= "+decode.constant(T_boolean)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+                       "\t\tchar c0; \t char  c\t= "+decode.constant(T_char)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+                       "\t\tfloat f0; \t float f\t= "+decode.constant(T_float)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+                       "\t\tdouble d0;\t double d\t= "+decode.constant(T_double)+";\n"+ //$NON-NLS-1$ //$NON-NLS-2$
+                       "\t\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$
+                       "\n"; //$NON-NLS-1$
+       
+               int error = 0;          
+               for (int i=0; i < operators.length; i++)
+               {       int operator = operators[i];
+                       for (int left=0; left<16;left++)
+                       for (int right=0; right<16;right++)
+                       {       int result = (OperatorSignatures[operator][(left<<4)+right]) & 0x0000F;
+                               if (result != T_undefined)
+       
+                                       //1/ First regular computation then 2/ comparaison
+                                       //with a compile time constant (generated by the compiler)
+                                       //      z0 = s >= s;
+                                       //      if ( z0 != (((short) 5) >= ((short) 5)))
+                                       //              System.out.println(155);
+       
+                               {       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$
+                                       s += begin      +decode.type(result)+"0"+test //$NON-NLS-1$
+                                                               +decode.constant(left)+" " //$NON-NLS-1$
+                                                               +decode.operator(operator)+" " //$NON-NLS-1$
+                                                               +decode.constant(right)+"))\n"; //$NON-NLS-1$
+                                       s += "\t\t\tSystem.out.println("+ (++error) +");\n"; //$NON-NLS-1$ //$NON-NLS-2$
+                                                                       
+                                       }
+                               }
+                       }
+                       
+               return s += "\n\t\tSystem.out.println(\"binary tables test : done\");}"; //$NON-NLS-1$
+       }
+
+       public static final int[] get_AND(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               int[] table  = new int[16*16];
+               
+               //      table[(T_undefined<<4)+T_undefined]     = T_undefined;
+               //      table[(T_undefined<<4)+T_byte]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_long]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_short]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_void]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_String]                = T_undefined;
+               //      table[(T_undefined<<4)+T_Object]                = T_undefined;
+               //      table[(T_undefined<<4)+T_double]                = T_undefined;
+               //      table[(T_undefined<<4)+T_float]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_boolean]               = T_undefined;
+               //      table[(T_undefined<<4)+T_char]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_int]                   = T_undefined;
+               //      table[(T_undefined<<4)+T_null]                  = T_undefined;
+               
+               //      table[(T_byte<<4)+T_undefined]  = T_undefined;
+               table[(T_byte<<4)+T_byte]               = (Byte2Int<<12) +(Byte2Int<<4) +T_int;
+               table[(T_byte<<4)+T_long]               = (Byte2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_byte<<4)+T_short]              = (Byte2Int<<12) +(Short2Int<<4)+T_int;
+               //      table[(T_byte<<4)+T_void]               = T_undefined;
+               //      table[(T_byte<<4)+T_String]     = T_undefined;
+               //      table[(T_byte<<4)+T_Object]     = T_undefined;
+               //      table[(T_byte<<4)+T_double]     = T_undefined;
+               //      table[(T_byte<<4)+T_float]              = T_undefined;
+               //      table[(T_byte<<4)+T_boolean]    = T_undefined;
+               table[(T_byte<<4)+T_char]               = (Byte2Int<<12) +(Char2Int<<4) +T_int;
+               table[(T_byte<<4)+T_int]                = (Byte2Int<<12) +(Int2Int<<4)  +T_int;
+               //      table[(T_byte<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_long<<4)+T_undefined]  = T_undefined;
+               table[(T_long<<4)+T_byte]               = (Long2Long<<12)+(Byte2Long<<4)+T_long;
+               table[(T_long<<4)+T_long]               = (Long2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_long<<4)+T_short]              = (Long2Long<<12)+(Short2Long<<4)+T_long;
+               //      table[(T_long<<4)+T_void]               = T_undefined;
+               //      table[(T_long<<4)+T_String]     = T_undefined;
+               //      table[(T_long<<4)+T_Object]     = T_undefined;
+               //      table[(T_long<<4)+T_double]     = T_undefined;
+               //      table[(T_long<<4)+T_float]              = T_undefined;
+               //      table[(T_long<<4)+T_boolean]    = T_undefined;
+               table[(T_long<<4)+T_char]               = (Long2Long<<12)+(Char2Long<<4)+T_long;
+               table[(T_long<<4)+T_int]                = (Long2Long<<12)+(Int2Long<<4)+T_long;
+               //      table[(T_long<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_short<<4)+T_undefined]         = T_undefined;
+               table[(T_short<<4)+T_byte]                      = (Short2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_short<<4)+T_long]                      = (Short2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_short<<4)+T_short]             = (Short2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_short<<4)+T_void]                      = T_undefined;
+               //      table[(T_short<<4)+T_String]            = T_undefined;
+               //      table[(T_short<<4)+T_Object]            = T_undefined;
+               //      table[(T_short<<4)+T_double]            = T_undefined;
+               //      table[(T_short<<4)+T_float]             = T_undefined;
+               //      table[(T_short<<4)+T_boolean]           = T_undefined;
+               table[(T_short<<4)+T_char]                      = (Short2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_short<<4)+T_int]                       = (Short2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_short<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_void<<4)+T_undefined]  = T_undefined;
+               //      table[(T_void<<4)+T_byte]               = T_undefined;
+               //      table[(T_void<<4)+T_long]               = T_undefined;
+               //      table[(T_void<<4)+T_short]              = T_undefined;
+               //      table[(T_void<<4)+T_void]               = T_undefined;
+               //      table[(T_void<<4)+T_String]     = T_undefined;
+               //      table[(T_void<<4)+T_Object]     = T_undefined;
+               //      table[(T_void<<4)+T_double]     = T_undefined;
+               //      table[(T_void<<4)+T_float]              = T_undefined;
+               //      table[(T_void<<4)+T_boolean]    = T_undefined;
+               //      table[(T_void<<4)+T_char]               = T_undefined;
+               //      table[(T_void<<4)+T_int]                = T_undefined;
+               //      table[(T_void<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_String<<4)+T_undefined]        = T_undefined;
+               //      table[(T_String<<4)+T_byte]             = T_undefined;
+               //      table[(T_String<<4)+T_long]             = T_undefined;
+               //      table[(T_String<<4)+T_short]            = T_undefined;
+               //      table[(T_String<<4)+T_void]             = T_undefined;
+               //      table[(T_String<<4)+T_String]           = T_undefined;
+               //      table[(T_String<<4)+T_Object]           = T_undefined;
+               //      table[(T_String<<4)+T_double]           = T_undefined;
+               //      table[(T_String<<4)+T_float]            = T_undefined;
+               //      table[(T_String<<4)+T_boolean]          = T_undefined;
+               //      table[(T_String<<4)+T_char]             = T_undefined;
+               //      table[(T_String<<4)+T_int]                      = T_undefined;
+               //      table[(T_String<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_Object<<4)+T_undefined]        = T_undefined;
+               //      table[(T_Object<<4)+T_byte]             = T_undefined;
+               //      table[(T_Object<<4)+T_long]             = T_undefined;
+               //      table[(T_Object<<4)+T_short]            = T_undefined;
+               //      table[(T_Object<<4)+T_void]             = T_undefined;
+               //      table[(T_Object<<4)+T_String]           = T_undefined;
+               //      table[(T_Object<<4)+T_Object]           = T_undefined;
+               //      table[(T_Object<<4)+T_double]           = T_undefined;
+               //      table[(T_Object<<4)+T_float]            = T_undefined;
+               //      table[(T_Object<<4)+T_boolean]          = T_undefined;
+               //      table[(T_Object<<4)+T_char]             = T_undefined;
+               //      table[(T_Object<<4)+T_int]                      = T_undefined;
+               //      table[(T_Object<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_double<<4)+T_undefined]        = T_undefined;
+               //      table[(T_double<<4)+T_byte]             = T_undefined;
+               //      table[(T_double<<4)+T_long]             = T_undefined;
+               //      table[(T_double<<4)+T_short]            = T_undefined;
+               //      table[(T_double<<4)+T_void]             = T_undefined;
+               //      table[(T_double<<4)+T_String]           = T_undefined;
+               //      table[(T_double<<4)+T_Object]           = T_undefined;
+               //      table[(T_double<<4)+T_double]           = T_undefined;
+               //      table[(T_double<<4)+T_float]            = T_undefined;
+               //      table[(T_double<<4)+T_boolean]          = T_undefined;
+               //      table[(T_double<<4)+T_char]             = T_undefined;
+               //      table[(T_double<<4)+T_int]                      = T_undefined;
+               //      table[(T_double<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_float<<4)+T_undefined]         = T_undefined;
+               //      table[(T_float<<4)+T_byte]                      = T_undefined;
+               //      table[(T_float<<4)+T_long]                      = T_undefined;
+               //      table[(T_float<<4)+T_short]             = T_undefined;
+               //      table[(T_float<<4)+T_void]                      = T_undefined;
+               //      table[(T_float<<4)+T_String]            = T_undefined;
+               //      table[(T_float<<4)+T_Object]            = T_undefined;
+               //      table[(T_float<<4)+T_double]            = T_undefined;
+               //      table[(T_float<<4)+T_float]             = T_undefined;
+               //      table[(T_float<<4)+T_boolean]           = T_undefined;
+               //      table[(T_float<<4)+T_char]                      = T_undefined;
+               //      table[(T_float<<4)+T_int]                       = T_undefined;
+               //      table[(T_float<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_boolean<<4)+T_undefined]               = T_undefined;
+               //      table[(T_boolean<<4)+T_byte]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_long]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_short]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_void]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_String]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_Object]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_double]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_float]                   = T_undefined;
+               table[(T_boolean<<4)+T_boolean]                 = (Boolean2Boolean << 12)+(Boolean2Boolean << 4)+T_boolean;
+               //      table[(T_boolean<<4)+T_char]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_int]                     = T_undefined;
+               //      table[(T_boolean<<4)+T_null]                    = T_undefined;
+                       
+               //      table[(T_char<<4)+T_undefined]          = T_undefined;
+               table[(T_char<<4)+T_byte]                       = (Char2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_char<<4)+T_long]                       = (Char2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_char<<4)+T_short]                      = (Char2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_char<<4)+T_void]                       = T_undefined;
+               //      table[(T_char<<4)+T_String]             = T_undefined;
+               //      table[(T_char<<4)+T_Object]             = T_undefined;
+               //      table[(T_char<<4)+T_double]             = T_undefined;
+               //      table[(T_char<<4)+T_float]                      = T_undefined;
+               //      table[(T_char<<4)+T_boolean]            = T_undefined;
+               table[(T_char<<4)+T_char]                       = (Char2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_char<<4)+T_int]                        = (Char2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_char<<4)+T_null]                       = T_undefined;
+                       
+               //      table[(T_int<<4)+T_undefined]   = T_undefined;
+               table[(T_int<<4)+T_byte]                = (Int2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_int<<4)+T_long]                = (Int2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_int<<4)+T_short]               = (Int2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_int<<4)+T_void]                = T_undefined;
+               //      table[(T_int<<4)+T_String]              = T_undefined;
+               //      table[(T_int<<4)+T_Object]              = T_undefined;
+               //      table[(T_int<<4)+T_double]              = T_undefined;
+               //      table[(T_int<<4)+T_float]               = T_undefined;
+               //      table[(T_int<<4)+T_boolean]     = T_undefined;
+               table[(T_int<<4)+T_char]                = (Int2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_int<<4)+T_int]                 = (Int2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_int<<4)+T_null]                = T_undefined;
+               
+               //      table[(T_null<<4)+T_undefined]          = T_undefined;
+               //      table[(T_null<<4)+T_byte]                       = T_undefined;
+               //      table[(T_null<<4)+T_long]                       = T_undefined;
+               //      table[(T_null<<4)+T_short]                      = T_undefined;
+               //      table[(T_null<<4)+T_void]                       = T_undefined;
+               //      table[(T_null<<4)+T_String]             = T_undefined;
+               //      table[(T_null<<4)+T_Object]             = T_undefined;
+               //      table[(T_null<<4)+T_double]             = T_undefined;
+               //      table[(T_null<<4)+T_float]                      = T_undefined;
+               //      table[(T_null<<4)+T_boolean]            = T_undefined;
+               //      table[(T_null<<4)+T_char]                       = T_undefined;
+               //      table[(T_null<<4)+T_int]                        = T_undefined;
+               //      table[(T_null<<4)+T_null]                       = T_undefined;
+       
+               return table;
+       }
+
+       public static final int[] get_AND_AND(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               int[] table  = new int[16*16];
+               
+               //     table[(T_undefined<<4)+T_undefined]              = T_undefined;
+               //     table[(T_undefined<<4)+T_byte]                   = T_undefined;
+               //     table[(T_undefined<<4)+T_long]                   = T_undefined;
+               //     table[(T_undefined<<4)+T_short]                  = T_undefined;
+               //     table[(T_undefined<<4)+T_void]                   = T_undefined;
+               //     table[(T_undefined<<4)+T_String]                 = T_undefined;
+               //     table[(T_undefined<<4)+T_Object]                 = T_undefined;
+               //     table[(T_undefined<<4)+T_double]                 = T_undefined;
+               //     table[(T_undefined<<4)+T_float]                  = T_undefined;
+               //     table[(T_undefined<<4)+T_boolean]                = T_undefined;
+               //     table[(T_undefined<<4)+T_char]                   = T_undefined;
+               //     table[(T_undefined<<4)+T_int]                    = T_undefined;
+               //     table[(T_undefined<<4)+T_null]                   = T_undefined;
+                       
+               //     table[(T_byte<<4)+T_undefined]   = T_undefined;
+               //     table[(T_byte<<4)+T_byte]                = T_undefined;
+               //     table[(T_byte<<4)+T_long]                = T_undefined;
+               //     table[(T_byte<<4)+T_short]               = T_undefined;
+               //     table[(T_byte<<4)+T_void]                = T_undefined;
+               //     table[(T_byte<<4)+T_String]              = T_undefined;
+               //     table[(T_byte<<4)+T_Object]              = T_undefined;
+               //     table[(T_byte<<4)+T_double]              = T_undefined;
+               //     table[(T_byte<<4)+T_float]               = T_undefined;
+               //     table[(T_byte<<4)+T_boolean]     = T_undefined;
+               //     table[(T_byte<<4)+T_char]                = T_undefined;
+               //     table[(T_byte<<4)+T_int]                 = T_undefined;
+               //     table[(T_byte<<4)+T_null]                = T_undefined;
+               
+               //     table[(T_long<<4)+T_undefined]   = T_undefined;
+               //     table[(T_long<<4)+T_byte]                = T_undefined;
+               //     table[(T_long<<4)+T_long]                = T_undefined;
+               //     table[(T_long<<4)+T_short]               = T_undefined;
+               //     table[(T_long<<4)+T_void]                = T_undefined;
+               //     table[(T_long<<4)+T_String]              = T_undefined;
+               //     table[(T_long<<4)+T_Object]              = T_undefined;
+               //     table[(T_long<<4)+T_double]              = T_undefined;
+               //     table[(T_long<<4)+T_float]               = T_undefined;
+               //     table[(T_long<<4)+T_boolean]     = T_undefined;
+               //     table[(T_long<<4)+T_char]                = T_undefined;
+               //     table[(T_long<<4)+T_int]                 = T_undefined;
+               //     table[(T_long<<4)+T_null]                = T_undefined;
+               
+               //     table[(T_short<<4)+T_undefined]  = T_undefined;
+               //     table[(T_short<<4)+T_byte]               = T_undefined;
+               //     table[(T_short<<4)+T_long]               = T_undefined;
+               //     table[(T_short<<4)+T_short]              = T_undefined;
+               //     table[(T_short<<4)+T_void]               = T_undefined;
+               //     table[(T_short<<4)+T_String]     = T_undefined;
+               //     table[(T_short<<4)+T_Object]     = T_undefined;
+               //     table[(T_short<<4)+T_double]     = T_undefined;
+               //     table[(T_short<<4)+T_float]              = T_undefined;
+               //     table[(T_short<<4)+T_boolean]    = T_undefined;
+               //     table[(T_short<<4)+T_char]               = T_undefined;
+               //     table[(T_short<<4)+T_int]                = T_undefined;
+               //     table[(T_short<<4)+T_null]               = T_undefined;
+               
+               //     table[(T_void<<4)+T_undefined]   = T_undefined;
+               //     table[(T_void<<4)+T_byte]                = T_undefined;
+               //     table[(T_void<<4)+T_long]                = T_undefined;
+               //     table[(T_void<<4)+T_short]               = T_undefined;
+               //     table[(T_void<<4)+T_void]                = T_undefined;
+               //     table[(T_void<<4)+T_String]      = T_undefined;
+               //     table[(T_void<<4)+T_Object]      = T_undefined;
+               //     table[(T_void<<4)+T_double]      = T_undefined;
+               //     table[(T_void<<4)+T_float]               = T_undefined;
+               //     table[(T_void<<4)+T_boolean]     = T_undefined;
+               //     table[(T_void<<4)+T_char]                = T_undefined;
+               //     table[(T_void<<4)+T_int]                 = T_undefined;
+               //     table[(T_void<<4)+T_null]                = T_undefined;
+               
+               //     table[(T_String<<4)+T_undefined]         = T_undefined;
+               //     table[(T_String<<4)+T_byte]              = T_undefined;
+               //     table[(T_String<<4)+T_long]              = T_undefined;
+               //     table[(T_String<<4)+T_short]             = T_undefined;
+               //     table[(T_String<<4)+T_void]              = T_undefined;
+               //     table[(T_String<<4)+T_String]            = T_undefined;
+               //     table[(T_String<<4)+T_Object]            = T_undefined;
+               //     table[(T_String<<4)+T_double]            = T_undefined;
+               //     table[(T_String<<4)+T_float]             = T_undefined;
+               //     table[(T_String<<4)+T_boolean]           = T_undefined;
+               //     table[(T_String<<4)+T_char]              = T_undefined;
+               //     table[(T_String<<4)+T_int]                       = T_undefined;
+               //     table[(T_String<<4)+T_null]              = T_undefined;
+               
+               //     table[(T_Object<<4)+T_undefined]         = T_undefined;
+               //     table[(T_Object<<4)+T_byte]              = T_undefined;
+               //     table[(T_Object<<4)+T_long]              = T_undefined;
+               //     table[(T_Object<<4)+T_short]             = T_undefined;
+               //     table[(T_Object<<4)+T_void]              = T_undefined;
+               //     table[(T_Object<<4)+T_String]            = T_undefined;
+               //     table[(T_Object<<4)+T_Object]            = T_undefined;
+               //     table[(T_Object<<4)+T_double]            = T_undefined;
+               //     table[(T_Object<<4)+T_float]             = T_undefined;
+               //     table[(T_Object<<4)+T_boolean]           = T_undefined;
+               //     table[(T_Object<<4)+T_char]              = T_undefined;
+               //     table[(T_Object<<4)+T_int]                       = T_undefined;
+               //     table[(T_Object<<4)+T_null]              = T_undefined;
+               
+               //     table[(T_double<<4)+T_undefined]         = T_undefined;
+               //     table[(T_double<<4)+T_byte]              = T_undefined;
+               //     table[(T_double<<4)+T_long]              = T_undefined;
+               //     table[(T_double<<4)+T_short]             = T_undefined;
+               //     table[(T_double<<4)+T_void]              = T_undefined;
+               //     table[(T_double<<4)+T_String]            = T_undefined;
+               //     table[(T_double<<4)+T_Object]            = T_undefined;
+               //     table[(T_double<<4)+T_double]            = T_undefined;
+               //     table[(T_double<<4)+T_float]             = T_undefined;
+               //     table[(T_double<<4)+T_boolean]           = T_undefined;
+               //     table[(T_double<<4)+T_char]              = T_undefined;
+               //     table[(T_double<<4)+T_int]                       = T_undefined;
+               //     table[(T_double<<4)+T_null]              = T_undefined;
+               
+               //     table[(T_float<<4)+T_undefined]  = T_undefined;
+               //     table[(T_float<<4)+T_byte]                       = T_undefined;
+               //     table[(T_float<<4)+T_long]                       = T_undefined;
+               //     table[(T_float<<4)+T_short]              = T_undefined;
+               //     table[(T_float<<4)+T_void]                       = T_undefined;
+               //     table[(T_float<<4)+T_String]             = T_undefined;
+               //     table[(T_float<<4)+T_Object]             = T_undefined;
+               //     table[(T_float<<4)+T_double]             = T_undefined;
+               //     table[(T_float<<4)+T_float]              = T_undefined;
+               //     table[(T_float<<4)+T_boolean]            = T_undefined;
+               //     table[(T_float<<4)+T_char]                       = T_undefined;
+               //     table[(T_float<<4)+T_int]                        = T_undefined;
+               //     table[(T_float<<4)+T_null]                       = T_undefined;
+               
+               //     table[(T_boolean<<4)+T_undefined]                = T_undefined;
+               //     table[(T_boolean<<4)+T_byte]                     = T_undefined;
+               //     table[(T_boolean<<4)+T_long]                     = T_undefined;
+               //     table[(T_boolean<<4)+T_short]                    = T_undefined;
+               //     table[(T_boolean<<4)+T_void]                     = T_undefined;
+               //     table[(T_boolean<<4)+T_String]                   = T_undefined;
+               //     table[(T_boolean<<4)+T_Object]                   = T_undefined;
+               //     table[(T_boolean<<4)+T_double]                   = T_undefined;
+               //     table[(T_boolean<<4)+T_float]                    = T_undefined;
+          table[(T_boolean<<4)+T_boolean]              = (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean;
+               //     table[(T_boolean<<4)+T_char]                     = T_undefined;
+               //     table[(T_boolean<<4)+T_int]                      = T_undefined;
+               //     table[(T_boolean<<4)+T_null]                     = T_undefined;
+                       
+               //     table[(T_char<<4)+T_undefined]           = T_undefined;
+               //     table[(T_char<<4)+T_byte]                        = T_undefined;
+               //     table[(T_char<<4)+T_long]                        = T_undefined;
+               //     table[(T_char<<4)+T_short]                       = T_undefined;
+               //     table[(T_char<<4)+T_void]                        = T_undefined;
+               //     table[(T_char<<4)+T_String]              = T_undefined;
+               //     table[(T_char<<4)+T_Object]              = T_undefined;
+               //     table[(T_char<<4)+T_double]              = T_undefined;
+               //     table[(T_char<<4)+T_float]                       = T_undefined;
+               //     table[(T_char<<4)+T_boolean]             = T_undefined;
+               //     table[(T_char<<4)+T_char]                        = T_undefined;
+               //     table[(T_char<<4)+T_int]                         = T_undefined;
+               //     table[(T_char<<4)+T_null]                        = T_undefined;
+                       
+               //     table[(T_int<<4)+T_undefined]    = T_undefined;
+               //     table[(T_int<<4)+T_byte]                 = T_undefined;
+               //     table[(T_int<<4)+T_long]                 = T_undefined;
+               //     table[(T_int<<4)+T_short]                = T_undefined;
+               //     table[(T_int<<4)+T_void]                 = T_undefined;
+               //     table[(T_int<<4)+T_String]               = T_undefined;
+               //     table[(T_int<<4)+T_Object]               = T_undefined;
+               //     table[(T_int<<4)+T_double]               = T_undefined;
+               //     table[(T_int<<4)+T_float]                = T_undefined;
+               //     table[(T_int<<4)+T_boolean]      = T_undefined;
+               //     table[(T_int<<4)+T_char]                 = T_undefined;
+               //     table[(T_int<<4)+T_int]          = T_undefined;
+               //     table[(T_int<<4)+T_null]                 = T_undefined;
+               
+               //     table[(T_null<<4)+T_undefined]           = T_undefined;
+               //     table[(T_null<<4)+T_byte]                        = T_undefined;
+               //     table[(T_null<<4)+T_long]                        = T_undefined;
+               //     table[(T_null<<4)+T_short]                       = T_undefined;
+               //     table[(T_null<<4)+T_void]                        = T_undefined;
+               //     table[(T_null<<4)+T_String]              = T_undefined;
+               //     table[(T_null<<4)+T_Object]              = T_undefined;
+               //     table[(T_null<<4)+T_double]              = T_undefined;
+               //     table[(T_null<<4)+T_float]                       = T_undefined;
+               //     table[(T_null<<4)+T_boolean]             = T_undefined;
+               //     table[(T_null<<4)+T_char]                        = T_undefined;
+               //     table[(T_null<<4)+T_int]                         = T_undefined;
+               //     table[(T_null<<4)+T_null]                        = T_undefined;
+               return table;
+       }
+
+       public static final int[] get_DIVIDE(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               
+       //      int[] table  = new int[16*16];
+               
+               return get_MINUS();
+       }
+
+       public static final int[] get_EQUAL_EQUAL(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               int[] table  = new int[16*16];
+               
+               //      table[(T_undefined<<4)+T_undefined]     = T_undefined;
+               //      table[(T_undefined<<4)+T_byte]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_long]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_short]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_void]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_String]                = T_undefined;
+               //      table[(T_undefined<<4)+T_Object]                = T_undefined;
+               //      table[(T_undefined<<4)+T_double]                = T_undefined;
+               //      table[(T_undefined<<4)+T_float]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_boolean]               = T_undefined;
+               //      table[(T_undefined<<4)+T_char]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_int]                   = T_undefined;
+               //      table[(T_undefined<<4)+T_null]                  = T_undefined;
+               
+               //      table[(T_byte<<4)+T_undefined]  = T_undefined;
+               table[(T_byte<<4)+T_byte]               = (Byte2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_byte<<4)+T_long]               = (Byte2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_byte<<4)+T_short]              = (Byte2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_byte<<4)+T_void]               = T_undefined;
+               //      table[(T_byte<<4)+T_String]     = T_undefined;
+               //      table[(T_byte<<4)+T_Object]     = T_undefined;
+               table[(T_byte<<4)+T_double]     = (Byte2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_byte<<4)+T_float]              = (Byte2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_byte<<4)+T_boolean]    = T_undefined;
+               table[(T_byte<<4)+T_char]               = (Byte2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_byte<<4)+T_int]                = (Byte2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_byte<<4)+T_null]               = T_undefined;
+       
+               //      table[(T_long<<4)+T_undefined]  = T_undefined;
+               table[(T_long<<4)+T_byte]               = (Long2Long<<12)+(Byte2Long<<4)+T_boolean;
+               table[(T_long<<4)+T_long]               = (Long2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_long<<4)+T_short]              = (Long2Long<<12)+(Short2Long<<4)+T_boolean;
+               //      table[(T_long<<4)+T_void]               = T_undefined;
+               //      table[(T_long<<4)+T_String]     = T_undefined;
+               //      table[(T_long<<4)+T_Object]     = T_undefined;
+               table[(T_long<<4)+T_double]     = (Long2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_long<<4)+T_float]              = (Long2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_long<<4)+T_boolean]    = T_undefined;
+               table[(T_long<<4)+T_char]               = (Long2Long<<12)+(Char2Long<<4)+T_boolean;
+               table[(T_long<<4)+T_int]                = (Long2Long<<12)+(Int2Long<<4)+T_boolean;
+               //      table[(T_long<<4)+T_null]               = T_undefined;
+       
+               //      table[(T_short<<4)+T_undefined]         = T_undefined;
+               table[(T_short<<4)+T_byte]                      = (Short2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_short<<4)+T_long]                      = (Short2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_short<<4)+T_short]             = (Short2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_short<<4)+T_void]                      = T_undefined;
+               //      table[(T_short<<4)+T_String]            = T_undefined;
+               //      table[(T_short<<4)+T_Object]            = T_undefined;
+               table[(T_short<<4)+T_double]            = (Short2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_short<<4)+T_float]             = (Short2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_short<<4)+T_boolean]           = T_undefined;
+               table[(T_short<<4)+T_char]                      = (Short2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_short<<4)+T_int]                       = (Short2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_short<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_void<<4)+T_undefined]  = T_undefined;
+               //      table[(T_void<<4)+T_byte]               = T_undefined;
+               //      table[(T_void<<4)+T_long]               = T_undefined;
+               //      table[(T_void<<4)+T_short]              = T_undefined;
+               //      table[(T_void<<4)+T_void]               = T_undefined;
+               //      table[(T_void<<4)+T_String]     = T_undefined;
+               //      table[(T_void<<4)+T_Object]     = T_undefined;
+               //      table[(T_void<<4)+T_double]     = T_undefined;
+               //      table[(T_void<<4)+T_float]              = T_undefined;
+               //      table[(T_void<<4)+T_boolean]    = T_undefined;
+               //      table[(T_void<<4)+T_char]               = T_undefined;
+               //      table[(T_void<<4)+T_int]                = T_undefined;
+               //      table[(T_void<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_String<<4)+T_undefined]        = T_undefined; 
+               //      table[(T_String<<4)+T_byte]             = T_undefined;
+               //      table[(T_String<<4)+T_long]             = T_undefined; 
+               //      table[(T_String<<4)+T_short]            = T_undefined;
+               //      table[(T_String<<4)+T_void]             = T_undefined;
+               table[(T_String<<4)+T_String]           = /*String2Object                 String2Object*/
+                                                                                         (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
+               table[(T_String<<4)+T_Object]           = /*String2Object                 Object2Object*/
+                                                                                         (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean;
+               //      table[(T_String<<4)+T_double]           = T_undefined;
+               //      table[(T_String<<4)+T_float]            = T_undefined; 
+               //      table[(T_String<<4)+T_boolean]          = T_undefined;
+               //      table[(T_String<<4)+T_char]             = T_undefined;
+               //      table[(T_String<<4)+T_int]                      = T_undefined;
+               table[(T_String<<4)+T_null]             = /*Object2String                null2Object */
+                                                                                         (T_Object<<16)+(T_String<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+       
+               //      table[(T_Object<<4)+T_undefined]        = T_undefined;
+               //      table[(T_Object<<4)+T_byte]             = T_undefined;
+               //      table[(T_Object<<4)+T_long]             = T_undefined;
+               //      table[(T_Object<<4)+T_short]            = T_undefined;
+               //      table[(T_Object<<4)+T_void]             = T_undefined;
+               table[(T_Object<<4)+T_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_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_double<<4)+T_undefined]        = T_undefined;
+               table[(T_double<<4)+T_byte]             = (Double2Double<<12)+(Byte2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_long]             = (Double2Double<<12)+(Long2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_short]            = (Double2Double<<12)+(Short2Double<<4)+T_boolean;
+               //      table[(T_double<<4)+T_void]             = T_undefined;
+               //      table[(T_double<<4)+T_String]           = T_undefined;
+               //      table[(T_double<<4)+T_Object]           = T_undefined;
+               table[(T_double<<4)+T_double]           = (Double2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_float]            = (Double2Double<<12)+(Float2Double<<4)+T_boolean;
+               //      table[(T_double<<4)+T_boolean]          = T_undefined;
+               table[(T_double<<4)+T_char]             = (Double2Double<<12)+(Char2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_int]                      = (Double2Double<<12)+(Int2Double<<4)+T_boolean;
+               //      table[(T_double<<4)+T_null]             = T_undefined;
+       
+               //      table[(T_float<<4)+T_undefined]         = T_undefined;
+               table[(T_float<<4)+T_byte]                      = (Float2Float<<12)+(Byte2Float<<4)+T_boolean;
+               table[(T_float<<4)+T_long]                      = (Float2Float<<12)+(Long2Float<<4)+T_boolean;
+               table[(T_float<<4)+T_short]             = (Float2Float<<12)+(Short2Float<<4)+T_boolean;
+               //      table[(T_float<<4)+T_void]                      = T_undefined;
+               //      table[(T_float<<4)+T_String]            = T_undefined;
+               //      table[(T_float<<4)+T_Object]            = T_undefined;
+               table[(T_float<<4)+T_double]            = (Float2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_float<<4)+T_float]             = (Float2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_float<<4)+T_boolean]           = T_undefined;
+               table[(T_float<<4)+T_char]                      = (Float2Float<<12)+(Char2Float<<4)+T_boolean;
+               table[(T_float<<4)+T_int]                       = (Float2Float<<12)+(Int2Float<<4)+T_boolean;
+               //      table[(T_float<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_boolean<<4)+T_undefined]               = T_undefined;
+               //      table[(T_boolean<<4)+T_byte]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_long]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_short]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_void]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_String]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_Object]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_double]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_float]                   = T_undefined;
+               table[(T_boolean<<4)+T_boolean]                 = (Boolean2Boolean<<12)+(Boolean2Boolean<<4)+T_boolean;
+               //      table[(T_boolean<<4)+T_char]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_int]                     = T_undefined;
+               //      table[(T_boolean<<4)+T_null]                    = T_undefined;
+                       
+               //      table[(T_char<<4)+T_undefined]          = T_undefined;
+               table[(T_char<<4)+T_byte]                       = (Char2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_char<<4)+T_long]                       = (Char2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_char<<4)+T_short]                      = (Char2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_char<<4)+T_void]                       = T_undefined;
+               //      table[(T_char<<4)+T_String]             = T_undefined;
+               //      table[(T_char<<4)+T_Object]             = T_undefined;
+               table[(T_char<<4)+T_double]             = (Char2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_char<<4)+T_float]                      = (Char2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_char<<4)+T_boolean]            = T_undefined;
+               table[(T_char<<4)+T_char]                       = (Char2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_char<<4)+T_int]                        = (Char2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_char<<4)+T_null]                       = T_undefined;
+                       
+               //      table[(T_int<<4)+T_undefined]   = T_undefined;
+               table[(T_int<<4)+T_byte]                = (Int2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_int<<4)+T_long]                = (Int2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_int<<4)+T_short]               = (Int2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_int<<4)+T_void]                = T_undefined;
+               //      table[(T_int<<4)+T_String]              = T_undefined;
+               //      table[(T_int<<4)+T_Object]              = T_undefined;
+               table[(T_int<<4)+T_double]              = (Int2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_int<<4)+T_float]               = (Int2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_int<<4)+T_boolean]     = T_undefined;
+               table[(T_int<<4)+T_char]                = (Int2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_int<<4)+T_int]                 = (Int2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_int<<4)+T_null]                = T_undefined;
+               
+               //      table[(T_null<<4)+T_undefined]          = T_undefined;
+               //      table[(T_null<<4)+T_byte]                       = T_undefined;
+               //      table[(T_null<<4)+T_long]                       = T_undefined;
+               //      table[(T_null<<4)+T_short]                      = T_undefined;
+               //      table[(T_null<<4)+T_void]                       = T_undefined;
+               table[(T_null<<4)+T_String]             = /*null2Object                 String2Object*/
+                                                                                         (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_String<<4)+T_boolean;
+               table[(T_null<<4)+T_Object]             = /*null2Object                 Object2Object*/
+                                                                                         (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_Object<<4)+T_boolean; 
+               //      table[(T_null<<4)+T_double]             = T_undefined;
+               //      table[(T_null<<4)+T_float]                      = T_undefined;
+               //      table[(T_null<<4)+T_boolean]            = T_undefined;
+               //      table[(T_null<<4)+T_char]                       = T_undefined;
+               //      table[(T_null<<4)+T_int]                        = T_undefined;
+               table[(T_null<<4)+T_null]                       = /*null2Object                 null2Object*/
+                                                                                         (T_Object<<16)+(T_null<<12)+(T_Object<<8)+(T_null<<4)+T_boolean;
+               return table;
+       }
+
+       public static final int[] get_GREATER(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_LESS();
+       }
+
+       public static final int[] get_GREATER_EQUAL(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_LESS();
+       }
+
+       public static final int[] get_LEFT_SHIFT(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               int[] table  = new int[16*16];
+               
+               //      table[(T_undefined<<4)+T_undefined]     = T_undefined;
+               //      table[(T_undefined<<4)+T_byte]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_long]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_short]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_void]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_String]                = T_undefined;
+               //      table[(T_undefined<<4)+T_Object]                = T_undefined;
+               //      table[(T_undefined<<4)+T_double]                = T_undefined;
+               //      table[(T_undefined<<4)+T_float]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_boolean]               = T_undefined;
+               //      table[(T_undefined<<4)+T_char]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_int]                   = T_undefined;
+               //      table[(T_undefined<<4)+T_null]                  = T_undefined;
+                       
+               //      table[(T_byte<<4)+T_undefined]  = T_undefined;
+               table[(T_byte<<4)+T_byte]               = (Byte2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_byte<<4)+T_long]               = (Byte2Int<<12)+(Long2Int<<4)+T_int;
+               table[(T_byte<<4)+T_short]              = (Byte2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_byte<<4)+T_void]               = T_undefined;
+               //      table[(T_byte<<4)+T_String]     = T_undefined;
+               //      table[(T_byte<<4)+T_Object]     = T_undefined;
+               //      table[(T_byte<<4)+T_double]     = T_undefined;
+               //      table[(T_byte<<4)+T_float]              = T_undefined;
+               //      table[(T_byte<<4)+T_boolean]    = T_undefined;
+               table[(T_byte<<4)+T_char]               = (Byte2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_byte<<4)+T_int]                = (Byte2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_byte<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_long<<4)+T_undefined]  = T_undefined;
+               table[(T_long<<4)+T_byte]               = (Long2Long<<12)+(Byte2Int<<4)+T_long;
+               table[(T_long<<4)+T_long]               = (Long2Long<<12)+(Long2Int<<4)+T_long;
+               table[(T_long<<4)+T_short]              = (Long2Long<<12)+(Short2Int<<4)+T_long;
+               //      table[(T_long<<4)+T_void]               = T_undefined;
+               //      table[(T_long<<4)+T_String]     = T_undefined;
+               //      table[(T_long<<4)+T_Object]     = T_undefined;
+               //      table[(T_long<<4)+T_double]     = T_undefined;
+               //      table[(T_long<<4)+T_float]              = T_undefined;
+               //      table[(T_long<<4)+T_boolean]    = T_undefined;
+               table[(T_long<<4)+T_char]               = (Long2Long<<12)+(Char2Int<<4)+T_long;
+               table[(T_long<<4)+T_int]                = (Long2Long<<12)+(Int2Int<<4)+T_long;
+               //      table[(T_long<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_short<<4)+T_undefined]         = T_undefined;
+               table[(T_short<<4)+T_byte]                      = (Short2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_short<<4)+T_long]                      = (Short2Int<<12)+(Long2Int<<4)+T_int;
+               table[(T_short<<4)+T_short]             = (Short2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_short<<4)+T_void]                      = T_undefined;
+               //      table[(T_short<<4)+T_String]            = T_undefined;
+               //      table[(T_short<<4)+T_Object]            = T_undefined;
+               //      table[(T_short<<4)+T_double]            = T_undefined;
+               //      table[(T_short<<4)+T_float]             = T_undefined;
+               //      table[(T_short<<4)+T_boolean]           = T_undefined;
+               table[(T_short<<4)+T_char]                      = (Short2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_short<<4)+T_int]                       = (Short2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_short<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_void<<4)+T_undefined]  = T_undefined;
+               //      table[(T_void<<4)+T_byte]               = T_undefined;
+               //      table[(T_void<<4)+T_long]               = T_undefined;
+               //      table[(T_void<<4)+T_short]              = T_undefined;
+               //      table[(T_void<<4)+T_void]               = T_undefined;
+               //      table[(T_void<<4)+T_String]     = T_undefined;
+               //      table[(T_void<<4)+T_Object]     = T_undefined;
+               //      table[(T_void<<4)+T_double]     = T_undefined;
+               //      table[(T_void<<4)+T_float]              = T_undefined;
+               //      table[(T_void<<4)+T_boolean]    = T_undefined;
+               //      table[(T_void<<4)+T_char]               = T_undefined;
+               //      table[(T_void<<4)+T_int]                = T_undefined;
+               //      table[(T_void<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_String<<4)+T_undefined]        = T_undefined;
+               //      table[(T_String<<4)+T_byte]             = T_undefined;
+               //      table[(T_String<<4)+T_long]             = T_undefined;
+               //      table[(T_String<<4)+T_short]            = T_undefined;
+               //      table[(T_String<<4)+T_void]             = T_undefined;
+               //      table[(T_String<<4)+T_String]           = T_undefined;
+               //      table[(T_String<<4)+T_Object]           = T_undefined;
+               //      table[(T_String<<4)+T_double]           = T_undefined;
+               //      table[(T_String<<4)+T_float]            = T_undefined;
+               //      table[(T_String<<4)+T_boolean]          = T_undefined;
+               //      table[(T_String<<4)+T_char]             = T_undefined;
+               //      table[(T_String<<4)+T_int]                      = T_undefined;
+               //      table[(T_String<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_Object<<4)+T_undefined]        = T_undefined;
+               //      table[(T_Object<<4)+T_byte]             = T_undefined;
+               //      table[(T_Object<<4)+T_long]             = T_undefined;
+               //      table[(T_Object<<4)+T_short]            = T_undefined;
+               //      table[(T_Object<<4)+T_void]             = T_undefined;
+               //      table[(T_Object<<4)+T_String]           = T_undefined;
+               //      table[(T_Object<<4)+T_Object]           = T_undefined;
+               //      table[(T_Object<<4)+T_double]           = T_undefined;
+               //      table[(T_Object<<4)+T_float]            = T_undefined;
+               //      table[(T_Object<<4)+T_boolean]          = T_undefined;
+               //      table[(T_Object<<4)+T_char]             = T_undefined;
+               //      table[(T_Object<<4)+T_int]                      = T_undefined;
+               //      table[(T_Object<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_double<<4)+T_undefined]        = T_undefined;
+               //      table[(T_double<<4)+T_byte]             = T_undefined;
+               //      table[(T_double<<4)+T_long]             = T_undefined;
+               //      table[(T_double<<4)+T_short]            = T_undefined;
+               //      table[(T_double<<4)+T_void]             = T_undefined;
+               //      table[(T_double<<4)+T_String]           = T_undefined;
+               //      table[(T_double<<4)+T_Object]           = T_undefined;
+               //      table[(T_double<<4)+T_double]           = T_undefined;
+               //      table[(T_double<<4)+T_float]            = T_undefined;
+               //      table[(T_double<<4)+T_boolean]          = T_undefined;
+               //      table[(T_double<<4)+T_char]             = T_undefined;
+               //      table[(T_double<<4)+T_int]                      = T_undefined;
+               //      table[(T_double<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_float<<4)+T_undefined]         = T_undefined;
+               //      table[(T_float<<4)+T_byte]                      = T_undefined;
+               //      table[(T_float<<4)+T_long]                      = T_undefined;
+               //      table[(T_float<<4)+T_short]             = T_undefined;
+               //      table[(T_float<<4)+T_void]                      = T_undefined;
+               //      table[(T_float<<4)+T_String]            = T_undefined;
+               //      table[(T_float<<4)+T_Object]            = T_undefined;
+               //      table[(T_float<<4)+T_double]            = T_undefined;
+               //      table[(T_float<<4)+T_float]             = T_undefined;
+               //      table[(T_float<<4)+T_boolean]           = T_undefined;
+               //      table[(T_float<<4)+T_char]                      = T_undefined;
+               //      table[(T_float<<4)+T_int]                       = T_undefined;
+               //      table[(T_float<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_boolean<<4)+T_undefined]               = T_undefined;
+               //      table[(T_boolean<<4)+T_byte]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_long]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_short]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_void]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_String]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_Object]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_double]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_float]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_boolean]                 = T_undefined;
+               //      table[(T_boolean<<4)+T_char]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_int]                     = T_undefined;
+               //      table[(T_boolean<<4)+T_null]                    = T_undefined;
+                       
+               //      table[(T_char<<4)+T_undefined]          = T_undefined;
+               table[(T_char<<4)+T_byte]                       = (Char2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_char<<4)+T_long]                       = (Char2Int<<12)+(Long2Int<<4)+T_int;
+               table[(T_char<<4)+T_short]                      = (Char2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_char<<4)+T_void]                       = T_undefined;
+               //      table[(T_char<<4)+T_String]             = T_undefined;
+               //      table[(T_char<<4)+T_Object]             = T_undefined;
+               //      table[(T_char<<4)+T_double]             = T_undefined;
+               //      table[(T_char<<4)+T_float]                      = T_undefined;
+               //      table[(T_char<<4)+T_boolean]            = T_undefined;
+               table[(T_char<<4)+T_char]                       = (Char2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_char<<4)+T_int]                        = (Char2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_char<<4)+T_null]                       = T_undefined;
+               
+               //      table[(T_int<<4)+T_undefined]   = T_undefined;
+               table[(T_int<<4)+T_byte]                = (Int2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_int<<4)+T_long]                = (Int2Int<<12)+(Long2Int<<4)+T_int;
+               table[(T_int<<4)+T_short]               = (Int2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_int<<4)+T_void]                = T_undefined;
+               //      table[(T_int<<4)+T_String]              = T_undefined;
+               //      table[(T_int<<4)+T_Object]              = T_undefined;
+               //      table[(T_int<<4)+T_double]              = T_undefined;
+               //      table[(T_int<<4)+T_float]               = T_undefined;
+               //      table[(T_int<<4)+T_boolean]     = T_undefined;
+               table[(T_int<<4)+T_char]                = (Int2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_int<<4)+T_int]                 = (Int2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_int<<4)+T_null]                = T_undefined;
+               
+               //      table[(T_null<<4)+T_undefined]          = T_undefined;
+               //      table[(T_null<<4)+T_byte]                       = T_undefined;
+               //      table[(T_null<<4)+T_long]                       = T_undefined;
+               //      table[(T_null<<4)+T_short]                      = T_undefined;
+               //      table[(T_null<<4)+T_void]                       = T_undefined;
+               //      table[(T_null<<4)+T_String]             = T_undefined;
+               //      table[(T_null<<4)+T_Object]             = T_undefined;
+               //      table[(T_null<<4)+T_double]             = T_undefined;
+               //      table[(T_null<<4)+T_float]                      = T_undefined;
+               //      table[(T_null<<4)+T_boolean]            = T_undefined;
+               //      table[(T_null<<4)+T_char]                       = T_undefined;
+               //      table[(T_null<<4)+T_int]                        = T_undefined;
+               //      table[(T_null<<4)+T_null]                       = T_undefined;
+       
+               return table;
+       }
+
+       public static final int[] get_LESS(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               int[] table  = new int[16*16];
+               
+               //      table[(T_undefined<<4)+T_undefined]     = T_undefined;
+               //      table[(T_undefined<<4)+T_byte]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_long]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_short]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_void]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_String]                = T_undefined;
+               //      table[(T_undefined<<4)+T_Object]                = T_undefined;
+               //      table[(T_undefined<<4)+T_double]                = T_undefined;
+               //      table[(T_undefined<<4)+T_float]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_boolean]               = T_undefined;
+               //      table[(T_undefined<<4)+T_char]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_int]                   = T_undefined;
+               //      table[(T_undefined<<4)+T_null]                  = T_undefined;
+               
+               //      table[(T_byte<<4)+T_undefined]  = T_undefined;
+               table[(T_byte<<4)+T_byte]               = (Byte2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_byte<<4)+T_long]               = (Byte2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_byte<<4)+T_short]              = (Byte2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_byte<<4)+T_void]               = T_undefined;
+               //      table[(T_byte<<4)+T_String]     = T_undefined;
+               //      table[(T_byte<<4)+T_Object]     = T_undefined;
+               table[(T_byte<<4)+T_double]     = (Byte2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_byte<<4)+T_float]              = (Byte2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_byte<<4)+T_boolean]    = T_undefined;
+               table[(T_byte<<4)+T_char]               = (Byte2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_byte<<4)+T_int]                = (Byte2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_byte<<4)+T_null]               = T_undefined;
+       
+               //      table[(T_long<<4)+T_undefined]  = T_undefined;
+               table[(T_long<<4)+T_byte]               = (Long2Long<<12)+(Byte2Long<<4)+T_boolean;
+               table[(T_long<<4)+T_long]               = (Long2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_long<<4)+T_short]              = (Long2Long<<12)+(Short2Long<<4)+T_boolean;
+               //      table[(T_long<<4)+T_void]               = T_undefined;
+               //      table[(T_long<<4)+T_String]     = T_undefined;
+               //      table[(T_long<<4)+T_Object]     = T_undefined;
+               table[(T_long<<4)+T_double]     = (Long2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_long<<4)+T_float]              = (Long2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_long<<4)+T_boolean]    = T_undefined;
+               table[(T_long<<4)+T_char]               = (Long2Long<<12)+(Char2Long<<4)+T_boolean;
+               table[(T_long<<4)+T_int]                = (Long2Long<<12)+(Int2Long<<4)+T_boolean;
+               //      table[(T_long<<4)+T_null]               = T_undefined;
+       
+               //      table[(T_short<<4)+T_undefined]         = T_undefined;
+               table[(T_short<<4)+T_byte]                      = (Short2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_short<<4)+T_long]                      = (Short2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_short<<4)+T_short]             = (Short2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_short<<4)+T_void]                      = T_undefined;
+               //      table[(T_short<<4)+T_String]            = T_undefined;
+               //      table[(T_short<<4)+T_Object]            = T_undefined;
+               table[(T_short<<4)+T_double]            = (Short2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_short<<4)+T_float]             = (Short2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_short<<4)+T_boolean]           = T_undefined;
+               table[(T_short<<4)+T_char]                      = (Short2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_short<<4)+T_int]                       = (Short2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_short<<4)+T_null]                      = T_undefined;
+       
+               //      table[(T_void<<4)+T_undefined]  = T_undefined;
+               //      table[(T_void<<4)+T_byte]               = T_undefined;
+               //      table[(T_void<<4)+T_long]               = T_undefined;
+               //      table[(T_void<<4)+T_short]              = T_undefined;
+               //      table[(T_void<<4)+T_void]               = T_undefined;
+               //      table[(T_void<<4)+T_String]     = T_undefined;
+               //      table[(T_void<<4)+T_Object]     = T_undefined;
+               //      table[(T_void<<4)+T_double]     = T_undefined;
+               //      table[(T_void<<4)+T_float]              = T_undefined;
+               //      table[(T_void<<4)+T_boolean]    = T_undefined;
+               //      table[(T_void<<4)+T_char]               = T_undefined;
+               //      table[(T_void<<4)+T_int]                = T_undefined;
+               //      table[(T_void<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_String<<4)+T_undefined]        = T_undefined; 
+               //      table[(T_String<<4)+T_byte]             = T_undefined;
+               //      table[(T_String<<4)+T_long]             = T_undefined; 
+               //      table[(T_String<<4)+T_short]            = T_undefined;
+               //      table[(T_String<<4)+T_void]             = T_undefined;
+               //      table[(T_String<<4)+T_String]           = T_undefined;
+               //      table[(T_String<<4)+T_Object]           = T_undefined;
+               //      table[(T_String<<4)+T_double]           = T_undefined;
+               //      table[(T_String<<4)+T_float]            = T_undefined; 
+               //      table[(T_String<<4)+T_boolean]          = T_undefined;
+               //      table[(T_String<<4)+T_char]             = T_undefined;
+               //      table[(T_String<<4)+T_int]                      = T_undefined;
+               //      table[(T_String<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_Object<<4)+T_undefined]        = T_undefined;
+               //      table[(T_Object<<4)+T_byte]             = T_undefined;
+               //      table[(T_Object<<4)+T_long]             = T_undefined;
+               //      table[(T_Object<<4)+T_short]            = T_undefined;
+               //      table[(T_Object<<4)+T_void]             = T_undefined;
+               //      table[(T_Object<<4)+T_String]           = T_undefined;
+               //      table[(T_Object<<4)+T_Object]           = T_undefined;
+               //      table[(T_Object<<4)+T_double]           = T_undefined;
+               //      table[(T_Object<<4)+T_float]            = T_undefined;
+               //      table[(T_Object<<4)+T_boolean]          = T_undefined;
+               //      table[(T_Object<<4)+T_char]             = T_undefined;
+               //      table[(T_Object<<4)+T_int]                      = T_undefined;
+               //      table[(T_Object<<4)+T_null]             = T_undefined;
+       
+               //      table[(T_double<<4)+T_undefined]        = T_undefined;
+               table[(T_double<<4)+T_byte]             = (Double2Double<<12)+(Byte2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_long]             = (Double2Double<<12)+(Long2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_short]            = (Double2Double<<12)+(Short2Double<<4)+T_boolean;
+               //      table[(T_double<<4)+T_void]             = T_undefined;
+               //      table[(T_double<<4)+T_String]           = T_undefined;
+               //      table[(T_double<<4)+T_Object]           = T_undefined;
+               table[(T_double<<4)+T_double]           = (Double2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_float]            = (Double2Double<<12)+(Float2Double<<4)+T_boolean;
+               //      table[(T_double<<4)+T_boolean]          = T_undefined;
+               table[(T_double<<4)+T_char]             = (Double2Double<<12)+(Char2Double<<4)+T_boolean;
+               table[(T_double<<4)+T_int]                      = (Double2Double<<12)+(Int2Double<<4)+T_boolean;
+               //      table[(T_double<<4)+T_null]             = T_undefined;
+       
+               //      table[(T_float<<4)+T_undefined]         = T_undefined;
+               table[(T_float<<4)+T_byte]                      = (Float2Float<<12)+(Byte2Float<<4)+T_boolean;
+               table[(T_float<<4)+T_long]                      = (Float2Float<<12)+(Long2Float<<4)+T_boolean;
+               table[(T_float<<4)+T_short]             = (Float2Float<<12)+(Short2Float<<4)+T_boolean;
+               //      table[(T_float<<4)+T_void]                      = T_undefined;
+               //      table[(T_float<<4)+T_String]            = T_undefined;
+               //      table[(T_float<<4)+T_Object]            = T_undefined;
+               table[(T_float<<4)+T_double]            = (Float2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_float<<4)+T_float]             = (Float2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_float<<4)+T_boolean]           = T_undefined;
+               table[(T_float<<4)+T_char]                      = (Float2Float<<12)+(Char2Float<<4)+T_boolean;
+               table[(T_float<<4)+T_int]                       = (Float2Float<<12)+(Int2Float<<4)+T_boolean;
+               //      table[(T_float<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_boolean<<4)+T_undefined]               = T_undefined;
+               //      table[(T_boolean<<4)+T_byte]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_long]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_short]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_void]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_String]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_Object]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_double]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_float]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_boolean]                 = T_undefined;
+               //      table[(T_boolean<<4)+T_char]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_int]                     = T_undefined;
+               //      table[(T_boolean<<4)+T_null]                    = T_undefined;
+                       
+               //      table[(T_char<<4)+T_undefined]          = T_undefined;
+               table[(T_char<<4)+T_byte]                       = (Char2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_char<<4)+T_long]                       = (Char2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_char<<4)+T_short]                      = (Char2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_char<<4)+T_void]                       = T_undefined;
+               //      table[(T_char<<4)+T_String]             = T_undefined;
+               //      table[(T_char<<4)+T_Object]             = T_undefined;
+               table[(T_char<<4)+T_double]             = (Char2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_char<<4)+T_float]                      = (Char2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_char<<4)+T_boolean]            = T_undefined;
+               table[(T_char<<4)+T_char]                       = (Char2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_char<<4)+T_int]                        = (Char2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_char<<4)+T_null]                       = T_undefined;
+               
+               //      table[(T_int<<4)+T_undefined]   = T_undefined;
+               table[(T_int<<4)+T_byte]                = (Int2Int<<12)+(Byte2Int<<4)+T_boolean;
+               table[(T_int<<4)+T_long]                = (Int2Long<<12)+(Long2Long<<4)+T_boolean;
+               table[(T_int<<4)+T_short]               = (Int2Int<<12)+(Short2Int<<4)+T_boolean;
+               //      table[(T_int<<4)+T_void]                = T_undefined;
+               //      table[(T_int<<4)+T_String]              = T_undefined;
+               //      table[(T_int<<4)+T_Object]              = T_undefined;
+               table[(T_int<<4)+T_double]              = (Int2Double<<12)+(Double2Double<<4)+T_boolean;
+               table[(T_int<<4)+T_float]               = (Int2Float<<12)+(Float2Float<<4)+T_boolean;
+               //      table[(T_int<<4)+T_boolean]     = T_undefined;
+               table[(T_int<<4)+T_char]                = (Int2Int<<12)+(Char2Int<<4)+T_boolean;
+               table[(T_int<<4)+T_int]                 = (Int2Int<<12)+(Int2Int<<4)+T_boolean;
+               //      table[(T_int<<4)+T_null]                = T_undefined;
+               
+               //      table[(T_null<<4)+T_undefined]          = T_undefined;
+               //      table[(T_null<<4)+T_byte]                       = T_undefined;
+               //      table[(T_null<<4)+T_long]                       = T_undefined;
+               //      table[(T_null<<4)+T_short]                      = T_undefined;
+               //      table[(T_null<<4)+T_void]                       = T_undefined;
+               //      table[(T_null<<4)+T_String]             = T_undefined;
+               //      table[(T_null<<4)+T_Object]             = T_undefined;
+               //      table[(T_null<<4)+T_double]             = T_undefined;
+               //      table[(T_null<<4)+T_float]                      = T_undefined;
+               //      table[(T_null<<4)+T_boolean]            = T_undefined;
+               //      table[(T_null<<4)+T_char]                       = T_undefined;
+               //      table[(T_null<<4)+T_int]                        = T_undefined;
+               //      table[(T_null<<4)+T_null]                       = T_undefined;
+       
+               return table;
+       }
+
+       public static final int[] get_LESS_EQUAL(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_LESS();
+       }
+
+       public static final int[] get_MINUS(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               int[] table  = new int[16*16];
+       
+               table = (int[]) get_PLUS().clone();
+
+               // customization        
+               table[(T_String<<4)+T_byte]             = T_undefined;
+               table[(T_String<<4)+T_long]             = T_undefined;
+               table[(T_String<<4)+T_short]            = T_undefined;
+               table[(T_String<<4)+T_void]             = T_undefined;
+               table[(T_String<<4)+T_String]           = T_undefined;
+               table[(T_String<<4)+T_Object]           = T_undefined;
+               table[(T_String<<4)+T_double]           = T_undefined;
+               table[(T_String<<4)+T_float]            = T_undefined;
+               table[(T_String<<4)+T_boolean]          = T_undefined;
+               table[(T_String<<4)+T_char]             = T_undefined;
+               table[(T_String<<4)+T_int]                      = T_undefined;
+               table[(T_String<<4)+T_null]             = T_undefined;
+               
+               table[(T_byte<<4)       +T_String]              = T_undefined;
+               table[(T_long<<4)       +T_String]              = T_undefined;
+               table[(T_short<<4)      +T_String]              = T_undefined;
+               table[(T_void<<4)       +T_String]              = T_undefined;
+               table[(T_Object<<4)     +T_String]              = T_undefined;
+               table[(T_double<<4)     +T_String]              = T_undefined;
+               table[(T_float<<4)      +T_String]              = T_undefined;
+               table[(T_boolean<<4)+T_String]          = T_undefined;
+               table[(T_char<<4)       +T_String]              = T_undefined;
+               table[(T_int<<4)        +T_String]              = T_undefined;
+               table[(T_null<<4)       +T_String]              = T_undefined;
+               
+               table[(T_null<<4)       +T_null]                = T_undefined;
+       
+               return table;
+       }
+
+       public static final int[] get_MULTIPLY(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_MINUS();
+       }
+
+       public static final int[] get_OR(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               
+               //      int[] table  = new int[16*16];
+               return get_AND();
+       }
+
+       public static final int[] get_OR_OR(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_AND_AND();
+       }
+
+       public static final int[] get_PLUS(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               int[] table  = new int[16*16];
+               
+               //      table[(T_undefined<<4)+T_undefined]     = T_undefined;
+               //      table[(T_undefined<<4)+T_byte]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_long]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_short]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_void]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_String]                = T_undefined;
+               //      table[(T_undefined<<4)+T_Object]                = T_undefined;
+               //      table[(T_undefined<<4)+T_double]                = T_undefined;
+               //      table[(T_undefined<<4)+T_float]                 = T_undefined;
+               //      table[(T_undefined<<4)+T_boolean]               = T_undefined;
+               //      table[(T_undefined<<4)+T_char]                  = T_undefined;
+               //      table[(T_undefined<<4)+T_int]                   = T_undefined;
+               //      table[(T_undefined<<4)+T_null]                  = T_undefined;
+                       
+               //      table[(T_byte<<4)+T_undefined]  = T_undefined;
+               table[(T_byte<<4)+T_byte]               = (Byte2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_byte<<4)+T_long]               = (Byte2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_byte<<4)+T_short]              = (Byte2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_byte<<4)+T_void]               = T_undefined;
+               table[(T_byte<<4)+T_String]     = (Byte2Byte<<12)+(String2String<<4)+T_String;
+               //      table[(T_byte<<4)+T_Object]     = T_undefined;
+               table[(T_byte<<4)+T_double]     = (Byte2Double<<12)+(Double2Double<<4)+T_double;
+               table[(T_byte<<4)+T_float]              = (Byte2Float<<12)+(Float2Float<<4)+T_float;
+               //      table[(T_byte<<4)+T_boolean]    = T_undefined;
+               table[(T_byte<<4)+T_char]               = (Byte2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_byte<<4)+T_int]                = (Byte2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_byte<<4)+T_null]               = T_undefined;
+       
+               //      table[(T_long<<4)+T_undefined]  = T_undefined;
+               table[(T_long<<4)+T_byte]               = (Long2Long<<12)+(Byte2Long<<4)+T_long;
+               table[(T_long<<4)+T_long]               = (Long2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_long<<4)+T_short]              = (Long2Long<<12)+(Short2Long<<4)+T_long;
+               //      table[(T_long<<4)+T_void]               = T_undefined;
+               table[(T_long<<4)+T_String]     = (Long2Long<<12)+(String2String<<4)+T_String;
+               //      table[(T_long<<4)+T_Object]     = T_undefined;
+               table[(T_long<<4)+T_double]     = (Long2Double<<12)+(Double2Double<<4)+T_double;
+               table[(T_long<<4)+T_float]              = (Long2Float<<12)+(Float2Float<<4)+T_float;
+               //      table[(T_long<<4)+T_boolean]    = T_undefined;
+               table[(T_long<<4)+T_char]               = (Long2Long<<12)+(Char2Long<<4)+T_long;
+               table[(T_long<<4)+T_int]                = (Long2Long<<12)+(Int2Long<<4)+T_long; 
+               //      table[(T_long<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_short<<4)+T_undefined]         = T_undefined;
+               table[(T_short<<4)+T_byte]                      = (Short2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_short<<4)+T_long]                      = (Short2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_short<<4)+T_short]             = (Short2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_short<<4)+T_void]                      = T_undefined;
+               table[(T_short<<4)+T_String]            = (Short2Short<<12)+(String2String<<4)+T_String;
+               //      table[(T_short<<4)+T_Object]            = T_undefined;
+               table[(T_short<<4)+T_double]            = (Short2Double<<12)+(Double2Double<<4)+T_double;
+               table[(T_short<<4)+T_float]             = (Short2Float<<12)+(Float2Float<<4)+T_float;
+               //      table[(T_short<<4)+T_boolean]           = T_undefined;
+               table[(T_short<<4)+T_char]                      = (Short2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_short<<4)+T_int]                       = (Short2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_short<<4)+T_null]                      = T_undefined;
+       
+               //      table[(T_void<<4)+T_undefined]  = T_undefined;
+               //      table[(T_void<<4)+T_byte]               = T_undefined;
+               //      table[(T_void<<4)+T_long]               = T_undefined;
+               //      table[(T_void<<4)+T_short]              = T_undefined;
+               //      table[(T_void<<4)+T_void]               = T_undefined;
+               //      table[(T_void<<4)+T_String]     = T_undefined;
+               //      table[(T_void<<4)+T_Object]     = T_undefined;
+               //      table[(T_void<<4)+T_double]     = T_undefined;
+               //      table[(T_void<<4)+T_float]              = T_undefined;
+               //      table[(T_void<<4)+T_boolean]    = T_undefined;
+               //      table[(T_void<<4)+T_char]               = T_undefined;
+               //      table[(T_void<<4)+T_int]                = T_undefined;
+               //      table[(T_void<<4)+T_null]               = T_undefined;
+               
+               //      table[(T_String<<4)+T_undefined]        = T_undefined; 
+               table[(T_String<<4)+T_byte]             = (String2String<<12)+(Byte2Byte<<4)+T_String;
+               table[(T_String<<4)+T_long]             = (String2String<<12)+(Long2Long<<4)+T_String; 
+               table[(T_String<<4)+T_short]            = (String2String<<12)+(Short2Short<<4)+T_String;
+               //      table[(T_String<<4)+T_void]             = T_undefined;
+               table[(T_String<<4)+T_String]           = (String2String<<12)+(String2String<<4)+T_String;
+               table[(T_String<<4)+T_Object]           = (String2String<<12)+(Object2Object<<4)+T_String;
+               table[(T_String<<4)+T_double]           = (String2String<<12)+(Double2Double<<4)+T_String;
+               table[(T_String<<4)+T_float]            = (String2String<<12)+(Float2Float<<4)+T_String; 
+               table[(T_String<<4)+T_boolean]          = (String2String<<12)+(Boolean2Boolean<<4)+T_String;
+               table[(T_String<<4)+T_char]             = (String2String<<12)+(Char2Char<<4)+T_String;
+               table[(T_String<<4)+T_int]                      = (String2String<<12)+(Int2Int<<4)+T_String;
+               table[(T_String<<4)+T_null]             = (String2String<<12)+(T_null<<8)+(T_null<<4)+T_String;
+       
+               //      table[(T_Object<<4)+T_undefined]        = T_undefined;
+               //      table[(T_Object<<4)+T_byte]             = T_undefined;
+               //      table[(T_Object<<4)+T_long]             = T_undefined;
+               //      table[(T_Object<<4)+T_short]            = T_undefined;
+               //      table[(T_Object<<4)+T_void]             = T_undefined;
+               table[(T_Object<<4)+T_String]           = (Object2Object<<12)+(String2String<<4)+T_String;
+               //      table[(T_Object<<4)+T_Object]           = T_undefined;
+               //      table[(T_Object<<4)+T_double]           = T_undefined;
+               //      table[(T_Object<<4)+T_float]            = T_undefined;
+               //      table[(T_Object<<4)+T_boolean]          = T_undefined;
+               //      table[(T_Object<<4)+T_char]             = T_undefined;
+               //      table[(T_Object<<4)+T_int]                      = T_undefined;
+               //      table[(T_Object<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_double<<4)+T_undefined]        = T_undefined;
+               table[(T_double<<4)+T_byte]             = (Double2Double<<12)+(Byte2Double<<4)+T_double;
+               table[(T_double<<4)+T_long]             = (Double2Double<<12)+(Long2Double<<4)+T_double;
+               table[(T_double<<4)+T_short]            = (Double2Double<<12)+(Short2Double<<4)+T_double; 
+               //      table[(T_double<<4)+T_void]             = T_undefined;
+               table[(T_double<<4)+T_String]           = (Double2Double<<12)+(String2String<<4)+T_String;
+               //      table[(T_double<<4)+T_Object]           = T_undefined;
+               table[(T_double<<4)+T_double]           = (Double2Double<<12)+(Double2Double<<4)+T_double;
+               table[(T_double<<4)+T_float]            = (Double2Double<<12)+(Float2Double<<4)+T_double; 
+               //      table[(T_double<<4)+T_boolean]          = T_undefined;
+               table[(T_double<<4)+T_char]             = (Double2Double<<12)+(Char2Double<<4)+T_double; 
+               table[(T_double<<4)+T_int]                      = (Double2Double<<12)+(Int2Double<<4)+T_double; 
+               //      table[(T_double<<4)+T_null]             = T_undefined;
+               
+               //      table[(T_float<<4)+T_undefined]         = T_undefined;
+               table[(T_float<<4)+T_byte]                      = (Float2Float<<12)+(Byte2Float<<4)+T_float;
+               table[(T_float<<4)+T_long]                      = (Float2Float<<12)+(Long2Float<<4)+T_float;
+               table[(T_float<<4)+T_short]             = (Float2Float<<12)+(Short2Float<<4)+T_float;
+               //      table[(T_float<<4)+T_void]                      = T_undefined;
+               table[(T_float<<4)+T_String]            = (Float2Float<<12)+(String2String<<4)+T_String;
+               //      table[(T_float<<4)+T_Object]            = T_undefined;
+               table[(T_float<<4)+T_double]            = (Float2Double<<12)+(Double2Double<<4)+T_double;
+               table[(T_float<<4)+T_float]             = (Float2Float<<12)+(Float2Float<<4)+T_float;
+               //      table[(T_float<<4)+T_boolean]           = T_undefined;
+               table[(T_float<<4)+T_char]                      = (Float2Float<<12)+(Char2Float<<4)+T_float;
+               table[(T_float<<4)+T_int]                       = (Float2Float<<12)+(Int2Float<<4)+T_float;
+               //      table[(T_float<<4)+T_null]                      = T_undefined;
+               
+               //      table[(T_boolean<<4)+T_undefined]               = T_undefined;
+               //      table[(T_boolean<<4)+T_byte]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_long]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_short]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_void]                    = T_undefined;
+               table[(T_boolean<<4)+T_String]                  = (Boolean2Boolean<<12)+(String2String<<4)+T_String;
+               //      table[(T_boolean<<4)+T_Object]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_double]                  = T_undefined;
+               //      table[(T_boolean<<4)+T_float]                   = T_undefined;
+               //      table[(T_boolean<<4)+T_boolean]                 = T_undefined;
+               //      table[(T_boolean<<4)+T_char]                    = T_undefined;
+               //      table[(T_boolean<<4)+T_int]                     = T_undefined;
+               //      table[(T_boolean<<4)+T_null]                    = T_undefined;
+               
+               //      table[(T_char<<4)+T_undefined]          = T_undefined;
+               table[(T_char<<4)+T_byte]                       = (Char2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_char<<4)+T_long]                       = (Char2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_char<<4)+T_short]                      = (Char2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_char<<4)+T_void]                       = T_undefined;
+               table[(T_char<<4)+T_String]             = (Char2Char<<12)+(String2String<<4)+T_String;
+               //      table[(T_char<<4)+T_Object]             = T_undefined;
+               table[(T_char<<4)+T_double]             = (Char2Double<<12)+(Double2Double<<4)+T_double;
+               table[(T_char<<4)+T_float]                      = (Char2Float<<12)+(Float2Float<<4)+T_float;
+               //      table[(T_char<<4)+T_boolean]            = T_undefined;
+               table[(T_char<<4)+T_char]                       = (Char2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_char<<4)+T_int]                        = (Char2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_char<<4)+T_null]                       = T_undefined;
+               
+               //      table[(T_int<<4)+T_undefined]   = T_undefined;
+               table[(T_int<<4)+T_byte]                = (Int2Int<<12)+(Byte2Int<<4)+T_int;
+               table[(T_int<<4)+T_long]                = (Int2Long<<12)+(Long2Long<<4)+T_long;
+               table[(T_int<<4)+T_short]               = (Int2Int<<12)+(Short2Int<<4)+T_int;
+               //      table[(T_int<<4)+T_void]                = T_undefined;
+               table[(T_int<<4)+T_String]              = (Int2Int<<12)+(String2String<<4)+T_String;
+               //      table[(T_int<<4)+T_Object]              = T_undefined;
+               table[(T_int<<4)+T_double]              = (Int2Double<<12)+(Double2Double<<4)+T_double;
+               table[(T_int<<4)+T_float]               = (Int2Float<<12)+(Float2Float<<4)+T_float;
+               //      table[(T_int<<4)+T_boolean]     = T_undefined;
+               table[(T_int<<4)+T_char]                = (Int2Int<<12)+(Char2Int<<4)+T_int;
+               table[(T_int<<4)+T_int]                 = (Int2Int<<12)+(Int2Int<<4)+T_int;
+               //      table[(T_int<<4)+T_null]                = T_undefined;
+       
+               //      table[(T_null<<4)+T_undefined]          = T_undefined;
+               //      table[(T_null<<4)+T_byte]                       = T_undefined;
+               //      table[(T_null<<4)+T_long]                       = T_undefined;
+               //      table[(T_null<<4)+T_short]                      = T_undefined;
+               //      table[(T_null<<4)+T_void]                       = T_undefined;
+               table[(T_null<<4)+T_String]             = (T_null<<16)+(T_null<<12)+(String2String<<4)+T_String;
+               //      table[(T_null<<4)+T_Object]             = T_undefined;
+               //      table[(T_null<<4)+T_double]             = T_undefined;
+               //      table[(T_null<<4)+T_float]                      = T_undefined;
+               //      table[(T_null<<4)+T_boolean]            = T_undefined;
+               //      table[(T_null<<4)+T_char]                       = T_undefined;
+               //      table[(T_null<<4)+T_int]                        = T_undefined;
+               //      table[(T_null<<4)+T_null]                       = (Null2String<<12)+(Null2String<<4)+T_String;;
+       
+               return table;
+       }
+
+       public static final int[] get_REMAINDER(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_MINUS();
+       }
+
+       public static final int[] get_RIGHT_SHIFT(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_LEFT_SHIFT();
+       }
+
+       public static final int[] get_UNSIGNED_RIGHT_SHIFT(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+               
+               //      int[] table  = new int[16*16];
+               return get_LEFT_SHIFT();
+       }
+
+       public static final int[] get_XOR(){
+       
+               //the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       
+
+               //      int[] table  = new int[16*16];
+               return get_AND();
+       }
+       
+       public String operatorToString() {
+               switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+                       case EQUAL_EQUAL :
+                               return "=="; //$NON-NLS-1$
+                       case LESS_EQUAL :
+                               return "<="; //$NON-NLS-1$
+                       case GREATER_EQUAL :
+                               return ">="; //$NON-NLS-1$
+                       case NOT_EQUAL :
+                               return "!="; //$NON-NLS-1$
+                       case LEFT_SHIFT :
+                               return "<<"; //$NON-NLS-1$
+                       case RIGHT_SHIFT :
+                               return ">>"; //$NON-NLS-1$
+                       case UNSIGNED_RIGHT_SHIFT :
+                               return ">>>"; //$NON-NLS-1$
+                       case OR_OR :
+                               return "||"; //$NON-NLS-1$
+                       case AND_AND :
+                               return "&&"; //$NON-NLS-1$
+                       case PLUS :
+                               return "+"; //$NON-NLS-1$
+                       case MINUS :
+                               return "-"; //$NON-NLS-1$
+                       case NOT :
+                               return "!"; //$NON-NLS-1$
+                       case REMAINDER :
+                               return "%"; //$NON-NLS-1$
+                       case XOR :
+                               return "^"; //$NON-NLS-1$
+                       case AND :
+                               return "&"; //$NON-NLS-1$
+                       case MULTIPLY :
+                               return "*"; //$NON-NLS-1$
+                       case OR :
+                               return "|"; //$NON-NLS-1$
+                       case TWIDDLE :
+                               return "~"; //$NON-NLS-1$
+                       case DIVIDE :
+                               return "/"; //$NON-NLS-1$
+                       case GREATER :
+                               return ">"; //$NON-NLS-1$
+                       case LESS :
+                               return "<"; //$NON-NLS-1$
+                       case QUESTIONCOLON :
+                               return "?:"; //$NON-NLS-1$
+                       case EQUAL :
+                               return "="; //$NON-NLS-1$
+               }
+               return "unknown operator"; //$NON-NLS-1$
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output){
+
+               output.append('(');
+               return printExpressionNoParenthesis(0, output).append(')');
+       }
+       
+       public abstract StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output);
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/OperatorIds.java b/src/java/org/eclipse/jdt/internal/compiler/ast/OperatorIds.java
new file mode 100644 (file)
index 0000000..c32c609
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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 interface OperatorIds {
+       public static final int AND_AND = 0;
+       public static final int OR_OR = 1;
+       public static final int AND = 2; 
+       public static final int OR = 3; 
+       public static final int LESS = 4;
+       public static final int LESS_EQUAL = 5;
+       public static final int GREATER = 6;
+       public static final int GREATER_EQUAL = 7;
+       public static final int XOR = 8;
+       public static final int DIVIDE = 9; 
+       public static final int LEFT_SHIFT = 10;
+       public static final int NOT = 11; 
+       public static final int TWIDDLE = 12; 
+       public static final int MINUS = 13; 
+       public static final int PLUS = 14; 
+       public static final int MULTIPLY = 15; 
+       public static final int REMAINDER = 16;
+       public static final int RIGHT_SHIFT = 17;
+       public static final int EQUAL_EQUAL = 18;
+       public static final int UNSIGNED_RIGHT_SHIFT= 19;
+       public static final int NumberOfTables = 20;
+
+       public static final int QUESTIONCOLON = 23;
+
+       public static final int NOT_EQUAL = 29;
+       public static final int EQUAL = 30;
+       public static final int INSTANCEOF = 31;
+       public static final int PLUS_PLUS = 32;
+       public static final int MINUS_MINUS = 33;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/PostfixExpression.java
new file mode 100644 (file)
index 0000000..67f7b4a
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class PostfixExpression extends CompoundAssignment {
+
+       public PostfixExpression(Expression l, Expression e, int op, int pos) {
+               
+               super(l, e, op, pos);
+               this.sourceStart = l.sourceStart;
+               this.sourceEnd = pos;
+       }
+       
+       /**
+        * Code generation for PostfixExpression
+        *
+        * @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) {
+
+               // various scenarii are possible, setting an array reference, 
+               // a field reference, a blank final field reference, a field of an enclosing instance or 
+               // just a local variable.
+
+               int pc = codeStream.position;
+                ((Reference) lhs).generatePostIncrement(currentScope, codeStream, this, valueRequired);
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(implicitConversion);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public String operatorToString() {
+               switch (operator) {
+                       case PLUS :
+                               return "++"; //$NON-NLS-1$
+                       case MINUS :
+                               return "--"; //$NON-NLS-1$
+               } 
+               return "unknown operator"; //$NON-NLS-1$
+       }
+       
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+               return lhs.printExpression(indent, output).append(' ').append(operatorToString()); 
+       } 
+
+       public boolean restrainUsageToNumericTypes() {
+
+               return true;
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       lhs.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/PrefixExpression.java
new file mode 100644 (file)
index 0000000..1bdb104
--- /dev/null
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.*;
+
+public class PrefixExpression extends CompoundAssignment {
+
+       /**
+        * PrefixExpression constructor comment.
+        * @param l org.eclipse.jdt.internal.compiler.ast.Expression
+        * @param e org.eclipse.jdt.internal.compiler.ast.Expression
+        * @param op int
+        */
+       public PrefixExpression(Expression l, Expression e, int op, int pos) {
+
+               super(l, e, op, l.sourceEnd);
+               this.sourceStart = pos;
+               this.sourceEnd = l.sourceEnd;
+       }
+
+       public String operatorToString() {
+
+               switch (operator) {
+                       case PLUS :
+                               return "++"; //$NON-NLS-1$
+                       case MINUS :
+                               return "--"; //$NON-NLS-1$
+               } 
+               return "unknown operator"; //$NON-NLS-1$
+       }
+
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+
+               output.append(operatorToString()).append(' ');
+               return lhs.printExpression(0, output); 
+       } 
+       
+       public boolean restrainUsageToNumericTypes() {
+
+               return true;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       lhs.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
new file mode 100644 (file)
index 0000000..af7dd02
--- /dev/null
@@ -0,0 +1,347 @@
+/*******************************************************************************
+ * 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.*;
+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
+ */
+public class QualifiedAllocationExpression extends AllocationExpression {
+       
+       //qualification may be on both side
+       public Expression enclosingInstance;
+       public TypeDeclaration anonymousType;
+       public ReferenceBinding superTypeBinding;
+       
+       public QualifiedAllocationExpression() {
+               // for subtypes
+       }
+
+       public QualifiedAllocationExpression(TypeDeclaration anonymousType) {
+               this.anonymousType = anonymousType;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // analyse the enclosing instance
+               if (enclosingInstance != null) {
+                       flowInfo = enclosingInstance.analyseCode(currentScope, flowContext, flowInfo);
+               }
+               
+               // check captured variables are initialized in current context (26134)
+               checkCapturedLocalInitializationIfNecessary(
+                       this.superTypeBinding == null ? this.binding.declaringClass : this.superTypeBinding, 
+                       currentScope, 
+                       flowInfo);
+               
+               // process arguments
+               if (arguments != null) {
+                       for (int i = 0, count = arguments.length; i < count; i++) {
+                               flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo);
+                       }
+               }
+
+               // analyse the anonymous nested type
+               if (anonymousType != null) {
+                       flowInfo = anonymousType.analyseCode(currentScope, flowContext, flowInfo);
+               }
+
+               // record some dependency information for exception types
+               ReferenceBinding[] thrownExceptions;
+               if (((thrownExceptions = binding.thrownExceptions).length) != 0) {
+                       // check exception handling
+                       flowContext.checkExceptionHandlers(
+                               thrownExceptions,
+                               this,
+                               flowInfo,
+                               currentScope);
+               }
+               manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+               manageSyntheticAccessIfNecessary(currentScope, flowInfo);
+               return flowInfo;
+       }
+
+       public Expression enclosingInstance() {
+
+               return enclosingInstance;
+       }
+
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+
+               int pc = codeStream.position;
+               ReferenceBinding allocatedType = binding.declaringClass;
+               codeStream.new_(allocatedType);
+               if (valueRequired) {
+                       codeStream.dup();
+               }
+               // better highlight for allocation: display the type individually
+               codeStream.recordPositionsFrom(pc, type.sourceStart);
+
+               // handling innerclass instance allocation - enclosing instance arguments
+               if (allocatedType.isNestedType()) {
+                       codeStream.generateSyntheticEnclosingInstanceValues(
+                               currentScope,
+                               allocatedType,
+                               enclosingInstance(),
+                               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);
+                       }
+               }
+               // handling innerclass instance allocation - outer local arguments
+               if (allocatedType.isNestedType()) {
+                       codeStream.generateSyntheticOuterArgumentValues(
+                               currentScope,
+                               allocatedType,
+                               this);
+               }
+               
+               // invoke constructor
+               if (syntheticAccessor == null) {
+                       codeStream.invokespecial(binding);
+               } 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;
+                               i < max;
+                               i++) {
+                               codeStream.aconst_null();
+                       }
+                       codeStream.invokespecial(syntheticAccessor);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+
+               if (anonymousType != null) {
+                       anonymousType.generateCode(currentScope, codeStream);
+               }
+       }
+       
+       public boolean isSuperAccess() {
+
+               // necessary to lookup super constructor of anonymous type
+               return anonymousType != null;
+       }
+       
+       /* Inner emulation consists in either recording a dependency 
+        * link only, or performing one level of propagation.
+        *
+        * Dependency mechanism is used whenever dealing with source target
+        * types, since by the time we reach them, we might not yet know their
+        * exact need.
+        */
+       public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               ReferenceBinding allocatedType;
+
+               // perform some emulation work in case there is some and we are inside a local type only
+               if ((allocatedType = binding.declaringClass).isNestedType()
+                       && currentScope.enclosingSourceType().isLocalType()) {
+
+                       if (allocatedType.isLocalType()) {
+                               ((LocalTypeBinding) allocatedType).addInnerEmulationDependent(currentScope, enclosingInstance != null);
+                       } else {
+                               // locally propagate, since we already now the desired shape for sure
+                               currentScope.propagateInnerEmulation(allocatedType, enclosingInstance != null);
+                       }
+               }
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               if (enclosingInstance != null)
+                       enclosingInstance.printExpression(0, output).append('.'); 
+               super.printExpression(0, output);
+               if (anonymousType != null) {
+                       anonymousType.print(indent, output);
+               }
+               return output;
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+
+               // added for code assist...cannot occur with 'normal' code
+               if (anonymousType == null && 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;
+               boolean hasError = false;
+               boolean enclosingInstanceContainsCast = false;
+               boolean argsContainCast = false;
+               
+               if (enclosingInstance != null) {
+                       if (enclosingInstance instanceof CastExpression) {
+                               enclosingInstance.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+                               enclosingInstanceContainsCast = true;
+                       }
+                       if ((enclosingInstanceType = enclosingInstance.resolveType(scope)) == null){
+                               hasError = true;
+                       } else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) {
+                               scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(
+                                       enclosingInstanceType,
+                                       enclosingInstance);
+                               hasError = true;
+                       } else {
+                               receiverType = ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType);
+                               if (receiverType != null && enclosingInstanceContainsCast) {
+                                               CastExpression.checkNeedForEnclosingInstanceCast(scope, enclosingInstance, enclosingInstanceType, receiverType);
+                               }
+                       }
+               } else {
+                       receiverType = type.resolveType(scope);
+               }
+               if (receiverType == null) {
+                       hasError = true;
+               } else if (((ReferenceBinding) receiverType).isFinal() && this.anonymousType != null) {
+                       scope.problemReporter().anonymousClassCannotExtendFinalClass(type, receiverType);
+                       hasError = true;
+               }
+
+               // will check for null after args are resolved
+               TypeBinding[] argumentTypes = NoParameters;
+               if (arguments != null) {
+                       int length = arguments.length;
+                       argumentTypes = new TypeBinding[length];
+                       for (int i = 0; i < length; i++) {
+                               Expression argument = this.arguments[i];
+                               if (argument instanceof CastExpression) {
+                                       argument.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+                                       argsContainCast = true;
+                               }
+                               if ((argumentTypes[i] = argument.resolveType(scope)) == null){
+                                       hasError = true;
+                               }
+                       }
+               }
+               // limit of fault-tolerance
+               if (hasError) return this.resolvedType = receiverType;
+               
+               if (this.anonymousType == null) {
+                       // qualified allocation with no anonymous type
+                       ReferenceBinding allocationType = (ReferenceBinding) receiverType;
+                       if (!receiverType.canBeInstantiated()) {
+                               scope.problemReporter().cannotInstantiate(type, receiverType);
+                               return this.resolvedType = receiverType;
+                       }
+                       if ((this.binding = scope.getConstructor(allocationType, argumentTypes, this)).isValidBinding()) {
+                               if (isMethodUseDeprecated(binding, scope)) {
+                                       scope.problemReporter().deprecatedMethod(this.binding, this);
+                               }
+                               if (arguments != null) {
+                                       for (int i = 0; i < arguments.length; i++) {
+                                               arguments[i].implicitWidening(this.binding.parameters[i], argumentTypes[i]);
+                                       }
+                                       if (argsContainCast) {
+                                               CastExpression.checkNeedForArgumentCasts(scope, null, allocationType, binding, this.arguments, argumentTypes, this);
+                                       }
+                               }
+                       } else {
+                               if (this.binding.declaringClass == null) {
+                                       this.binding.declaringClass = allocationType;
+                               }
+                               scope.problemReporter().invalidConstructor(this, this.binding);
+                               return this.resolvedType = receiverType;
+                       }
+
+                       // The enclosing instance must be compatible with the innermost enclosing type
+                       ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
+                       if (enclosingInstanceType.isCompatibleWith(expectedType)) {
+                               return receiverType;
+                       }
+                       scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+                               this.enclosingInstance,
+                               enclosingInstanceType,
+                               expectedType);
+                       return this.resolvedType = receiverType;
+               }
+
+               // anonymous type scenario
+               // an anonymous class inherits from java.lang.Object when declared "after" an interface
+               this.superTypeBinding = receiverType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) receiverType;
+               // insert anonymous type in scope
+               scope.addAnonymousType(this.anonymousType, (ReferenceBinding) receiverType);
+               this.anonymousType.resolve(scope);              
+               
+               // find anonymous super constructor
+               MethodBinding inheritedBinding = scope.getConstructor(this.superTypeBinding, argumentTypes, this);
+               if (!inheritedBinding.isValidBinding()) {
+                       if (inheritedBinding.declaringClass == null) {
+                               inheritedBinding.declaringClass = this.superTypeBinding;
+                       }
+                       scope.problemReporter().invalidConstructor(this, inheritedBinding);
+                       return this.resolvedType = anonymousType.binding;
+               }
+               if (enclosingInstance != null) {
+                       ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType();
+                       if (targetEnclosing == null) {
+                               scope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, (ReferenceBinding)receiverType);
+                               return this.resolvedType = anonymousType.binding;
+                       } else  if (!enclosingInstanceType.isCompatibleWith(targetEnclosing)) {
+                               scope.problemReporter().typeMismatchErrorActualTypeExpectedType(enclosingInstance, enclosingInstanceType, targetEnclosing);
+                               return this.resolvedType = anonymousType.binding;
+                       }
+               }
+
+               // this promotion has to be done somewhere: here or inside the constructor of the
+               // anonymous class. We do it here while the constructor of the inner is then easier.
+               if (arguments != null) {
+                       for (int i = 0; i < arguments.length; i++) {
+                               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);
+               return this.resolvedType = anonymousType.binding; // 1.2 change
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+
+               if (visitor.visit(this, scope)) {
+                       if (enclosingInstance != null)
+                               enclosingInstance.traverse(visitor, scope);
+                       type.traverse(visitor, scope);
+                       if (arguments != null) {
+                               int argumentsLength = arguments.length;
+                               for (int i = 0; i < argumentsLength; i++)
+                                       arguments[i].traverse(visitor, scope);
+                       }
+                       if (anonymousType != null)
+                               anonymousType.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedNameReference.java
new file mode 100644 (file)
index 0000000..8afa15a
--- /dev/null
@@ -0,0 +1,812 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+public class QualifiedNameReference extends NameReference {
+       
+       public char[][] tokens;
+       public long[] sourcePositions;  
+       public FieldBinding[] otherBindings, otherCodegenBindings;
+       int[] otherDepths;
+       public int indexOfFirstFieldBinding;//points (into tokens) for the first token that corresponds to first FieldBinding
+       SyntheticAccessMethodBinding syntheticWriteAccessor;
+       SyntheticAccessMethodBinding[] syntheticReadAccessors;
+       protected FieldBinding lastFieldBinding;
+       public QualifiedNameReference(
+               char[][] sources,
+               long[] positions,
+               int sourceStart,
+               int sourceEnd) {
+               super();
+               this.tokens = sources;
+               this.sourcePositions = positions;
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+       public FlowInfo analyseAssignment(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo,
+               Assignment assignment,
+               boolean isCompound) {
+
+               // 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();
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // reading a field
+                               lastFieldBinding = (FieldBinding) binding;
+                               if (needValue) {
+                                       manageSyntheticReadAccessIfNecessary(currentScope, lastFieldBinding, this.actualReceiverType, 0, flowInfo);
+                               }                               // check if final blank field
+                               if (lastFieldBinding.isBlankFinal()
+                                   && this.otherBindings != null // the last field binding is only assigned
+                                       && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) {
+                                       if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) {
+                                               currentScope.problemReporter().uninitializedBlankFinalField(
+                                                       lastFieldBinding,
+                                                       this);
+                                       }
+                               }
+                               break;
+                       case LOCAL :
+                               // first binding is a local variable
+                               LocalVariableBinding localBinding;
+                               if (!flowInfo
+                                       .isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+                                       currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
+                               }
+                               if (flowInfo.isReachable()) {
+                                       localBinding.useFlag = LocalVariableBinding.USED;
+                               } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
+                                       localBinding.useFlag = LocalVariableBinding.FAKE_USED;
+                               }
+               }
+               
+               if (needValue) {
+                       manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+                       // only for first binding
+               }
+               // all intermediate field accesses are read accesses
+               if (otherBindings != null) {
+                       for (int i = 0; i < otherBindingsCount-1; i++) {
+                               lastFieldBinding = otherBindings[i];
+                               needValue = !otherBindings[i+1].isStatic();
+                               if (needValue) {
+                                       manageSyntheticReadAccessIfNecessary(
+                                               currentScope, 
+                                               lastFieldBinding, 
+                                               i == 0 
+                                                       ? ((VariableBinding)binding).type
+                                                       : otherBindings[i-1].type,
+                                               i + 1, 
+                                               flowInfo);
+                               }
+                       }
+                       lastFieldBinding = otherBindings[otherBindingsCount-1];
+               }
+
+               if (isCompound) {
+                       if (binding == lastFieldBinding
+                               && lastFieldBinding.isBlankFinal()
+                               && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)
+                               && (!flowInfo.isDefinitelyAssigned(lastFieldBinding))) {
+                               currentScope.problemReporter().uninitializedBlankFinalField(
+                                       lastFieldBinding,
+                                       this);
+                       }
+                       TypeBinding lastReceiverType;
+                       if (lastFieldBinding == binding){
+                               lastReceiverType = this.actualReceiverType;
+                       } else if (otherBindingsCount == 1){
+                               lastReceiverType = ((VariableBinding)this.binding).type;
+                       } else {
+                               lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
+                       }
+                       manageSyntheticReadAccessIfNecessary(
+                               currentScope,
+                               lastFieldBinding,
+                               lastReceiverType,
+                               lastFieldBinding == binding
+                                       ? 0 
+                                       : otherBindingsCount, 
+                               flowInfo);
+               }
+               
+               if (assignment.expression != null) {
+                       flowInfo =
+                               assignment
+                                       .expression
+                                       .analyseCode(currentScope, flowContext, flowInfo)
+                                       .unconditionalInits();
+               }
+               
+               // the last field access is a write access
+               if (lastFieldBinding.isFinal()) {
+                       // in a context where it can be assigned?
+                       if (lastFieldBinding.isBlankFinal()
+                                       && !isCompound
+                                       && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding) 
+                                       && indexOfFirstFieldBinding == 1) {
+                               if (flowInfo.isPotentiallyAssigned(lastFieldBinding)) {
+                                       currentScope.problemReporter().duplicateInitializationOfBlankFinalField(lastFieldBinding, this);
+                               } else {
+                                       flowContext.recordSettingFinal(lastFieldBinding, this, flowInfo);
+                               }
+                               flowInfo.markAsDefinitelyAssigned(lastFieldBinding);
+                       } else {
+                               currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this);
+                               if (currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) { // pretend it got assigned
+                                       flowInfo.markAsDefinitelyAssigned(lastFieldBinding);
+                               }
+                       }
+               }
+               // equivalent to valuesRequired[maxOtherBindings]
+               TypeBinding lastReceiverType;
+               if (lastFieldBinding == binding){
+                       lastReceiverType = this.actualReceiverType;
+               } else if (otherBindingsCount == 1){
+                       lastReceiverType = ((VariableBinding)this.binding).type;
+               } else {
+                       lastReceiverType = this.otherBindings[otherBindingsCount-2].type;
+               }
+               manageSyntheticWriteAccessIfNecessary(currentScope, lastFieldBinding, lastReceiverType, flowInfo);
+
+               return flowInfo;
+       }
+       
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return analyseCode(currentScope, flowContext, flowInfo, true);
+       }
+       
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo,
+               boolean valueRequired) {
+                       
+               // 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 ? valueRequired : !this.otherBindings[0].isStatic();
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // reading a field
+                               if (needValue) {
+                                       manageSyntheticReadAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0, flowInfo);
+                               }
+                               // check if reading a final blank field
+                               FieldBinding fieldBinding;
+                                       if ((fieldBinding = (FieldBinding) binding).isBlankFinal()
+                                               && (indexOfFirstFieldBinding == 1)
+                                       // was an implicit reference to the first field binding
+                                               && currentScope.allowBlankFinalFieldAssignment(fieldBinding)
+                                               && (!flowInfo.isDefinitelyAssigned(fieldBinding))) {
+                                       currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
+                               }
+                               break;
+                       case LOCAL : // reading a local variable
+                               LocalVariableBinding localBinding;
+                               if (!flowInfo
+                                       .isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+                                       currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
+                               }
+                               if (flowInfo.isReachable()) {
+                                       localBinding.useFlag = LocalVariableBinding.USED;
+                               } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
+                                       localBinding.useFlag = LocalVariableBinding.FAKE_USED;
+                               }
+               }
+               if (needValue) {
+                       manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+                       // only for first binding
+               }
+               if (otherBindings != null) {
+                       for (int i = 0; i < otherBindingsCount; i++) {
+                               needValue = i < otherBindingsCount-1 ? !otherBindings[i+1].isStatic() : valueRequired;
+                               if (needValue) {
+                                       manageSyntheticReadAccessIfNecessary(
+                                               currentScope, 
+                                               otherBindings[i], 
+                                               i == 0 
+                                                       ? ((VariableBinding)binding).type
+                                                       : otherBindings[i-1].type,
+                                               i + 1,
+                                               flowInfo);
+                               }
+                       }
+               }
+               return flowInfo;
+       }
+       /**
+        * Check and/or redirect the field access to the delegate receiver if any
+        */
+       public TypeBinding checkFieldAccess(BlockScope scope) {
+               // check for forward references
+               FieldBinding fieldBinding = (FieldBinding) binding;
+               MethodScope methodScope = scope.methodScope();
+               if (methodScope.enclosingSourceType() == fieldBinding.declaringClass
+                       && methodScope.lastVisibleFieldID >= 0
+                       && fieldBinding.id >= methodScope.lastVisibleFieldID) {
+                       if ((!fieldBinding.isStatic() || methodScope.isStatic)
+                               && this.indexOfFirstFieldBinding == 1)
+                               scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
+               }
+               bits &= ~RestrictiveFlagMASK; // clear bits
+               bits |= FIELD;
+               return getOtherFieldBindings(scope);
+       }
+       public void generateAssignment(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Assignment assignment,
+               boolean valueRequired) {
+                       
+               generateReadSequence(currentScope, codeStream);
+               assignment.expression.generateCode(currentScope, codeStream, true);
+               fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired);
+               // equivalent to valuesRequired[maxOtherBindings]
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(assignment.implicitConversion);
+               }
+       }
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+                       
+               int pc = codeStream.position;
+               if (constant != NotAConstant) {
+                       if (valueRequired) {
+                               codeStream.generateConstant(constant, implicitConversion);
+                       }
+               } else {
+                       generateReadSequence(currentScope, codeStream); 
+                       if (valueRequired) {
+                               if (lastFieldBinding.declaringClass == null) { // array length
+                                       codeStream.arraylength();
+                                       codeStream.generateImplicitConversion(implicitConversion);
+                               } else {
+                                       if (lastFieldBinding.constant != NotAConstant) {
+                                               if (!lastFieldBinding.isStatic()){
+                                                       codeStream.invokeObjectGetClass();
+                                                       codeStream.pop();
+                                               }
+                                               // inline the last field constant
+                                               codeStream.generateConstant(lastFieldBinding.constant, implicitConversion);
+                                       } else {
+                                               SyntheticAccessMethodBinding accessor =
+                                                       syntheticReadAccessors == null
+                                                               ? null
+                                                               : syntheticReadAccessors[syntheticReadAccessors.length - 1];
+                                               if (accessor == null) {
+                                                       if (lastFieldBinding.isStatic()) {
+                                                               codeStream.getstatic(lastFieldBinding);
+                                                       } else {
+                                                               codeStream.getfield(lastFieldBinding);
+                                                       }
+                                               } else {
+                                                       codeStream.invokestatic(accessor);
+                                               }
+                                               codeStream.generateImplicitConversion(implicitConversion);
+                                       }
+                               }
+                       } else {
+                               if (lastFieldBinding != null && !lastFieldBinding.isStatic()){
+                                       codeStream.invokeObjectGetClass(); // perform null check
+                                       codeStream.pop();
+                               }
+                                                       
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+       public void generateCompoundAssignment(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Expression expression,
+               int operator,
+               int assignmentImplicitConversion,
+               boolean valueRequired) {
+                       
+               generateReadSequence(currentScope, codeStream);
+               SyntheticAccessMethodBinding accessor =
+                       syntheticReadAccessors == null
+                               ? null
+                               : syntheticReadAccessors[syntheticReadAccessors.length - 1];
+               if (lastFieldBinding.isStatic()) {
+                       if (accessor == null) {
+                               codeStream.getstatic(lastFieldBinding);
+                       } else {
+                               codeStream.invokestatic(accessor);
+                       }
+               } else {
+                       codeStream.dup();
+                       if (accessor == null) {
+                               codeStream.getfield(lastFieldBinding);
+                       } else {
+                               codeStream.invokestatic(accessor);
+                       }
+               }
+               // 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);
+               }
+               // actual assignment
+               fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, valueRequired);
+               // equivalent to valuesRequired[maxOtherBindings]
+       }
+       public void generatePostIncrement(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               CompoundAssignment postIncrement,
+               boolean valueRequired) {
+               generateReadSequence(currentScope, codeStream);
+               SyntheticAccessMethodBinding accessor =
+                       syntheticReadAccessors == null
+                               ? null
+                               : syntheticReadAccessors[syntheticReadAccessors.length - 1];
+               if (lastFieldBinding.isStatic()) {
+                       if (accessor == null) {
+                               codeStream.getstatic(lastFieldBinding);
+                       } else {
+                               codeStream.invokestatic(accessor);
+                       }
+               } else {
+                       codeStream.dup();
+                       if (accessor == null) {
+                               codeStream.getfield(lastFieldBinding);
+                       } else {
+                               codeStream.invokestatic(accessor);
+                       }
+               }
+               // duplicate the old field value
+               if (valueRequired) {
+                       if (lastFieldBinding.isStatic()) {
+                               if ((lastFieldBinding.type == LongBinding)
+                                       || (lastFieldBinding.type == DoubleBinding)) {
+                                       codeStream.dup2();
+                               } else {
+                                       codeStream.dup();
+                               }
+                       } else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
+                               if ((lastFieldBinding.type == LongBinding)
+                                       || (lastFieldBinding.type == DoubleBinding)) {
+                                       codeStream.dup2_x1();
+                               } else {
+                                       codeStream.dup_x1();
+                               }
+                       }
+               }
+               codeStream.generateConstant(
+                       postIncrement.expression.constant,
+                       implicitConversion);
+               codeStream.sendOperator(postIncrement.operator, lastFieldBinding.type.id);
+               codeStream.generateImplicitConversion(
+                       postIncrement.assignmentImplicitConversion);
+               fieldStore(codeStream, lastFieldBinding, syntheticWriteAccessor, false);
+       }
+       /*
+        * 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) {
+                       
+               // 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();
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD :
+                               lastFieldBinding = (FieldBinding) this.codegenBinding;
+                               // if first field is actually constant, we can inline it
+                               if (lastFieldBinding.constant != NotAConstant) {
+                                       break;
+                               }
+                               if (needValue && !lastFieldBinding.isStatic()) {
+                                       if ((bits & DepthMASK) != 0) {
+                                               ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+                                               Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+                                               codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+                                       } else {
+                                               generateReceiver(codeStream);
+                                       }
+                               }
+                               break;
+                       case LOCAL : // reading the first local variable
+                               lastFieldBinding = null;
+                               if (!needValue) break; // no value needed
+                               LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+                               // regular local variable read
+                               if (localBinding.constant != NotAConstant) {
+                                       codeStream.generateConstant(localBinding.constant, 0);
+                                       // no implicit conversion
+                               } else {
+                                       // outer local?
+                                       if ((bits & DepthMASK) != 0) {
+                                               // outer local can be reached either through a synthetic arg or a synthetic field
+                                               VariableBinding[] path = currentScope.getEmulationPath(localBinding);
+                                               codeStream.generateOuterAccess(path, this, localBinding, currentScope);
+                                       } else {
+                                               codeStream.load(localBinding);
+                                       }
+                               }
+               }
+
+               // 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];
+                               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()) {
+                                                                       codeStream.invokeObjectGetClass(); // perform null check
+                                                                       codeStream.pop();
+                                                               }
+                                                               codeStream.generateConstant(lastFieldBinding.constant, 0);
+                                                       } else if (lastFieldBinding.isStatic()) {
+                                                               codeStream.getstatic(lastFieldBinding);
+                                                       } else {
+                                                               codeStream.getfield(lastFieldBinding);
+                                                       }
+                                               } else {
+                                                       codeStream.invokestatic(accessor);
+                                               }
+                                       } else {
+                                               if (this.codegenBinding != this.lastFieldBinding && !this.lastFieldBinding.isStatic()){
+                                                       codeStream.invokeObjectGetClass(); // perform null check
+                                                       codeStream.pop();
+                                               }                                               
+                                       }
+                               }
+                               this.lastFieldBinding = nextField;
+                       }
+               }
+       }
+       public void generateReceiver(CodeStream codeStream) {
+               codeStream.aload_0();
+       }
+       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()) {
+                               //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);
+                                       return null;
+                                }
+                       } else {
+                               // indirect static reference ?
+                               if (indexOfFirstFieldBinding > 1 
+                                               && fieldBinding.declaringClass != actualReceiverType) {
+                                       scope.problemReporter().indirectAccessToStaticField(this, fieldBinding);
+                               }
+                       }
+                       // only last field is actually a write access if any
+                       if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && indexOfFirstFieldBinding == length))
+                               scope.problemReporter().deprecatedField(fieldBinding, this);
+               }
+               TypeBinding type = ((VariableBinding) binding).type;
+               int index = indexOfFirstFieldBinding;
+               if (index == length) { //       restrictiveFlag == FIELD
+                       this.constant = FieldReference.getConstantFor((FieldBinding) binding, this, false, scope);
+                       return type;
+               }
+               // allocation of the fieldBindings array        and its respective constants
+               int otherBindingsLength = length - index;
+               otherCodegenBindings = otherBindings = new FieldBinding[otherBindingsLength];
+               otherDepths = new int[otherBindingsLength];
+               
+               // fill the first constant (the one of the binding)
+               this.constant =
+                       ((bits & FIELD) != 0)
+                               ? FieldReference.getConstantFor((FieldBinding) binding, this, false, scope)
+                               : ((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      
+               while (index < length) {
+                       char[] token = tokens[index];
+                       if (type == null)
+                               return null; // could not resolve type prior to this point
+
+                       bits &= ~DepthMASK; // flush previous depth if any                      
+                       FieldBinding field = scope.getField(type, token, this);
+                       int place = index - indexOfFirstFieldBinding;
+                       otherBindings[place] = field;
+                       otherDepths[place] = (bits & DepthMASK) >> DepthSHIFT;
+                       if (field.isValidBinding()) {
+                               // only last field is actually a write access if any
+                               if (isFieldUseDeprecated(field, scope, (this.bits & IsStrictlyAssignedMASK) !=0 && index+1 == length)) {
+                                       scope.problemReporter().deprecatedField(field, this);
+                               }
+                               Constant someConstant = FieldReference.getConstantFor(field, this, false, scope);
+                               // constant propagation can only be performed as long as the previous one is a constant too.
+                               if (this.constant != NotAConstant) {
+                                       this.constant = someConstant;                                   
+                               }
+
+                               if (field.isStatic()) {
+                                       // static field accessed through receiver? legal but unoptimal (optional warning)
+                                       scope.problemReporter().nonStaticAccessToStaticField(this, field);
+                                       // indirect static reference ?
+                                       if (field.declaringClass != type) {
+                                               scope.problemReporter().indirectAccessToStaticField(this, field);
+                                       }
+                               }
+                               type = field.type;
+                               index++;
+                       } else {
+                               constant = NotAConstant; //don't fill other constants slots...
+                               scope.problemReporter().invalidField(this, field, index, type);
+                               setDepth(firstDepth);
+                               return null;
+                       }
+               }
+               setDepth(firstDepth);
+               return (otherBindings[otherBindingsLength - 1]).type;
+       }
+       public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+               if (!flowInfo.isReachable()) return;
+               //If inlinable field, forget the access emulation, the code gen will directly target it
+               if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) {
+                       return;
+               }
+               if ((bits & RestrictiveFlagMASK) == LOCAL) {
+                       currentScope.emulateOuterAccess((LocalVariableBinding) binding);
+               }
+       }
+       public void manageSyntheticReadAccessIfNecessary(
+                       BlockScope currentScope,
+                       FieldBinding fieldBinding,
+                       TypeBinding lastReceiverType,
+                       int index,
+                       FlowInfo flowInfo) {
+               if (!flowInfo.isReachable()) return;
+               // index == 0 denotes the first fieldBinding, index > 0 denotes one of the 'otherBindings'
+               if (fieldBinding.constant != NotAConstant)
+                       return;
+               if (fieldBinding.isPrivate()) { // private access
+                       if (fieldBinding.declaringClass != currentScope.enclosingSourceType()) {
+                               if (syntheticReadAccessors == null) {
+                                       if (otherBindings == null)
+                                               syntheticReadAccessors = new SyntheticAccessMethodBinding[1];
+                                       else
+                                               syntheticReadAccessors =
+                                                       new SyntheticAccessMethodBinding[otherBindings.length + 1];
+                               }
+                               syntheticReadAccessors[index] = ((SourceTypeBinding) fieldBinding.declaringClass).addSyntheticMethod(fieldBinding, true);
+                               currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+                               return;
+                       }
+               } else if (fieldBinding.isProtected()){
+                       int depth = index == 0 ? (bits & DepthMASK) >> DepthSHIFT : otherDepths[index-1];
+                       // implicit protected access (only for first one)
+                       if (depth > 0 && (fieldBinding.declaringClass.getPackage()
+                                                               != currentScope.enclosingSourceType().getPackage())) {
+                               if (syntheticReadAccessors == null) {
+                                       if (otherBindings == null)
+                                               syntheticReadAccessors = new SyntheticAccessMethodBinding[1];
+                                       else
+                                               syntheticReadAccessors =
+                                                       new SyntheticAccessMethodBinding[otherBindings.length + 1];
+                               }
+                               syntheticReadAccessors[index] =
+                                       ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth))
+                                                                                       .addSyntheticMethod(fieldBinding, true);
+                               currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+                               return;
+                       }
+               }
+               // if the binding declaring class is not visible, need special action
+               // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+               // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+               if (fieldBinding.declaringClass != lastReceiverType
+                       && !lastReceiverType.isArrayType()                      
+                       && fieldBinding.declaringClass != null
+                       && fieldBinding.constant == NotAConstant
+                       && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+                                       && (index > 0 || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
+                                       && fieldBinding.declaringClass.id != T_Object)
+                               || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+                       if (index == 0){
+                               this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
+                       } else {
+                               if (this.otherCodegenBindings == this.otherBindings){
+                                       int l = this.otherBindings.length;
+                                       System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
+                               }
+                               this.otherCodegenBindings[index-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
+                       }
+               }
+       }
+       /*
+        * No need to emulate access to protected fields since not implicitly accessed
+        */
+       public void manageSyntheticWriteAccessIfNecessary(
+                       BlockScope currentScope,
+                       FieldBinding fieldBinding,
+                       TypeBinding lastReceiverType,
+                       FlowInfo flowInfo) {
+               if (!flowInfo.isReachable()) return;
+               if (fieldBinding.isPrivate()) {
+                       if (fieldBinding.declaringClass != currentScope.enclosingSourceType()) {
+                               syntheticWriteAccessor = ((SourceTypeBinding) fieldBinding.declaringClass)
+                                                                                       .addSyntheticMethod(fieldBinding, false);
+                               currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+                               return;
+                       }
+               } else if (fieldBinding.isProtected()){
+                       int depth = fieldBinding == binding ? (bits & DepthMASK) >> DepthSHIFT : otherDepths[otherDepths.length-1];
+                       if (depth > 0 && (fieldBinding.declaringClass.getPackage()
+                                                               != currentScope.enclosingSourceType().getPackage())) {
+                               syntheticWriteAccessor = ((SourceTypeBinding) currentScope.enclosingSourceType().enclosingTypeAt(depth))
+                                                                                       .addSyntheticMethod(fieldBinding, false);
+                               currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+                               return;
+                       }
+               }
+               // if the binding declaring class is not visible, need special action
+               // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+               // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+               if (fieldBinding.declaringClass != lastReceiverType
+                       && !lastReceiverType.isArrayType()                      
+                       && fieldBinding.declaringClass != null
+                       && fieldBinding.constant == NotAConstant
+                       && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2
+                                       && (fieldBinding != binding || indexOfFirstFieldBinding > 1 || !fieldBinding.isStatic())
+                                       && fieldBinding.declaringClass.id != T_Object)
+                               || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+                       if (fieldBinding == binding){
+                               this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
+                       } else {
+                               if (this.otherCodegenBindings == this.otherBindings){
+                                       int l = this.otherBindings.length;
+                                       System.arraycopy(this.otherBindings, 0, this.otherCodegenBindings = new FieldBinding[l], 0, l);
+                               }
+                               this.otherCodegenBindings[this.otherCodegenBindings.length-1] = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)lastReceiverType);
+                       }
+               }
+               
+       }
+       
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+               
+               for (int i = 0; i < tokens.length; i++) {
+                       if (i > 0) output.append('.');
+                       output.append(tokens[i]);
+               }
+               return output;
+       }
+               
+       /**
+        * Normal field binding did not work, try to bind to a field of the delegate receiver.
+        */
+       public TypeBinding reportError(BlockScope scope) {
+               if (binding instanceof ProblemFieldBinding) {
+                       scope.problemReporter().invalidField(this, (FieldBinding) binding);
+               } else if (binding instanceof ProblemReferenceBinding) {
+                       scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               } else {
+                       scope.problemReporter().unresolvableReference(this, binding);
+               }
+               return null;
+       }
+       public TypeBinding resolveType(BlockScope scope) {
+               // 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();
+               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 :
+                                       if (binding instanceof LocalVariableBinding) {
+                                               if (!((LocalVariableBinding) binding).isFinal() && ((bits & DepthMASK) != 0))
+                                                       scope.problemReporter().cannotReferToNonFinalOuterLocal(
+                                                               (LocalVariableBinding) binding,
+                                                               this);
+                                               bits &= ~RestrictiveFlagMASK; // clear bits
+                                               bits |= LOCAL;
+                                               return this.resolvedType = getOtherFieldBindings(scope);
+                                       }
+                                       if (binding instanceof FieldBinding) {
+                                               // check for forward references
+                                               FieldBinding fieldBinding = (FieldBinding) binding;
+                                               MethodScope methodScope = scope.methodScope();
+                                               if (methodScope.enclosingSourceType() == fieldBinding.declaringClass
+                                                               && methodScope.lastVisibleFieldID >= 0
+                                                               && fieldBinding.id >= methodScope.lastVisibleFieldID) {
+                                                       if ((!fieldBinding.isStatic() || methodScope.isStatic)
+                                                               && this.indexOfFirstFieldBinding == 1) {
+                                                               scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
+                                                               }
+                                               }
+                                               if (!fieldBinding.isStatic() 
+                                                               && this.indexOfFirstFieldBinding == 1
+                                                               && scope.environment().options.getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
+                                                       scope.problemReporter().unqualifiedFieldAccess(this, fieldBinding);
+                                               }
+                                               bits &= ~RestrictiveFlagMASK; // clear bits
+                                               bits |= FIELD;
+                                               
+                                               // check for deprecated receiver type
+                                               // deprecation check for receiver type if not first token
+                                               if (indexOfFirstFieldBinding > 1) {
+                                                       if (isTypeUseDeprecated(this.actualReceiverType, scope))
+                                                               scope.problemReporter().deprecatedType(this.actualReceiverType, this);
+                                               }
+                                               
+                                               return this.resolvedType = getOtherFieldBindings(scope);
+                                       }
+                                       // 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;
+                       }
+               }
+               //========error cases===============
+               return this.resolvedType = this.reportError(scope);
+       }
+       
+       public void setFieldIndex(int index) {
+               this.indexOfFirstFieldBinding = index;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+       public String unboundReferenceErrorName() {
+               return new String(tokens[0]);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
new file mode 100644 (file)
index 0000000..592c433
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.*;
+
+public class QualifiedSuperReference extends QualifiedThisReference {
+       
+       public QualifiedSuperReference(TypeReference name, int pos, int sourceEnd) {
+               super(name, pos, sourceEnd);
+       }
+
+       public boolean isSuper() {
+
+               return true;
+       }
+
+       public boolean isThis() {
+
+               return false;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               return qualification.print(0, output).append(".super"); //$NON-NLS-1$
+       }
+       
+       public TypeBinding resolveType(BlockScope scope) {
+
+               if ((this.bits & ParenthesizedMASK) != 0) {
+                       scope.problemReporter().invalidParenthesizedExpression(this);
+                       return null;
+               }
+               super.resolveType(scope);
+               if (currentCompatibleType == null)
+                       return null; // error case
+
+               if (currentCompatibleType.id == T_Object) {
+                       scope.problemReporter().cannotUseSuperInJavaLangObject(this);
+                       return null;
+               }
+               return this.resolvedType = currentCompatibleType.superclass();
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       qualification.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedThisReference.java
new file mode 100644 (file)
index 0000000..93e4c1c
--- /dev/null
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class QualifiedThisReference extends ThisReference {
+       
+       public TypeReference qualification;
+       ReferenceBinding currentCompatibleType;
+       
+       public QualifiedThisReference(TypeReference name, int sourceStart, int sourceEnd) {
+               super(sourceStart, sourceEnd);
+               qualification = name;
+               this.sourceStart = name.sourceStart;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               return flowInfo;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo,
+               boolean valueRequired) {
+
+               return flowInfo;
+       }
+
+       /**
+        * Code generation for QualifiedThisReference
+        *
+        * @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 ((bits & DepthMASK) != 0) {
+                               Object[] emulationPath =
+                                       currentScope.getEmulationPath(this.currentCompatibleType, true /*only exact match*/, false/*consider enclosing arg*/);
+                               codeStream.generateOuterAccess(emulationPath, this, this.currentCompatibleType, currentScope);
+                       } else {
+                               // nothing particular after all
+                               codeStream.aload_0();
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+
+               constant = NotAConstant;
+               this.resolvedType = this.qualification.resolveType(scope);
+               if (this.resolvedType == null) return null;
+
+               // 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) {
+                       depth++;
+                       this.currentCompatibleType = this.currentCompatibleType.isStatic() ? null : this.currentCompatibleType.enclosingType();
+               }
+               bits &= ~DepthMASK; // flush previous depth if any                      
+               bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits
+
+               if (this.currentCompatibleType == null) {
+                       scope.problemReporter().noSuchEnclosingInstance(this.resolvedType, this, false);
+                       return this.resolvedType;
+               }
+
+               // 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;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+
+               return qualification.print(0, output).append(".this"); //$NON-NLS-1$
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       qualification.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
new file mode 100644 (file)
index 0000000..b37276b
--- /dev/null
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.*;
+
+public class QualifiedTypeReference extends TypeReference {
+
+       public char[][] tokens;
+       public long[] sourcePositions;
+
+       public QualifiedTypeReference(char[][] sources , long[] poss) {
+               
+               tokens = sources ;
+               sourcePositions = poss ;
+               sourceStart = (int) (sourcePositions[0]>>>32) ;
+               sourceEnd = (int)(sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFFL ) ;
+       }
+       
+       public QualifiedTypeReference(char[][] sources , TypeBinding type , long[] poss) {
+               
+               this(sources,poss);
+               this.resolvedType = type;
+       }
+       
+       public TypeReference copyDims(int dim){
+               //return a type reference copy of me with some dimensions
+               //warning : the new type ref has a null binding
+               return new ArrayQualifiedTypeReference(tokens,null,dim,sourcePositions) ;
+       }
+       
+       public TypeBinding getTypeBinding(Scope scope) {
+               
+               if (this.resolvedType != null)
+                       return this.resolvedType;
+               return scope.getType(tokens);
+       }
+       
+       public char[][] getTypeName(){
+       
+               return tokens;
+       }
+       
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+               
+               for (int i = 0; i < tokens.length; i++) {
+                       if (i > 0) output.append('.');
+                       output.append(tokens[i]);
+               }
+               return output;
+       }
+       
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+       
+       public void traverse(ASTVisitor visitor, ClassScope scope) {
+               
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Reference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Reference.java
new file mode 100644 (file)
index 0000000..41d498b
--- /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.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public abstract class Reference extends Expression  {
+/**
+ * BaseLevelReference constructor comment.
+ */
+public Reference() {
+       super();
+}
+public abstract FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound);
+
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+       return flowInfo;
+}
+public FieldBinding fieldBinding() {
+       //this method should be sent one FIELD-tagged references
+       //  (ref.bits & BindingIds.FIELD != 0)()
+       return null ;
+}
+public void fieldStore(CodeStream codeStream, FieldBinding fieldBinding, MethodBinding syntheticWriteAccessor, boolean valueRequired) {
+
+       if (fieldBinding.isStatic()) {
+               if (valueRequired) {
+                       if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
+                               codeStream.dup2();
+                       } else {
+                               codeStream.dup();
+                       }
+               }
+               if (syntheticWriteAccessor == null) {
+                       codeStream.putstatic(fieldBinding);
+               } else {
+                       codeStream.invokestatic(syntheticWriteAccessor);
+               }
+       } else { // Stack:  [owner][new field value]  ---> [new field value][owner][new field value]
+               if (valueRequired) {
+                       if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
+                               codeStream.dup2_x1();
+                       } else {
+                               codeStream.dup_x1();
+                       }
+               }
+               if (syntheticWriteAccessor == null) {
+                       codeStream.putfield(fieldBinding);
+               } else {
+                       codeStream.invokestatic(syntheticWriteAccessor);
+               }
+       }
+}
+public abstract void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired);
+
+public abstract void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired);
+
+public abstract void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired);
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
new file mode 100644 (file)
index 0000000..ca74dae
--- /dev/null
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ReturnStatement extends Statement {
+               
+       public Expression expression;
+       public TypeBinding expressionType;
+       public boolean isSynchronized;
+       public SubRoutineStatement[] subroutines;
+       public boolean isAnySubRoutineEscaping = false;
+       public LocalVariableBinding saveValueVariable;
+       
+       public ReturnStatement(Expression expr, int s, int e ) {
+               sourceStart = s;
+               sourceEnd = e;
+               expression = expr ;
+       }
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {      // here requires to generate a sequence of finally blocks invocations depending corresponding
+               // to each of the traversed try statements, so that execution will terminate properly.
+       
+               // lookup the label, this should answer the returnContext
+       
+               if (expression != null) {
+                       flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo);
+               }
+               // compute the return sequence (running the finally blocks)
+               FlowContext traversedContext = flowContext;
+               int subIndex = 0, maxSub = 5;
+               boolean saveValueNeeded = false;
+               boolean hasValueToSave = expression != null && expression.constant == NotAConstant;
+               do {
+                       SubRoutineStatement sub;
+                       if ((sub = traversedContext.subRoutine()) != null) {
+                               if (this.subroutines == null){
+                                       this.subroutines = new SubRoutineStatement[maxSub];
+                               }
+                               if (subIndex == maxSub) {
+                                       System.arraycopy(this.subroutines, 0, (this.subroutines = new SubRoutineStatement[maxSub *= 2]), 0, subIndex); // grow
+                               }
+                               this.subroutines[subIndex++] = sub;
+                               if (sub.isSubRoutineEscaping()) {
+                                       saveValueNeeded = false;
+                                       isAnySubRoutineEscaping = true;
+                                       break;
+                               }
+                       }
+                       traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+       
+                       ASTNode node;
+                       if ((node = traversedContext.associatedNode) instanceof SynchronizedStatement) {
+                               isSynchronized = true;
+       
+                       } else if (node instanceof TryStatement) {
+                               TryStatement tryStatement = (TryStatement) node;
+                               flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
+                               if (hasValueToSave) {
+                                       if (this.saveValueVariable == null){ // closest subroutine secret variable is used
+                                               prepareSaveValueLocation(tryStatement);
+                                       }
+                                       saveValueNeeded = true;
+                               }
+       
+                       } else if (traversedContext instanceof InitializationFlowContext) {
+                                       currentScope.problemReporter().cannotReturnInInitializer(this);
+                                       return FlowInfo.DEAD_END;
+                       }
+               } while ((traversedContext = traversedContext.parent) != null);
+               
+               // resize subroutines
+               if ((subroutines != null) && (subIndex != maxSub)) {
+                       System.arraycopy(subroutines, 0, (subroutines = new SubRoutineStatement[subIndex]), 0, subIndex);
+               }
+       
+               // secret local variable for return value (note that this can only occur in a real method)
+               if (saveValueNeeded) {
+                       if (this.saveValueVariable != null) {
+                               this.saveValueVariable.useFlag = LocalVariableBinding.USED;
+                       }
+               } else {
+                       this.saveValueVariable = null;
+                       if ((!isSynchronized) && (expressionType == BooleanBinding)) {
+                               this.expression.bits |= ValueForReturnMASK;
+                       }
+               }
+               return FlowInfo.DEAD_END;
+       }
+        
+       /**
+        * Retrun statement code generation
+        *
+        *   generate the finallyInvocationSequence.
+        *
+        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+        * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+               if ((bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               int pc = codeStream.position;
+               // generate the expression
+               if ((expression != null) && (expression.constant == NotAConstant)) {
+                       expression.generateCode(currentScope, codeStream, needValue()); // no value needed if non-returning subroutine
+                       generateStoreSaveValueIfNecessary(codeStream);
+               }
+               
+               // generation of code responsible for invoking the finally blocks in sequence
+               if (subroutines != null) {
+                       for (int i = 0, max = subroutines.length; i < max; i++) {
+                               SubRoutineStatement sub = subroutines[i];
+                               sub.generateSubRoutineInvocation(currentScope, codeStream);
+                               if (sub.isSubRoutineEscaping()) {
+                                               codeStream.recordPositionsFrom(pc, this.sourceStart);
+                                               SubRoutineStatement.reenterExceptionHandlers(subroutines, i, codeStream);
+                                               return;
+                               }
+                               sub.exitAnyExceptionHandler();
+                       }
+               }
+               if (saveValueVariable != null) codeStream.load(saveValueVariable);
+               
+               if ((expression != null) && (expression.constant != NotAConstant)) {
+                       codeStream.generateConstant(expression.constant, expression.implicitConversion);
+                       generateStoreSaveValueIfNecessary(codeStream);          
+               }
+               // output the suitable return bytecode or wrap the value inside a descriptor for doits
+               this.generateReturnBytecode(codeStream);
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+               SubRoutineStatement.reenterExceptionHandlers(subroutines, -1, codeStream);
+       }
+       /**
+        * Dump the suitable return bytecode for a return statement
+        *
+        */
+       public void generateReturnBytecode(CodeStream codeStream) {
+       
+               if (expression == null) {
+                       codeStream.return_();
+               } else {
+                       switch (expression.implicitConversion >> 4) {
+                               case T_boolean :
+                               case T_int :
+                                       codeStream.ireturn();
+                                       break;
+                               case T_float :
+                                       codeStream.freturn();
+                                       break;
+                               case T_long :
+                                       codeStream.lreturn();
+                                       break;
+                               case T_double :
+                                       codeStream.dreturn();
+                                       break;
+                               default :
+                                       codeStream.areturn();
+                       }
+               }
+       }
+       public void generateStoreSaveValueIfNecessary(CodeStream codeStream){
+               if (saveValueVariable != null) codeStream.store(saveValueVariable, false);
+       }
+       public boolean needValue(){
+               return (subroutines == null) || (saveValueVariable != null) || isSynchronized;
+       }
+       public void prepareSaveValueLocation(TryStatement targetTryStatement){
+                       
+               this.saveValueVariable = targetTryStatement.secretReturnValue;
+       }
+       public StringBuffer printStatement(int tab, StringBuffer output){
+       
+               printIndent(tab, output).append("return "); //$NON-NLS-1$
+               if (expression != null )
+                       expression.printExpression(0, output) ;
+               return output.append(';');
+       }
+       public void resolve(BlockScope scope) {
+               MethodScope methodScope = scope.methodScope();
+               MethodBinding methodBinding;
+               TypeBinding methodType =
+                       (methodScope.referenceContext instanceof AbstractMethodDeclaration)
+                               ? ((methodBinding = ((AbstractMethodDeclaration) methodScope.referenceContext).binding) == null 
+                                       ? null 
+                                       : methodBinding.returnType)
+                               : VoidBinding;
+               if (methodType == VoidBinding) {
+                       // the expression should be null
+                       if (expression == null)
+                               return;
+                       if ((expressionType = expression.resolveType(scope)) != null)
+                               scope.problemReporter().attemptToReturnNonVoidExpression(this, expressionType);
+                       return;
+               }
+               if (expression == null) {
+                       if (methodType != null) scope.problemReporter().shouldReturn(methodType, this);
+                       return;
+               }
+               if ((expressionType = expression.resolveType(scope)) == null)
+                       return;
+       
+               if (methodType != null && expression.isConstantValueOfTypeAssignableToType(expressionType, methodType)) {
+                       // dealing with constant
+                       expression.implicitWidening(methodType, expressionType);
+                       return;
+               }
+               if (expressionType == VoidBinding) {
+                       scope.problemReporter().attemptToReturnVoidValue(this);
+                       return;
+               }
+               if (methodType != null && expressionType.isCompatibleWith(methodType)) {
+                       expression.implicitWidening(methodType, expressionType);
+                       return;
+               }
+               if (methodType != null){
+                       scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionType, methodType);
+               }
+       }
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               if (visitor.visit(this, scope)) {
+                       if (expression != null)
+                               expression.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
new file mode 100644 (file)
index 0000000..908732b
--- /dev/null
@@ -0,0 +1,687 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+public class SingleNameReference extends NameReference implements OperatorIds {
+       public char[] token;
+
+       public MethodBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor
+       public static final int READ = 0;
+       public static final int WRITE = 1;
+       
+       public SingleNameReference(char[] source, long pos) {
+               super();
+               token = source;
+               sourceStart = (int) (pos >>> 32);
+               sourceEnd = (int) pos;
+       }
+       public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
+       
+               boolean isReachable = flowInfo.isReachable();
+               // compound assignment extra work
+               if (isCompound) { // check the variable part is initialized if blank final
+                       switch (bits & RestrictiveFlagMASK) {
+                               case FIELD : // reading a field
+                                       FieldBinding fieldBinding;
+                                       if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
+                                                       && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
+                                               if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
+                                                       currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
+                                               }
+                                       }
+                                       manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+                                       break;
+                               case LOCAL : // reading a local variable
+                                       // check if assigning a final blank field
+                                       LocalVariableBinding localBinding;
+                                       if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+                                               currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
+                                               // we could improve error msg here telling "cannot use compound assignment on final local variable"
+                                       }
+                                       if (isReachable) {
+                                               localBinding.useFlag = LocalVariableBinding.USED;
+                                       } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
+                                               localBinding.useFlag = LocalVariableBinding.FAKE_USED;
+                                       }
+                       }
+               }
+               if (assignment.expression != null) {
+                       flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+               }
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // assigning to a field
+                               manageSyntheticWriteAccessIfNecessary(currentScope, flowInfo);
+       
+                               // check if assigning a final field
+                               FieldBinding fieldBinding;
+                               if ((fieldBinding = (FieldBinding) binding).isFinal()) {
+                                       // inside a context where allowed
+                                       if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
+                                               if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
+                                                       currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
+                                               } else {
+                                                       flowContext.recordSettingFinal(fieldBinding, this, flowInfo);                                           
+                                               }
+                                               flowInfo.markAsDefinitelyAssigned(fieldBinding);
+                                       } else {
+                                               currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
+                                       }
+                               }
+                               break;
+                       case LOCAL : // assigning to a local variable 
+                               LocalVariableBinding localBinding = (LocalVariableBinding) binding;
+                               if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
+                                       bits |= FirstAssignmentToLocalMASK;
+                               } else {
+                                       bits &= ~FirstAssignmentToLocalMASK;
+                               }
+                               if (localBinding.isFinal()) {
+                                       if ((bits & DepthMASK) == 0) {
+                                               // tolerate assignment to final local in unreachable code (45674)
+                                               if ((isReachable && isCompound) || !localBinding.isBlankFinal()){
+                                                       currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this);
+                                               } else if (flowInfo.isPotentiallyAssigned(localBinding)) {
+                                                       currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
+                                               } else {
+                                                       flowContext.recordSettingFinal(localBinding, this, flowInfo);                                                           
+                                               }
+                                       } else {
+                                               currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
+                                       }
+                               }
+                               flowInfo.markAsDefinitelyAssigned(localBinding);
+               }
+               manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+               return flowInfo;
+       }
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+               return analyseCode(currentScope, flowContext, flowInfo, true);
+       }
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
+       
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // reading a field
+                               if (valueRequired) {
+                                       manageSyntheticReadAccessIfNecessary(currentScope, flowInfo);
+                               }
+                               // check if reading a final blank field
+                               FieldBinding fieldBinding;
+                               if ((fieldBinding = (FieldBinding) binding).isBlankFinal() 
+                                               && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
+                                       if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
+                                               currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
+                                       }
+                               }
+                               break;
+                       case LOCAL : // reading a local variable
+                               LocalVariableBinding localBinding;
+                               if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+                                       currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
+                               }
+                               if (flowInfo.isReachable()) {
+                                       localBinding.useFlag = LocalVariableBinding.USED;
+                               } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) {
+                                       localBinding.useFlag = LocalVariableBinding.FAKE_USED;
+                               }
+               }
+               if (valueRequired) {
+                       manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+               }
+               return flowInfo;
+       }
+       public TypeBinding checkFieldAccess(BlockScope scope) {
+       
+               FieldBinding fieldBinding = (FieldBinding) binding;
+               
+               bits &= ~RestrictiveFlagMASK; // clear bits
+               bits |= FIELD;
+               if (!((FieldBinding) binding).isStatic()) {
+                       // must check for the static status....
+                       if (scope.methodScope().isStatic) {
+                               scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding);
+                               constant = NotAConstant;
+                               return fieldBinding.type;
+                       }
+               }
+               constant = FieldReference.getConstantFor(fieldBinding, this, true, scope);
+       
+               if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssignedMASK) !=0))
+                       scope.problemReporter().deprecatedField(fieldBinding, this);
+       
+               MethodScope ms = scope.methodScope();
+               if ((this.bits & IsStrictlyAssignedMASK) == 0
+                       && ms.enclosingSourceType() == fieldBinding.declaringClass
+                       && ms.lastVisibleFieldID >= 0
+                       && fieldBinding.id >= ms.lastVisibleFieldID) {
+                       //if the field is static and ms is not .... then it is valid
+                       if (!fieldBinding.isStatic() || ms.isStatic)
+                               scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
+               }
+               //====================================================
+       
+               return fieldBinding.type;
+       
+       }
+       public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
+       
+               // optimizing assignment like: i = i + 1 or i = 1 + i
+               if (assignment.expression.isCompactableOperation()) {
+                       BinaryExpression operation = (BinaryExpression) assignment.expression;
+                       SingleNameReference variableReference;
+                       if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == binding)) {
+                               // i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
+                               variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT, operation.left.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
+                               return;
+                       }
+                       int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
+                       if ((operation.right instanceof SingleNameReference)
+                               && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
+                               && ((variableReference = (SingleNameReference) operation.right).binding == binding)
+                               && (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
+                               && ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
+                               && ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
+                               // i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
+                               variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
+                               return;
+                       }
+               }
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // assigning to a field
+                               FieldBinding fieldBinding;
+                               if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
+                                       if ((bits & DepthMASK) != 0) {
+                                               ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+                                               Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+                                               codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+                                       } else {
+                                               this.generateReceiver(codeStream);
+                                       }
+                               }
+                               assignment.expression.generateCode(currentScope, codeStream, true);
+                               fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], valueRequired);
+                               if (valueRequired) {
+                                       codeStream.generateImplicitConversion(assignment.implicitConversion);
+                               }
+                               return;
+                       case LOCAL : // assigning to a local variable
+                               LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+                               if (localBinding.resolvedPosition != -1) {
+                                       assignment.expression.generateCode(currentScope, codeStream, true);
+                               } else {
+                                       if (assignment.expression.constant != NotAConstant) {
+                                               // assigning an unused local to a constant value = no actual assignment is necessary
+                                               if (valueRequired) {
+                                                       codeStream.generateConstant(assignment.expression.constant, assignment.implicitConversion);
+                                               }
+                                       } else {
+                                               assignment.expression.generateCode(currentScope, codeStream, true);
+                                               /* Even though the value may not be required, we force it to be produced, and discard it later
+                                               on if it was actually not necessary, so as to provide the same behavior as JDK1.2beta3. */
+                                               if (valueRequired) {
+                                                       codeStream.generateImplicitConversion(assignment.implicitConversion); // implicit conversion
+                                               } else {
+                                                       if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
+                                                               codeStream.pop2();
+                                                       } else {
+                                                               codeStream.pop();
+                                                       }
+                                               }
+                                       }
+                                       return;
+                               }
+                               // 26903, need extra cast to store null in array local var      
+                               if (localBinding.type.isArrayType() 
+                                       && (assignment.expression.resolvedType == NullBinding   // arrayLoc = null
+                                               || ((assignment.expression instanceof CastExpression)   // arrayLoc = (type[])null
+                                                       && (((CastExpression)assignment.expression).innermostCastedExpression().resolvedType == NullBinding)))){
+                                       codeStream.checkcast(localBinding.type); 
+                               }
+                               
+                               // normal local assignment (since cannot store in outer local which are final locations)
+                               codeStream.store(localBinding, valueRequired);
+                               if ((bits & FirstAssignmentToLocalMASK) != 0) { // for local variable debug attributes
+                                       localBinding.recordInitializationStartPC(codeStream.position);
+                               }
+                               // implicit conversion
+                               if (valueRequired) {
+                                       codeStream.generateImplicitConversion(assignment.implicitConversion);
+                               }
+               }
+       }
+       public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+               int pc = codeStream.position;
+               if (constant != NotAConstant) {
+                       if (valueRequired) {
+                               codeStream.generateConstant(constant, implicitConversion);
+                       }
+               } else {
+                       switch (bits & RestrictiveFlagMASK) {
+                               case FIELD : // reading a field
+                                       FieldBinding fieldBinding;
+                                       if (valueRequired) {
+                                               if ((fieldBinding = (FieldBinding) this.codegenBinding).constant == NotAConstant) { // directly use inlined value for constant fields
+                                                       boolean isStatic;
+                                                       if (!(isStatic = fieldBinding.isStatic())) {
+                                                               if ((bits & DepthMASK) != 0) {
+                                                                       ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+                                                                       Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+                                                                       codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+                                                               } else {
+                                                                       generateReceiver(codeStream);
+                                                               }
+                                                       }
+                                                       // managing private access                                                      
+                                                       if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+                                                               if (isStatic) {
+                                                                       codeStream.getstatic(fieldBinding);
+                                                               } else {
+                                                                       codeStream.getfield(fieldBinding);
+                                                               }
+                                                       } else {
+                                                               codeStream.invokestatic(syntheticAccessors[READ]);
+                                                       }
+                                                       codeStream.generateImplicitConversion(implicitConversion);
+                                               } else { // directly use the inlined value
+                                                       codeStream.generateConstant(fieldBinding.constant, implicitConversion);
+                                               }
+                                       }
+                                       break;
+                               case LOCAL : // reading a local
+                                       LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+                                       if (valueRequired) {
+                                               // outer local?
+                                               if ((bits & DepthMASK) != 0) {
+                                                       // outer local can be reached either through a synthetic arg or a synthetic field
+                                                       VariableBinding[] path = currentScope.getEmulationPath(localBinding);
+                                                       codeStream.generateOuterAccess(path, this, localBinding, currentScope);
+                                               } else {
+                                                       // regular local variable read
+                                                       codeStream.load(localBinding);
+                                               }
+                                               codeStream.generateImplicitConversion(implicitConversion);
+                                       }
+                       }
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+       /*
+        * Regular API for compound assignment, relies on the fact that there is only one reference to the
+        * variable, which carries both synthetic read/write accessors.
+        * The APIs with an extra argument is used whenever there are two references to the same variable which
+        * are optimized in one access: e.g "a = a + 1" optimized into "a++".
+        */
+       public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
+       
+               this.generateCompoundAssignment(
+                       currentScope, 
+                       codeStream, 
+                       syntheticAccessors == null ? null : syntheticAccessors[WRITE],
+                       expression,
+                       operator, 
+                       assignmentImplicitConversion, 
+                       valueRequired);
+       }
+       /*
+        * The APIs with an extra argument is used whenever there are two references to the same variable which
+        * are optimized in one access: e.g "a = a + 1" optimized into "a++".
+        */
+       public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, MethodBinding writeAccessor, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // assigning to a field
+                               FieldBinding fieldBinding;
+                               if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
+                                       if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+                                               codeStream.getstatic(fieldBinding);
+                                       } else {
+                                               codeStream.invokestatic(syntheticAccessors[READ]);
+                                       }
+                               } else {
+                                       if ((bits & DepthMASK) != 0) {
+                                               ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+                                               Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+                                               codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+                                       } else {
+                                               codeStream.aload_0();
+                                       }
+                                       codeStream.dup();
+                                       if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+                                               codeStream.getfield(fieldBinding);
+                                       } else {
+                                               codeStream.invokestatic(syntheticAccessors[READ]);
+                                       }
+                               }
+                               break;
+                       case LOCAL : // assigning to a local variable (cannot assign to outer local)
+                               LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+                               Constant assignConstant;
+                               int increment;
+                               // using incr bytecode if possible
+                               switch (localBinding.type.id) {
+                                       case T_String :
+                                               codeStream.generateStringAppend(currentScope, this, expression);
+                                               if (valueRequired) {
+                                                       codeStream.dup();
+                                               }
+                                               codeStream.store(localBinding, false);
+                                               return;
+                                       case T_int :
+                                               if (((assignConstant = expression.constant) != NotAConstant) 
+                                                       && (assignConstant.typeID() != T_float) // only for integral types
+                                                       && (assignConstant.typeID() != T_double)
+                                                       && ((increment = assignConstant.intValue()) == (short) increment)) { // 16 bits value
+                                                       switch (operator) {
+                                                               case PLUS :
+                                                                       codeStream.iinc(localBinding.resolvedPosition, increment);
+                                                                       if (valueRequired) {
+                                                                               codeStream.load(localBinding);
+                                                                       }
+                                                                       return;
+                                                               case MINUS :
+                                                                       codeStream.iinc(localBinding.resolvedPosition, -increment);
+                                                                       if (valueRequired) {
+                                                                               codeStream.load(localBinding);
+                                                                       }
+                                                                       return;
+                                                       }
+                                               }
+                                       default :
+                                               codeStream.load(localBinding);
+                               }
+               }
+               // perform the actual compound operation
+               int operationTypeID;
+               if ((operationTypeID = implicitConversion >> 4) == T_String || operationTypeID == T_Object) {
+                       // we enter here if the single name reference is a field of type java.lang.String or if the type of the 
+                       // operation is java.lang.Object
+                       // For example: o = o + ""; // where the compiled type of o is java.lang.Object.
+                       codeStream.generateStringAppend(currentScope, null, expression);
+               } else {
+                       // promote the array reference to the suitable operation type
+                       codeStream.generateImplicitConversion(implicitConversion);
+                       // generate the increment value (will by itself  be promoted to the operation value)
+                       if (expression == IntLiteral.One){ // prefix operation
+                               codeStream.generateConstant(expression.constant, implicitConversion);                   
+                       } else {
+                               expression.generateCode(currentScope, codeStream, true);
+                       }               
+                       // perform the operation
+                       codeStream.sendOperator(operator, operationTypeID);
+                       // cast the value back to the array reference type
+                       codeStream.generateImplicitConversion(assignmentImplicitConversion);
+               }
+               // store the result back into the variable
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // assigning to a field
+                               fieldStore(codeStream, (FieldBinding) this.codegenBinding, writeAccessor, valueRequired);
+                               return;
+                       case LOCAL : // assigning to a local variable
+                               LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+                               if (valueRequired) {
+                                       if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
+                                               codeStream.dup2();
+                                       } else {
+                                               codeStream.dup();
+                                       }
+                               }
+                               codeStream.store(localBinding, false);
+               }
+       }
+       
+       public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
+               switch (bits & RestrictiveFlagMASK) {
+                       case FIELD : // assigning to a field
+                               FieldBinding fieldBinding;
+                               if ((fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) {
+                                       if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+                                               codeStream.getstatic(fieldBinding);
+                                       } else {
+                                               codeStream.invokestatic(syntheticAccessors[READ]);
+                                       }
+                               } else {
+                                       if ((bits & DepthMASK) != 0) {
+                                               ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT);
+                                               Object[] emulationPath = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/);
+                                               codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope);
+                                       } else {
+                                               codeStream.aload_0();
+                                       }
+                                       codeStream.dup();
+                                       if ((syntheticAccessors == null) || (syntheticAccessors[READ] == null)) {
+                                               codeStream.getfield(fieldBinding);
+                                       } else {
+                                               codeStream.invokestatic(syntheticAccessors[READ]);
+                                       }
+                               }
+                               if (valueRequired) {
+                                       if (fieldBinding.isStatic()) {
+                                               if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
+                                                       codeStream.dup2();
+                                               } else {
+                                                       codeStream.dup();
+                                               }
+                                       } else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
+                                               if ((fieldBinding.type == LongBinding) || (fieldBinding.type == DoubleBinding)) {
+                                                       codeStream.dup2_x1();
+                                               } else {
+                                                       codeStream.dup_x1();
+                                               }
+                                       }
+                               }
+                               codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+                               codeStream.sendOperator(postIncrement.operator, fieldBinding.type.id);
+                               codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
+                               fieldStore(codeStream, fieldBinding, syntheticAccessors == null ? null : syntheticAccessors[WRITE], false);
+                               return;
+                       case LOCAL : // assigning to a local variable
+                               LocalVariableBinding localBinding = (LocalVariableBinding) this.codegenBinding;
+                               // using incr bytecode if possible
+                               if (localBinding.type == IntBinding) {
+                                       if (valueRequired) {
+                                               codeStream.load(localBinding);
+                                       }
+                                       if (postIncrement.operator == PLUS) {
+                                               codeStream.iinc(localBinding.resolvedPosition, 1);
+                                       } else {
+                                               codeStream.iinc(localBinding.resolvedPosition, -1);
+                                       }
+                               } else {
+                                       codeStream.load(localBinding);
+                                       if (valueRequired){
+                                               if ((localBinding.type == LongBinding) || (localBinding.type == DoubleBinding)) {
+                                                       codeStream.dup2();
+                                               } else {
+                                                       codeStream.dup();
+                                               }
+                                       }
+                                       codeStream.generateConstant(postIncrement.expression.constant, implicitConversion);
+                                       codeStream.sendOperator(postIncrement.operator, localBinding.type.id);
+                                       codeStream.generateImplicitConversion(postIncrement.assignmentImplicitConversion);
+       
+                                       codeStream.store(localBinding, false);
+                               }
+               }
+       }
+       
+       public void generateReceiver(CodeStream codeStream) {
+               
+               codeStream.aload_0();
+       }
+       
+       public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+       
+               if (!flowInfo.isReachable()) return;
+               //If inlinable field, forget the access emulation, the code gen will directly target it
+               if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) return;
+       
+               if ((bits & RestrictiveFlagMASK) == LOCAL) {
+                       currentScope.emulateOuterAccess((LocalVariableBinding) binding);
+               }
+       }
+       public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+       
+               if (!flowInfo.isReachable()) return;
+       
+               //If inlinable field, forget the access emulation, the code gen will directly target it
+               if (constant != NotAConstant)
+                       return;
+       
+               if ((bits & FIELD) != 0) {
+                       FieldBinding fieldBinding = (FieldBinding) binding;
+                       if (((bits & DepthMASK) != 0)
+                               && (fieldBinding.isPrivate() // private access
+                                       || (fieldBinding.isProtected() // implicit protected access
+                                                       && fieldBinding.declaringClass.getPackage() 
+                                                               != currentScope.enclosingSourceType().getPackage()))) {
+                               if (syntheticAccessors == null)
+                                       syntheticAccessors = new MethodBinding[2];
+                               syntheticAccessors[READ] = 
+                                       ((SourceTypeBinding)currentScope.enclosingSourceType().
+                                               enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
+                                                       addSyntheticMethod(fieldBinding, true);
+                               currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+                               return;
+                       }
+                       // if the binding declaring class is not visible, need special action
+                       // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+                       // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+                       // and not from Object or implicit static field access. 
+                       if (fieldBinding.declaringClass != this.actualReceiverType
+                               && !this.actualReceiverType.isArrayType()       
+                               && fieldBinding.declaringClass != null
+                               && fieldBinding.constant == NotAConstant
+                               && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+                                               && !fieldBinding.isStatic()
+                                               && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+                                       || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+                               this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+                       }
+               }
+       }
+       public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+       
+               if (!flowInfo.isReachable()) return;
+               if ((bits & FIELD) != 0) {
+                       FieldBinding fieldBinding = (FieldBinding) binding;
+                       if (((bits & DepthMASK) != 0) 
+                               && (fieldBinding.isPrivate() // private access
+                                       || (fieldBinding.isProtected() // implicit protected access
+                                                       && fieldBinding.declaringClass.getPackage() 
+                                                               != currentScope.enclosingSourceType().getPackage()))) {
+                               if (syntheticAccessors == null)
+                                       syntheticAccessors = new MethodBinding[2];
+                               syntheticAccessors[WRITE] = 
+                                       ((SourceTypeBinding)currentScope.enclosingSourceType().
+                                               enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
+                                                       addSyntheticMethod(fieldBinding, false);
+                               currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+                               return;
+                       }
+                       // if the binding declaring class is not visible, need special action
+                       // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+                       // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type
+                       // and not from Object or implicit static field access. 
+                       if (fieldBinding.declaringClass != this.actualReceiverType
+                               && !this.actualReceiverType.isArrayType()       
+                               && fieldBinding.declaringClass != null
+                               && fieldBinding.constant == NotAConstant
+                               && ((currentScope.environment().options.targetJDK >= ClassFileConstants.JDK1_2 
+                                               && !fieldBinding.isStatic()
+                                               && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+                                       || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+                               this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+                       }
+               }
+       }
+       public StringBuffer printExpression(int indent, StringBuffer output){
+       
+               return output.append(token);
+       }
+       
+       public TypeBinding reportError(BlockScope scope) {
+               
+               //=====error cases=======
+               constant = Constant.NotAConstant;
+               if (binding instanceof ProblemFieldBinding) {
+                       scope.problemReporter().invalidField(this, (FieldBinding) binding);
+               } else if (binding instanceof ProblemReferenceBinding) {
+                       scope.problemReporter().invalidType(this, (TypeBinding) binding);
+               } else {
+                       scope.problemReporter().unresolvableReference(this, binding);
+               }
+               return null;
+       }
+       public TypeBinding resolveType(BlockScope scope) {
+               // for code gen, harm the restrictiveFlag       
+       
+               this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
+               
+               if ((this.codegenBinding = this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this, true /*resolve*/)).isValidBinding()) {
+                       switch (bits & RestrictiveFlagMASK) {
+                               case VARIABLE : // =========only variable============
+                               case VARIABLE | TYPE : //====both variable and type============
+                                       if (binding instanceof VariableBinding) {
+                                               VariableBinding variable = (VariableBinding) binding;
+                                               if (binding instanceof LocalVariableBinding) {
+                                                       bits &= ~RestrictiveFlagMASK;  // clear bits
+                                                       bits |= LOCAL;
+                                                       if ((this.bits & IsStrictlyAssignedMASK) == 0) {
+                                                               constant = variable.constant;
+                                                       } else {
+                                                               constant = NotAConstant;
+                                                       }
+                                                       if (!variable.isFinal() && (bits & DepthMASK) != 0) {
+                                                               scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)variable, this);
+                                                       }
+                                                       return this.resolvedType = variable.type;
+                                               }
+                                               // a field
+                                               FieldBinding field = (FieldBinding) this.binding;
+                                               if (!field.isStatic() && scope.environment().options.getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) {
+                                                       scope.problemReporter().unqualifiedFieldAccess(this, field);
+                                               }
+                                               return this.resolvedType = checkFieldAccess(scope);
+                                       }
+       
+                                       // thus it was a type
+                                       bits &= ~RestrictiveFlagMASK;  // clear bits
+                                       bits |= TYPE;
+                               case TYPE : //========only type==============
+                                       constant = Constant.NotAConstant;
+                                       //deprecated test
+                                       if (isTypeUseDeprecated((TypeBinding) binding, scope))
+                                               scope.problemReporter().deprecatedType((TypeBinding) binding, this);
+                                       return this.resolvedType = (TypeBinding) binding;
+                       }
+               }
+       
+               // error scenarii
+               return this.resolvedType = this.reportError(scope);
+       }
+               
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+       
+       public String unboundReferenceErrorName(){
+       
+               return new String(token);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
new file mode 100644 (file)
index 0000000..4d29467
--- /dev/null
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SingleTypeReference extends TypeReference {
+
+       public char[] token;
+
+       public SingleTypeReference(char[] source, long pos) {
+
+                       token = source;
+                       sourceStart = (int) (pos>>>32)  ;
+                       sourceEnd = (int) (pos & 0x00000000FFFFFFFFL) ;
+               
+       }
+
+       public SingleTypeReference(char[] source ,TypeBinding type, long pos) {
+               this(source, pos) ;
+               this.resolvedType = type ;
+       }
+
+       public TypeReference copyDims(int dim){
+               //return a type reference copy of me with some dimensions
+               //warning : the new type ref has a null binding
+               
+               return new ArrayTypeReference(token,null,dim,(((long)sourceStart)<<32)+sourceEnd) ;
+       }
+
+       public TypeBinding getTypeBinding(Scope scope) {
+               if (this.resolvedType != null)
+                       return this.resolvedType;
+               return scope.getType(token);
+       }
+
+       public char [][] getTypeName() {
+               return new char[][] { token };
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output){
+               
+               return output.append(token);
+       }
+
+       public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+
+               ReferenceBinding memberTb = scope.getMemberType(token, enclosingType);
+               if (!memberTb.isValidBinding()) {
+                       scope.problemReporter().invalidEnclosingType(this, memberTb, enclosingType);
+                       return null;
+               }
+               if (isTypeUseDeprecated(memberTb, scope))
+                       scope.problemReporter().deprecatedType(memberTb, this);
+               return this.resolvedType = memberTb;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+
+       public void traverse(ASTVisitor visitor, ClassScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/Statement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/Statement.java
new file mode 100644 (file)
index 0000000..2e240f7
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public abstract class Statement extends ASTNode {
+       
+       public abstract FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo);
+       
+       /**
+        * INTERNAL USE ONLY.
+        * This is used to redirect inter-statements jumps.
+        */
+       public void branchChainTo(Label label) {
+               // do nothing by default
+       }
+       
+       // Report an error if necessary
+       public boolean complainIfUnreachable(FlowInfo flowInfo, BlockScope scope, boolean didAlreadyComplain) {
+       
+               if ((flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0) {
+                       this.bits &= ~ASTNode.IsReachableMASK;
+                       boolean reported = flowInfo == FlowInfo.DEAD_END;
+                       if (!didAlreadyComplain && reported) {
+                               scope.problemReporter().unreachableCode(this);
+                       }
+                       return reported; // keep going for fake reachable
+               }
+               return false;
+       }
+       
+       public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
+       
+       public boolean isEmptyBlock() {
+               return false;
+       }
+       
+       public boolean isValidJavaStatement() {
+               //the use of this method should be avoid in most cases
+               //and is here mostly for documentation purpose.....
+               //while the parser is responsable for creating
+               //welled formed expression statement, which results
+               //in the fact that java-non-semantic-expression-used-as-statement
+               //should not be parsable...thus not being built.
+               //It sounds like the java grammar as help the compiler job in removing
+               //-by construction- some statement that would have no effect....
+               //(for example all expression that may do side-effects are valid statement
+               // -this is an appromative idea.....-)
+
+               return true;
+       }
+       
+       public StringBuffer print(int indent, StringBuffer output) {
+               return printStatement(indent, output);
+       }
+       public abstract StringBuffer printStatement(int indent, StringBuffer output);
+
+       public abstract void resolve(BlockScope scope);
+       
+       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;
+       }
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/StringLiteral.java
new file mode 100644 (file)
index 0000000..833b5d5
--- /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.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class StringLiteral extends Literal {
+
+       char[] source;
+
+       public StringLiteral(char[] token, int s, int e) {
+
+               this(s,e);
+               source = token;
+       }
+
+       public StringLiteral(int s, int e) {
+
+               super(s,e);
+       }
+
+       public void computeConstant() {
+       
+               constant = Constant.fromValue(String.valueOf(source));
+       }
+
+       public ExtendedStringLiteral extendWith(CharLiteral lit){
+
+               //add the lit source to mine, just as if it was mine
+               return new ExtendedStringLiteral(this,lit);
+       }
+
+       public ExtendedStringLiteral extendWith(StringLiteral lit){
+
+               //add the lit source to mine, just as if it was mine
+               return new ExtendedStringLiteral(this,lit);
+       }
+
+       /**
+        *  Add the lit source to mine, just as if it was mine
+        */
+       public StringLiteralConcatenation extendsWith(StringLiteral lit) {
+               return new StringLiteralConcatenation(this, lit);
+       }
+       /**
+        * Code generation for string literal
+        */ 
+       public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+
+               int pc = codeStream.position;
+               if (valueRequired)
+                       codeStream.ldc(constant.stringValue());
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public TypeBinding literalType(BlockScope scope) {
+
+               return scope.getJavaLangString();
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+       
+               // handle some special char.....
+               output.append('\"');
+               for (int i = 0; i < source.length; i++) {
+                       switch (source[i]) {
+                               case '\b' :
+                                       output.append("\\b"); //$NON-NLS-1$
+                                       break;
+                               case '\t' :
+                                       output.append("\\t"); //$NON-NLS-1$
+                                       break;
+                               case '\n' :
+                                       output.append("\\n"); //$NON-NLS-1$
+                                       break;
+                               case '\f' :
+                                       output.append("\\f"); //$NON-NLS-1$
+                                       break;
+                               case '\r' :
+                                       output.append("\\r"); //$NON-NLS-1$
+                                       break;
+                               case '\"' :
+                                       output.append("\\\""); //$NON-NLS-1$
+                                       break;
+                               case '\'' :
+                                       output.append("\\'"); //$NON-NLS-1$
+                                       break;
+                               case '\\' : //take care not to display the escape as a potential real char
+                                       output.append("\\\\"); //$NON-NLS-1$
+                                       break;
+                               default :
+                                       output.append(source[i]);
+                       }
+               }
+               output.append('\"'); 
+               return output;
+       }
+
+       public char[] source() {
+
+               return source;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               visitor.visit(this, scope);
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java b/src/java/org/eclipse/jdt/internal/compiler/ast/StringLiteralConcatenation.java
new file mode 100644 (file)
index 0000000..77ee9cc
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Flatten string literal
+ */
+public class StringLiteralConcatenation extends StringLiteral {
+       private static final int INITIAL_SIZE = 5;
+       public StringLiteral[] literals;
+       public int counter;
+       /**     
+        * Build a two-strings literal
+        * */
+       public StringLiteralConcatenation(StringLiteral str1, StringLiteral str2) {
+               super(str1.sourceStart, str1.sourceEnd);
+               this.source = str1.source;
+               this.literals = new StringLiteral[INITIAL_SIZE];
+               this.counter = 0;
+               this.literals[this.counter++] = str1;
+               extendsWith(str2);
+       }
+
+       /**
+        *  Add the lit source to mine, just as if it was mine
+        */
+       public StringLiteralConcatenation extendsWith(StringLiteral lit) {
+               this.sourceEnd = lit.sourceEnd;
+               final int literalsLength = this.literals.length;
+               if (this.counter == literalsLength) {
+                       // resize
+                       System.arraycopy(this.literals, 0, this.literals = new StringLiteral[literalsLength + INITIAL_SIZE], 0, literalsLength);
+               }
+               //uddate the source
+               int length = source.length;
+               System.arraycopy(
+                       source,
+                       0,
+                       source = new char[length + lit.source.length],
+                       0,
+                       length);
+               System.arraycopy(lit.source, 0, source, length, lit.source.length);
+               this.literals[this.counter++] = lit;            
+               return this;
+       }
+       
+       public StringBuffer printExpression(int indent, StringBuffer output) {
+               output.append("StringLiteralConcatenation{"); //$NON-NLS-1$
+               for (int i = 0, max = this.counter; i < max; i++) {
+                       this.literals[i].printExpression(indent, output);
+                       output.append("+\n");//$NON-NLS-1$
+               }
+               return output.append('}');
+       }
+       
+       public char[] source() {
+               return source;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope scope) {
+               if (visitor.visit(this, scope)) {
+                       for (int i = 0, max = this.counter; i < max; i++) {
+                               this.literals[i].traverse(visitor, scope);
+                       }                       
+               }
+               visitor.endVisit(this, scope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/SubRoutineStatement.java
new file mode 100644 (file)
index 0000000..59b697b
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+
+/**
+ * Extra behavior for statements which are generating subroutines
+ */
+public abstract class SubRoutineStatement extends Statement {
+       
+       public static final ExceptionLabel[] NO_EXCEPTION_HANDLER = new ExceptionLabel[0];
+       ExceptionLabel[] anyExceptionLabels = NO_EXCEPTION_HANDLER;
+       int anyExceptionLabelsCount = 0;
+       
+       public abstract boolean isSubRoutineEscaping();
+
+       public abstract void generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream);
+       
+       public ExceptionLabel enterAnyExceptionHandler(CodeStream codeStream) {
+               
+               int length;
+               if ((length = this.anyExceptionLabelsCount) == this.anyExceptionLabels.length) {
+                       System.arraycopy(this.anyExceptionLabels, 0 , this.anyExceptionLabels=new ExceptionLabel[length*2 + 1], 0, length);
+               }
+               ExceptionLabel exceptionLabel = new ExceptionLabel(codeStream, null);
+               this.anyExceptionLabels[this.anyExceptionLabelsCount++] = exceptionLabel;
+               return exceptionLabel;
+       }
+
+       public void exitAnyExceptionHandler() {
+               if (this.anyExceptionLabelsCount == 0) return;
+               ExceptionLabel currentLabel = this.anyExceptionLabels[this.anyExceptionLabelsCount-1];
+               if (currentLabel.start == currentLabel.codeStream.position) {
+                       // discard empty exception handler
+                       this.anyExceptionLabels[--this.anyExceptionLabelsCount] = null;
+               }
+               currentLabel.placeEnd();
+       }
+       
+       public void placeAllAnyExceptionHandlers() {
+               
+               for (int i = 0; i < this.anyExceptionLabelsCount; i++) {
+                       this.anyExceptionLabels[i].place();
+               }
+       }
+       
+       public static void reenterExceptionHandlers(SubRoutineStatement[] subroutines, int max, CodeStream codeStream) {
+               if (subroutines == null) return;
+               if (max < 0) max = subroutines.length;
+               for (int i = 0; i < max; i++) {
+                       subroutines[i].enterAnyExceptionHandler(codeStream); 
+               }       
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/SuperReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/SuperReference.java
new file mode 100644 (file)
index 0000000..a877d12
--- /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.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class SuperReference extends ThisReference {
+       
+       public SuperReference(int sourceStart, int sourceEnd) {
+
+               super(sourceStart, sourceEnd);
+       }
+
+       public static ExplicitConstructorCall implicitSuperConstructorCall() {
+
+               return new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+       }
+
+       public boolean isImplicitThis() {
+               
+               return false;
+       }
+
+       public boolean isSuper() {
+               
+               return true;
+       }
+
+       public boolean isThis() {
+               
+               return false ;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output){
+       
+               return output.append("super"); //$NON-NLS-1$
+               
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+
+               constant = NotAConstant;
+               if (!checkAccess(scope.methodScope()))
+                       return null;
+               SourceTypeBinding enclosingTb = scope.enclosingSourceType();
+               if (enclosingTb.id == T_Object) {
+                       scope.problemReporter().cannotUseSuperInJavaLangObject(this);
+                       return null;
+               }
+               return this.resolvedType = enclosingTb.superclass;
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+               visitor.visit(this, blockScope);
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
new file mode 100644 (file)
index 0000000..65cddb1
--- /dev/null
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SwitchStatement extends Statement {
+
+       public Expression expression;
+       public Statement[] statements;
+       public BlockScope scope;
+       public int explicitDeclarations;
+       public Label breakLabel;
+       public CaseStatement[] cases;
+       public CaseStatement defaultCase;
+       public int caseCount = 0;
+       public int blockStart;
+       
+       // for local variables table attributes
+       int preSwitchInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+
+       public FlowInfo analyseCode(
+                       BlockScope currentScope,
+                       FlowContext flowContext,
+                       FlowInfo flowInfo) {
+
+           try {
+                       flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo);
+                       SwitchFlowContext switchContext =
+                               new SwitchFlowContext(flowContext, this, (breakLabel = new Label()));
+       
+                       // analyse the block by considering specially the case/default statements (need to bind them 
+                       // to the entry point)
+                       FlowInfo caseInits = FlowInfo.DEAD_END;
+                       // in case of statements before the first case
+                       preSwitchInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(flowInfo);
+                       int caseIndex = 0;
+                       if (statements != null) {
+                               boolean didAlreadyComplain = false;
+                               for (int i = 0, max = statements.length; i < max; i++) {
+                                       Statement statement = statements[i];
+                                       if ((caseIndex < caseCount) && (statement == cases[caseIndex])) { // statement is a case
+                                               this.scope.switchCase = cases[caseIndex]; // record entering in a switch case block
+                                               caseIndex++;
+                                               caseInits = caseInits.mergedWith(flowInfo.copy().unconditionalInits());
+                                               didAlreadyComplain = false; // reset complaint
+                                       } else if (statement == defaultCase) { // statement is the default case
+                                               this.scope.switchCase = defaultCase; // record entering in a switch case block
+                                               caseInits = caseInits.mergedWith(flowInfo.copy().unconditionalInits());
+                                               didAlreadyComplain = false; // reset complaint
+                                       }
+                                       if (!statement.complainIfUnreachable(caseInits, scope, didAlreadyComplain)) {
+                                               caseInits = statement.analyseCode(scope, switchContext, caseInits);
+                                       } else {
+                                               didAlreadyComplain = true;
+                                       }
+                               }
+                       }
+       
+                       // if no default case, then record it may jump over the block directly to the end
+                       if (defaultCase == null) {
+                               // only retain the potential initializations
+                               flowInfo.addPotentialInitializationsFrom(
+                                       caseInits.mergedWith(switchContext.initsOnBreak));
+                               mergedInitStateIndex =
+                                       currentScope.methodScope().recordInitializationStates(flowInfo);
+                               return flowInfo;
+                       }
+       
+                       // merge all branches inits
+                       FlowInfo mergedInfo = caseInits.mergedWith(switchContext.initsOnBreak);
+                       mergedInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(mergedInfo);
+                       return mergedInfo;
+           } finally {
+               if (this.scope != null) this.scope.switchCase = null; // no longer inside switch case block
+           }
+       }
+
+       /**
+        * Switch 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) {
+
+           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;
+                       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 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);
+       
+                                       } else {
+                                               codeStream.tableswitch(
+                                                       defaultLabel,
+                                                       min,
+                                                       max,
+                                                       constants,
+                                                       sortedIndexes,
+                                                       caseLabels);
+                                       }
+                               } else {
+                                       codeStream.lookupswitch(defaultLabel, 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 (preSwitchInitStateIndex != -1) {
+                                                       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 (preSwitchInitStateIndex != -1) {
+                                                               codeStream.removeNotDefinitelyAssignedVariables(
+                                                                       currentScope,
+                                                                       preSwitchInitStateIndex);
+                                                       }
+                                               }
+                                       }
+                                       statement.generateCode(scope, codeStream);
+                               }
+                       }
+                       // place the trailing labels (for break and default case)
+                       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.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       }
+                       if (scope != currentScope) {
+                               codeStream.exitUserScope(scope);
+                       }
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+           } finally {
+               if (this.scope != null) this.scope.switchCase = null; // no longer inside switch case block
+           }           
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               printIndent(indent, output).append("switch ("); //$NON-NLS-1$
+               expression.printExpression(0, output).append(") {"); //$NON-NLS-1$
+               if (statements != null) {
+                       for (int i = 0; i < statements.length; i++) {
+                               output.append('\n');
+                               if (statements[i] instanceof CaseStatement) {
+                                       statements[i].printStatement(indent, output);
+                               } else {
+                                       statements[i].printStatement(indent+2, output);
+                               }
+                       }
+               }
+               output.append("\n"); //$NON-NLS-1$
+               return printIndent(indent, output).append('}');
+       }
+
+       public void resolve(BlockScope upperScope) {
+       
+           try {
+                       TypeBinding testType = expression.resolveType(upperScope);
+                       if (testType == null)
+                               return;
+                       expression.implicitWidening(testType, testType);
+                       if (!(expression.isConstantValueOfTypeAssignableToType(testType, IntBinding))) {
+                               if (!testType.isCompatibleWith(IntBinding)) {
+                                       upperScope.problemReporter().incorrectSwitchType(expression, testType);
+                                       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];
+                               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) {
+                                               //----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]);
+                                                                               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;
+                                               }
+                                       }
+                               }
+                       } else {
+                               if ((this.bits & UndocumentedEmptyBlockMASK) != 0) {
+                                       upperScope.problemReporter().undocumentedEmptyBlock(this.blockStart, this.sourceEnd);
+                               }
+                       }
+           } finally {
+               if (this.scope != null) this.scope.switchCase = null; // no longer inside switch case block
+           }
+       }
+
+       public void traverse(
+                       ASTVisitor visitor,
+                       BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       expression.traverse(visitor, scope);
+                       if (statements != null) {
+                               int statementsLength = statements.length;
+                               for (int i = 0; i < statementsLength; i++)
+                                       statements[i].traverse(visitor, scope);
+                       }
+               }
+               visitor.endVisit(this, blockScope);
+       }
+       
+       /**
+        * Dispatch the call on its last statement.
+        */
+       public void branchChainTo(Label label) {
+               
+               // in order to improve debug attributes for stepping (11431)
+               // we want to inline the jumps to #breakLabel which already got
+               // generated (if any), and have them directly branch to a better
+               // location (the argument label).
+               // we know at this point that the breakLabel already got placed
+               if (this.breakLabel.hasForwardReferences()) {
+                       label.appendForwardReferencesFrom(this.breakLabel);
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/SynchronizedStatement.java
new file mode 100644 (file)
index 0000000..2a45c54
--- /dev/null
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class SynchronizedStatement extends SubRoutineStatement {
+
+       public Expression expression;
+       public Block block;
+       public BlockScope scope;
+       boolean blockExit;
+       public LocalVariableBinding synchroVariable;
+       static final char[] SecretLocalDeclarationName = " syncValue".toCharArray(); //$NON-NLS-1$
+
+       public SynchronizedStatement(
+               Expression expression,
+               Block statement,
+               int s,
+               int e) {
+
+               this.expression = expression;
+               this.block = statement;
+               sourceEnd = e;
+               sourceStart = s;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // mark the synthetic variable as being used
+               synchroVariable.useFlag = LocalVariableBinding.USED;
+
+               // simple propagation to subnodes
+               flowInfo =
+                       block.analyseCode(
+                               scope,
+                               new InsideSubRoutineFlowContext(flowContext, this),
+                               expression.analyseCode(scope, flowContext, flowInfo));
+
+               // optimizing code gen
+               this.blockExit = !flowInfo.isReachable();
+
+               return flowInfo;
+       }
+
+       public boolean isSubRoutineEscaping() {
+
+               return false;
+       }
+       
+       /**
+        * Synchronized 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;
+               }
+               // in case the labels needs to be reinitialized
+               // when the code generation is restarted in wide mode
+               if (this.anyExceptionLabelsCount > 0) {
+                       this.anyExceptionLabels = NO_EXCEPTION_HANDLER;
+                       this.anyExceptionLabelsCount = 0;
+               }
+               int pc = codeStream.position;
+
+               // generate the synchronization expression
+               expression.generateCode(scope, codeStream, true);
+               if (block.isEmptyBlock()) {
+                       if ((synchroVariable.type == LongBinding)
+                               || (synchroVariable.type == DoubleBinding)) {
+                               codeStream.dup2();
+                       } else {
+                               codeStream.dup();
+                       }
+                       // only take the lock
+                       codeStream.monitorenter();
+                       codeStream.monitorexit();
+               } else {
+                       // enter the monitor
+                       codeStream.store(synchroVariable, true);
+                       codeStream.monitorenter();
+
+                       // generate  the body of the synchronized block
+                       this.enterAnyExceptionHandler(codeStream);
+                       block.generateCode(scope, codeStream);
+                       Label endLabel = new Label(codeStream);
+                       if (!blockExit) {
+                               codeStream.load(synchroVariable);
+                               codeStream.monitorexit();
+                               codeStream.goto_(endLabel);
+                       }
+                       // generate the body of the exception handler
+                       this.exitAnyExceptionHandler();
+                       this.placeAllAnyExceptionHandlers();
+                       codeStream.incrStackSize(1);
+                       codeStream.load(synchroVariable);
+                       codeStream.monitorexit();
+                       codeStream.athrow();
+                       if (!blockExit) {
+                               endLabel.place();
+                       }
+               }
+               if (scope != currentScope) {
+                       codeStream.exitUserScope(scope);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement#generateSubRoutineInvocation(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream)
+        */
+       public void generateSubRoutineInvocation(
+                       BlockScope currentScope,
+                       CodeStream codeStream) {
+
+               codeStream.load(this.synchroVariable);
+               codeStream.monitorexit();
+       }
+
+       public void resolve(BlockScope upperScope) {
+
+               // special scope for secret locals optimization.
+               scope = new BlockScope(upperScope);
+               TypeBinding type = expression.resolveType(scope);
+               if (type == null)
+                       return;
+               switch (type.id) {
+                       case (T_boolean) :
+                       case (T_char) :
+                       case (T_float) :
+                       case (T_double) :
+                       case (T_byte) :
+                       case (T_short) :
+                       case (T_int) :
+                       case (T_long) :
+                               scope.problemReporter().invalidTypeToSynchronize(expression, type);
+                               break;
+                       case (T_void) :
+                               scope.problemReporter().illegalVoidExpression(expression);
+                               break;
+                       case (T_null) :
+                               scope.problemReporter().invalidNullToSynchronize(expression);
+                               break; 
+               }
+               //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);
+               block.resolveUsing(scope);
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               printIndent(indent, output);
+               output.append("synchronized ("); //$NON-NLS-1$
+               expression.printExpression(0, output).append(')');
+               output.append('\n');
+               return block.printStatement(indent + 1, output); 
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       expression.traverse(visitor, scope);
+                       block.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ThisReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ThisReference.java
new file mode 100644 (file)
index 0000000..78ccdfa
--- /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.ast;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class ThisReference extends Reference {
+
+       public static ThisReference implicitThis(){
+
+               ThisReference implicitThis = new ThisReference(0, 0); 
+               implicitThis.bits |= IsImplicitThisMask;
+               return implicitThis;
+       }
+               
+       public ThisReference(int sourceStart, int sourceEnd) {
+       
+               this.sourceStart = sourceStart;
+               this.sourceEnd = sourceEnd;
+       }
+
+       /* 
+        * @see Reference#analyseAssignment(...)
+        */
+       public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
+
+               return flowInfo; // this cannot be assigned
+       }
+
+       public boolean checkAccess(MethodScope methodScope) {
+       
+               // this/super cannot be used in constructor call
+               if (methodScope.isConstructorCall) {
+                       methodScope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this);
+                       return false;
+               }
+       
+               // static may not refer to this/super
+               if (methodScope.isStatic) {
+                       methodScope.problemReporter().errorThisSuperInStatic(this);
+                       return false;
+               }
+               return true;
+       }
+
+       /* 
+        * @see Reference#generateAssignment(...)
+        */
+       public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
+
+                // this cannot be assigned
+       }
+
+       public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+       
+               int pc = codeStream.position;
+               if (valueRequired)
+                       codeStream.aload_0();
+               if ((this.bits & IsImplicitThisMask) == 0) codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /* 
+        * @see Reference#generateCompoundAssignment(...)
+        */
+       public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion,  boolean valueRequired) {
+
+                // this cannot be assigned
+       }
+       
+       /* 
+        * @see org.eclipse.jdt.internal.compiler.ast.Reference#generatePostIncrement()
+        */
+       public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
+
+                // this cannot be assigned
+       }
+       
+       public boolean isImplicitThis() {
+               
+               return (this.bits & IsImplicitThisMask) != 0;
+       }
+
+       public boolean isThis() {
+               
+               return true ;
+       }
+
+       public StringBuffer printExpression(int indent, StringBuffer output){
+       
+               if (this.isImplicitThis()) return output;
+               return output.append("this"); //$NON-NLS-1$
+       }
+
+       public TypeBinding resolveType(BlockScope scope) {
+       
+               constant = NotAConstant;
+               if (!this.isImplicitThis() &&!checkAccess(scope.methodScope())) {
+                       return null;
+               }
+               return this.resolvedType = scope.enclosingSourceType();
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+
+               visitor.visit(this, blockScope);
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/ThrowStatement.java
new file mode 100644 (file)
index 0000000..dac8920
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class ThrowStatement extends Statement {
+       public Expression exception;
+       public TypeBinding exceptionType;
+
+       public ThrowStatement(Expression exception, int startPosition) {
+               this.exception = exception;
+               this.sourceStart = startPosition;
+               this.sourceEnd = exception.sourceEnd;
+       }
+
+       public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+
+               exception.analyseCode(currentScope, flowContext, flowInfo);
+               // need to check that exception thrown is actually caught somewhere
+               flowContext.checkExceptionHandlers(exceptionType, this, flowInfo, currentScope);
+               return FlowInfo.DEAD_END;
+       }
+
+       /**
+        * Throw 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;
+               exception.generateCode(currentScope, codeStream, true);
+               codeStream.athrow();
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+
+               printIndent(indent, output).append("throw "); //$NON-NLS-1$
+               exception.printExpression(0, output);
+               return output.append(';');
+       }
+
+       public void resolve(BlockScope scope) {
+               
+               exceptionType = exception.resolveTypeExpecting(scope, scope.getJavaLangThrowable());
+               
+               if (exceptionType == NullBinding
+                               && scope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3){
+                       // if compliant with 1.4, this problem will not be reported
+                       scope.problemReporter().cannotThrowNull(this);
+               }
+               exception.implicitWidening(exceptionType, exceptionType);
+       }
+
+       public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+               if (visitor.visit(this, blockScope))
+                       exception.traverse(visitor, blockScope);
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java b/src/java/org/eclipse/jdt/internal/compiler/ast/TrueLiteral.java
new file mode 100644 (file)
index 0000000..14dc78f
--- /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.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.codegen.Label;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class TrueLiteral extends MagicLiteral {
+       static final char[] source = {'t' , 'r' , 'u' , 'e'};
+public TrueLiteral(int s , int e) {
+       super(s,e);
+}
+public void computeConstant() {
+
+       constant = Constant.fromValue(true);}
+/**
+ * Code generation for the true 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.iconst_1();
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
+
+       // trueLabel being not nil means that we will not fall through into the TRUE case
+
+       int pc = codeStream.position;
+       // constant == true
+       if (valueRequired) {
+               if (falseLabel == null) {
+                       // implicit falling through the FALSE case
+                       if (trueLabel != null) {
+                               codeStream.goto_(trueLabel);
+                       }
+               }
+       }
+       codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public TypeBinding literalType(BlockScope scope) {
+       return BooleanBinding;
+}
+/**
+ * 
+ */
+public char[] source() {
+       return source;
+}
+public void traverse(ASTVisitor visitor, BlockScope scope) {
+       visitor.visit(this, scope);
+       visitor.endVisit(this, scope);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
new file mode 100644 (file)
index 0000000..bda4130
--- /dev/null
@@ -0,0 +1,572 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class TryStatement extends SubRoutineStatement {
+       
+       public Block tryBlock;
+       public Block[] catchBlocks;
+       public Argument[] catchArguments;
+       public Block finallyBlock;
+       BlockScope scope;
+
+       private boolean isSubRoutineEscaping = false;
+       public UnconditionalFlowInfo subRoutineInits;
+       
+       // should rename into subRoutineComplete to be set to false by default
+
+       ReferenceBinding[] caughtExceptionTypes;
+       boolean tryBlockExit;
+       boolean[] catchExits;
+       public int[] preserveExceptionHandler;
+
+       Label subRoutineStartLabel;
+       public LocalVariableBinding anyExceptionVariable,
+               returnAddressVariable,
+               secretReturnValue;
+
+       public final static char[] SecretReturnName = " returnAddress".toCharArray(); //$NON-NLS-1$
+       public final static char[] SecretAnyHandlerName = " anyExceptionHandler".toCharArray(); //$NON-NLS-1$
+       public static final char[] SecretLocalDeclarationName = " returnValue".toCharArray(); //$NON-NLS-1$
+
+       // for local variables table attributes
+       int preTryInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               // Consider the try block and catch block so as to compute the intersection of initializations and      
+               // the minimum exit relative depth amongst all of them. Then consider the subroutine, and append its
+               // initialization to the try/catch ones, if the subroutine completes normally. If the subroutine does not
+               // complete, then only keep this result for the rest of the analysis
+
+               // process the finally block (subroutine) - create a context for the subroutine
+
+               preTryInitStateIndex =
+                       currentScope.methodScope().recordInitializationStates(flowInfo);
+
+               if (anyExceptionVariable != null) {
+                       anyExceptionVariable.useFlag = LocalVariableBinding.USED;
+               }
+               if (returnAddressVariable != null) { // TODO (philippe) if subroutine is escaping, unused
+                       returnAddressVariable.useFlag = LocalVariableBinding.USED;
+               }
+               InsideSubRoutineFlowContext insideSubContext;
+               FinallyFlowContext finallyContext;
+               UnconditionalFlowInfo subInfo;
+               if (subRoutineStartLabel == null) {
+                       // no finally block
+                       insideSubContext = null;
+                       finallyContext = null;
+                       subInfo = null;
+               } else {
+                       // analyse finally block first
+                       insideSubContext = new InsideSubRoutineFlowContext(flowContext, this);
+                       subInfo = 
+                               finallyBlock
+                                       .analyseCode(
+                                               currentScope,
+                                               finallyContext = new FinallyFlowContext(flowContext, finallyBlock),
+                                               flowInfo.copy())
+                                       .unconditionalInits();
+                       if (subInfo == FlowInfo.DEAD_END) {
+                               isSubRoutineEscaping = true;
+                               scope.problemReporter().finallyMustCompleteNormally(finallyBlock);
+                       }
+                       this.subRoutineInits = subInfo;
+               }
+               // process the try block in a context handling the local exceptions.
+               ExceptionHandlingFlowContext handlingContext =
+                       new ExceptionHandlingFlowContext(
+                               insideSubContext == null ? flowContext : insideSubContext,
+                               tryBlock,
+                               caughtExceptionTypes,
+                               scope,
+                               flowInfo.unconditionalInits());
+
+               FlowInfo tryInfo;
+               if (tryBlock.isEmptyBlock()) {
+                       tryInfo = flowInfo;
+                       tryBlockExit = false;
+               } else {
+                       tryInfo = tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy());
+                       tryBlockExit = !tryInfo.isReachable();
+               }
+
+               // check unreachable catch blocks
+               handlingContext.complainIfUnusedExceptionHandlers(scope, this);
+
+               // process the catch blocks - computing the minimal exit depth amongst try/catch
+               if (catchArguments != null) {
+                       int catchCount;
+                       catchExits = new boolean[catchCount = catchBlocks.length];
+                       for (int i = 0; i < catchCount; i++) {
+                               // keep track of the inits that could potentially have led to this exception handler (for final assignments diagnosis)
+                               FlowInfo catchInfo =
+                                       flowInfo
+                                               .copy()
+                                               .unconditionalInits()
+                                               .addPotentialInitializationsFrom(
+                                                       handlingContext.initsOnException(caughtExceptionTypes[i]).unconditionalInits())
+                                               .addPotentialInitializationsFrom(tryInfo.unconditionalInits())
+                                               .addPotentialInitializationsFrom(handlingContext.initsOnReturn);
+
+                               // catch var is always set
+                               catchInfo.markAsDefinitelyAssigned(catchArguments[i].binding);
+                               /*
+                               "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. 
+                               try { x = 1; throwSomething();} catch(Exception e){ x = 2} "
+                               "(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,
+                                               catchInfo);
+                               catchExits[i] = !catchInfo.isReachable();
+                               tryInfo = tryInfo.mergedWith(catchInfo.unconditionalInits());
+                       }
+               }
+               if (subRoutineStartLabel == null) {
+                       mergedInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(tryInfo);
+                       return tryInfo;
+               }
+
+
+               // 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(
+                       tryInfo.isReachable() 
+                               ? (tryInfo.addPotentialInitializationsFrom(insideSubContext.initsOnReturn))
+                               : insideSubContext.initsOnReturn, 
+                       currentScope);
+               if (subInfo == FlowInfo.DEAD_END) {
+                       mergedInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(subInfo);
+                       return subInfo;
+               } else {
+                       FlowInfo mergedInfo = tryInfo.addInitializationsFrom(subInfo);
+                       mergedInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(mergedInfo);
+                       return mergedInfo;
+               }
+       }
+
+       public boolean isSubRoutineEscaping() {
+
+               return isSubRoutineEscaping;
+       }
+
+       /**
+        * Try statement code generation with or without jsr bytecode use
+        *      post 1.5 target level, cannot use jsr bytecode, must instead inline finally block
+        * returnAddress is only allocated if jsr is allowed
+        */
+       public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+               if ((bits & IsReachableMASK) == 0) {
+                       return;
+               }
+               // in case the labels needs to be reinitialized
+               // when the code generation is restarted in wide mode
+               if (this.anyExceptionLabelsCount > 0) {
+                       this.anyExceptionLabels = NO_EXCEPTION_HANDLER;
+                       this.anyExceptionLabelsCount = 0;
+               }
+               int pc = codeStream.position;
+               final int NO_FINALLY = 0;                                                                       // no finally block
+               final int FINALLY_SUBROUTINE = 1;                                       // finally is generated as a subroutine (using jsr/ret bytecodes)
+               final int FINALLY_DOES_NOT_COMPLETE = 2;        // non returning finally is optimized with only one instance of finally block
+               final int FINALLY_MUST_BE_INLINED = 3;                  // finally block must be inlined since cannot use jsr/ret bytecodes >1.5
+               int finallyMode;
+               if (subRoutineStartLabel == null) { 
+                       finallyMode = NO_FINALLY;
+               } else {
+                       if (this.isSubRoutineEscaping) {
+                               finallyMode = FINALLY_DOES_NOT_COMPLETE;
+                       } else if (scope.environment().options.inlineJsrBytecode) {
+                               finallyMode = FINALLY_MUST_BE_INLINED;
+                       } else {
+                               finallyMode = FINALLY_SUBROUTINE;
+                       }
+               }
+               boolean requiresNaturalExit = false;
+               // preparing exception labels
+               int maxCatches;
+               ExceptionLabel[] exceptionLabels =
+                       new ExceptionLabel[maxCatches =
+                               catchArguments == null ? 0 : catchArguments.length];
+               for (int i = 0; i < maxCatches; i++) {
+                       exceptionLabels[i] = new ExceptionLabel(codeStream, catchArguments[i].binding.type);
+               }
+               if (subRoutineStartLabel != null) {
+                       subRoutineStartLabel.initialize(codeStream);
+                       this.enterAnyExceptionHandler(codeStream);
+               }
+               // generate the try block
+               tryBlock.generateCode(scope, codeStream);
+               boolean tryBlockHasSomeCode = codeStream.position != pc;
+               // flag telling if some bytecodes were issued inside the try block
+
+               // place end positions of user-defined exception labels
+               if (tryBlockHasSomeCode) {
+                       // natural exit may require subroutine invocation (if finally != null)
+                       Label naturalExitLabel = new Label(codeStream);
+                       if (!tryBlockExit) {
+                               int position = codeStream.position;
+                               switch(finallyMode) {
+                                       case FINALLY_SUBROUTINE :
+                                       case FINALLY_MUST_BE_INLINED :
+                                               requiresNaturalExit = true;
+                                               // fall through
+                                       case NO_FINALLY :
+                                               codeStream.goto_(naturalExitLabel);
+                                               break;
+                                       case FINALLY_DOES_NOT_COMPLETE :
+                                               codeStream.goto_(subRoutineStartLabel);
+                                               break;
+                               }
+                               codeStream.updateLastRecordedEndPC(position);
+                               //goto is tagged as part of the try block
+                       }
+                       for (int i = 0; i < maxCatches; i++) {
+                               exceptionLabels[i].placeEnd();
+                       }
+                       /* generate sequence of handler, all starting by storing the TOS (exception
+                       thrown) into their own catch variables, the one specified in the source
+                       that must denote the handled exception.
+                       */
+                       if (catchArguments == null) {
+                               this.exitAnyExceptionHandler();
+                       } else {
+                               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);
+                                       }
+                                       exceptionLabels[i].place();
+                                       codeStream.incrStackSize(1);
+                                       // optimizing the case where the exception variable is not actually used
+                                       LocalVariableBinding catchVar;
+                                       int varPC = codeStream.position;
+                                       if ((catchVar = catchArguments[i].binding).resolvedPosition != -1) {
+                                               codeStream.store(catchVar, false);
+                                               catchVar.recordInitializationStartPC(codeStream.position);
+                                               codeStream.addVisibleLocalVariable(catchVar);
+                                       } else {
+                                               codeStream.pop();
+                                       }
+                                       codeStream.recordPositionsFrom(varPC, catchArguments[i].sourceStart);
+                                       // Keep track of the pcs at diverging point for computing the local attribute
+                                       // since not passing the catchScope, the block generation will exitUserScope(catchScope)
+                                       catchBlocks[i].generateCode(scope, codeStream);
+
+                                       if (i == maxCatches - 1) {
+                                               this.exitAnyExceptionHandler();
+                                       }
+                                       if (!catchExits[i]) {
+                                               switch(finallyMode) {
+                                                       case FINALLY_SUBROUTINE :
+                                                       case FINALLY_MUST_BE_INLINED :
+                                                               requiresNaturalExit = true;
+                                                               // fall through
+                                                       case NO_FINALLY :
+                                                               codeStream.goto_(naturalExitLabel);
+                                                               break;
+                                                       case FINALLY_DOES_NOT_COMPLETE :
+                                                               codeStream.goto_(subRoutineStartLabel);
+                                                               break;
+                                               }
+                                       }
+                               }
+                       }
+                       // extra handler for trailing natural exit (will be fixed up later on when natural exit is generated below)
+                       ExceptionLabel naturalExitExceptionHandler = 
+                               finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit ? this.enterAnyExceptionHandler(codeStream) : null;
+                                               
+                       // addition of a special handler so as to ensure that any uncaught exception (or exception thrown
+                       // inside catch blocks) will run the finally block
+                       int finallySequenceStartPC = codeStream.position;
+                       if (subRoutineStartLabel != null) {
+                               // the additional handler is doing: jsr finallyBlock and rethrow TOS-exception
+                               this.placeAllAnyExceptionHandlers();
+
+                               if (preTryInitStateIndex != -1) {
+                                       // reset initialization state, as for a normal catch block
+                                       codeStream.removeNotDefinitelyAssignedVariables(
+                                               currentScope,
+                                               preTryInitStateIndex);
+                               }
+
+                               codeStream.incrStackSize(1);
+                               switch(finallyMode) {
+                                       
+                                       case FINALLY_SUBROUTINE :
+                                               codeStream.store(anyExceptionVariable, false);
+                                               codeStream.jsr(subRoutineStartLabel);
+                                               codeStream.load(anyExceptionVariable);
+                                               codeStream.athrow();
+                                               subRoutineStartLabel.place();
+                                               codeStream.incrStackSize(1);
+                                               codeStream.store(returnAddressVariable, false);
+                                               codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+                                               finallyBlock.generateCode(scope, codeStream);
+                                               int position = codeStream.position;
+                                               codeStream.ret(returnAddressVariable.resolvedPosition);
+                                               codeStream.updateLastRecordedEndPC(position);
+                                               codeStream.recordPositionsFrom(
+                                                       position,
+                                                       finallyBlock.sourceEnd);
+                                               // the ret bytecode is part of the subroutine
+                                               break;
+                                               
+                                       case FINALLY_MUST_BE_INLINED :
+                                               codeStream.store(anyExceptionVariable, false);
+                                               this.finallyBlock.generateCode(currentScope, codeStream);
+                                               codeStream.load(anyExceptionVariable);
+                                               codeStream.athrow();
+                                               subRoutineStartLabel.place();
+                                               codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+                                               break;
+                                               
+                                       case FINALLY_DOES_NOT_COMPLETE :
+                                               codeStream.pop();
+                                               subRoutineStartLabel.place();
+                                               codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
+                                               finallyBlock.generateCode(scope, codeStream);
+                                               break;
+                               }
+                               // will naturally fall into subsequent code after subroutine invocation
+                               naturalExitLabel.place();
+                               if (requiresNaturalExit) {
+                                       switch(finallyMode) {
+
+                                               case FINALLY_SUBROUTINE :
+                                                       int position = codeStream.position;                                     
+                                                       // fix up natural exit handler
+                                                       naturalExitExceptionHandler.placeStart();
+                                                       codeStream.jsr(subRoutineStartLabel);
+                                                       naturalExitExceptionHandler.placeEnd();
+                                                       codeStream.recordPositionsFrom(
+                                                               position,
+                                                               finallyBlock.sourceStart);                                      
+                                                       break;
+                                               
+                                               case FINALLY_MUST_BE_INLINED :
+                                                       // May loose some local variable initializations : affecting the local variable attributes
+                                                       // needed since any exception handler got inlined subroutine
+                                                       if (preTryInitStateIndex != -1) {
+                                                               codeStream.removeNotDefinitelyAssignedVariables(
+                                                                       currentScope,
+                                                                       preTryInitStateIndex);
+                                                       }
+                                                       // entire sequence for finally is associated to finally block
+                                                       finallyBlock.generateCode(scope, codeStream);
+                                                       break;
+                                               
+                                               case FINALLY_DOES_NOT_COMPLETE :
+                                                       break;
+                                       }
+                               }
+                       } else {
+                               // no subroutine, simply position end label (natural exit == end)
+                               naturalExitLabel.place();
+                       }
+               } else {
+                       // try block had no effect, only generate the body of the finally block if any
+                       if (subRoutineStartLabel != null) {
+                               finallyBlock.generateCode(scope, codeStream);
+                       }
+               }
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(
+                               currentScope,
+                               mergedInitStateIndex);
+                       codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement#generateSubRoutineInvocation(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream)
+        */
+       public void generateSubRoutineInvocation(
+                       BlockScope currentScope,
+                       CodeStream codeStream) {
+       
+               if (this.isSubRoutineEscaping) {
+                               codeStream.goto_(this.subRoutineStartLabel);
+               } else {
+                       if (currentScope.environment().options.inlineJsrBytecode) { 
+                               // cannot use jsr bytecode, then simply inline the subroutine
+                               this.finallyBlock.generateCode(currentScope, codeStream);
+                       } else {
+                               // classic subroutine invocation, distinguish case of non-returning subroutine
+                               codeStream.jsr(this.subRoutineStartLabel);
+                       }
+               }
+       }
+
+       public StringBuffer printStatement(int indent, StringBuffer output) {
+               printIndent(indent, output).append("try \n"); //$NON-NLS-1$
+               tryBlock.printStatement(indent + 1, output); //$NON-NLS-1$
+
+               //catches
+               if (catchBlocks != null)
+                       for (int i = 0; i < catchBlocks.length; i++) {
+                                       output.append('\n');
+                                       printIndent(indent, output).append("catch ("); //$NON-NLS-1$
+                                       catchArguments[i].print(0, output).append(") "); //$NON-NLS-1$
+                                       catchBlocks[i].printStatement(indent + 1, output);
+                       }
+               //finally
+               if (finallyBlock != null) {
+                       output.append('\n');
+                       printIndent(indent, output).append("finally\n"); //$NON-NLS-1$
+                       finallyBlock.printStatement(indent + 1, output);
+               }
+
+               return output;
+       }
+
+       public void resolve(BlockScope upperScope) {
+
+               // special scope for secret locals optimization.        
+               this.scope = new BlockScope(upperScope);
+
+               BlockScope tryScope = new BlockScope(scope);
+               BlockScope finallyScope = null;
+               
+               if (finallyBlock != null) {
+                       if (finallyBlock.isEmptyBlock()) {
+                               if ((finallyBlock.bits & UndocumentedEmptyBlockMASK) != 0) {
+                                       scope.problemReporter().undocumentedEmptyBlock(finallyBlock.sourceStart, finallyBlock.sourceEnd);
+                               }
+                       } else {
+                               finallyScope = new BlockScope(scope, false); // don't add it yet to parent scope
+       
+                               // provision for returning and forcing the finally block to run
+                               MethodScope methodScope = scope.methodScope();
+       
+                               // the type does not matter as long as it is not a base type
+                               if (!upperScope.environment().options.inlineJsrBytecode) {
+                                       this.returnAddressVariable =
+                                               new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), AccDefault, false);
+                                       finallyScope.addLocalVariable(returnAddressVariable);
+                                       this.returnAddressVariable.constant = NotAConstant; // not inlinable
+                               }
+                               this.subRoutineStartLabel = new Label();
+       
+                               this.anyExceptionVariable =
+                                       new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), AccDefault, false);
+                               finallyScope.addLocalVariable(this.anyExceptionVariable);
+                               this.anyExceptionVariable.constant = NotAConstant; // not inlinable
+       
+                               if (!methodScope.isInsideInitializer()) {
+                                       MethodBinding methodBinding =
+                                               ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
+                                       if (methodBinding != null) {
+                                               TypeBinding methodReturnType = methodBinding.returnType;
+                                               if (methodReturnType.id != T_void) {
+                                                       this.secretReturnValue =
+                                                               new LocalVariableBinding(
+                                                                       SecretLocalDeclarationName,
+                                                                       methodReturnType,
+                                                                       AccDefault,
+                                                                       false);
+                                                       finallyScope.addLocalVariable(this.secretReturnValue);
+                                                       this.secretReturnValue.constant = NotAConstant; // not inlinable
+                                               }
+                                       }
+                               }
+                               finallyBlock.resolveUsing(finallyScope);
+                               // force the finally scope to have variable positions shifted after its try scope and catch ones
+                               finallyScope.shiftScopes = new BlockScope[catchArguments == null ? 1 : catchArguments.length+1];
+                               finallyScope.shiftScopes[0] = tryScope;
+                       }
+               }
+               this.tryBlock.resolveUsing(tryScope);
+
+               // arguments type are checked against JavaLangThrowable in resolveForCatch(..)
+               if (this.catchBlocks != null) {
+                       int length = this.catchArguments.length;
+                       TypeBinding[] argumentTypes = new TypeBinding[length];
+                       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;
+                               catchBlocks[i].resolveUsing(catchScope);
+                       }
+
+                       // Verify that the catch clause are ordered in the right way:
+                       // more specialized first.
+                       this.caughtExceptionTypes = new ReferenceBinding[length];
+                       for (int i = 0; i < length; i++) {
+                               caughtExceptionTypes[i] = (ReferenceBinding) argumentTypes[i];
+                               for (int j = 0; j < i; j++) {
+                                       if (caughtExceptionTypes[i].isCompatibleWith(argumentTypes[j])) {
+                                               scope.problemReporter().wrongSequenceOfExceptionTypesError(this, caughtExceptionTypes[i], i, argumentTypes[j]);
+                                       }
+                               }
+                       }
+               } else {
+                       caughtExceptionTypes = new ReferenceBinding[0];
+               }
+               
+               if (finallyScope != null){
+                       // add finallyScope as last subscope, so it can be shifted behind try/catch subscopes.
+                       // the shifting is necessary to achieve no overlay in between the finally scope and its
+                       // sibling in term of local variable positions.
+                       this.scope.addSubscope(finallyScope);
+               }
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       tryBlock.traverse(visitor, scope);
+                       if (catchArguments != null) {
+                               for (int i = 0, max = catchBlocks.length; i < max; i++) {
+                                       catchArguments[i].traverse(visitor, scope);
+                                       catchBlocks[i].traverse(visitor, scope);
+                               }
+                       }
+                       if (finallyBlock != null)
+                               finallyBlock.traverse(visitor, scope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/src/java/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
new file mode 100644 (file)
index 0000000..b6ba6f1
--- /dev/null
@@ -0,0 +1,1135 @@
+/*******************************************************************************
+ * 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.*;
+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.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.problem.*;
+
+public class TypeDeclaration
+       extends Statement
+       implements ProblemSeverities, ReferenceContext {
+
+       public static final char[] ANONYMOUS_EMPTY_NAME = new char[] {};
+
+       public int modifiers = AccDefault;
+       public int modifiersSourceStart;
+       public char[] name;
+       public TypeReference superclass;
+       public TypeReference[] superInterfaces;
+       public FieldDeclaration[] fields;
+       public AbstractMethodDeclaration[] methods;
+       public TypeDeclaration[] memberTypes;
+       public SourceTypeBinding binding;
+       public ClassScope scope;
+       public MethodScope initializerScope;
+       public MethodScope staticInitializerScope;
+       public boolean ignoreFurtherInvestigation = false;
+       public int maxFieldCount;
+       public int declarationSourceStart;
+       public int declarationSourceEnd;
+       public int bodyStart;
+       public int bodyEnd; // doesn't include the trailing comment if any.
+       protected boolean hasBeenGenerated = false;
+       public CompilationResult compilationResult;
+       private MethodDeclaration[] missingAbstractMethods;
+       public Javadoc javadoc; 
+
+       public QualifiedAllocationExpression allocation; // for anonymous only
+       public TypeDeclaration enclosingType; // for member types only
+       
+       public TypeDeclaration(CompilationResult compilationResult){
+               this.compilationResult = compilationResult;
+       }
+               
+       /*
+        *      We cause the compilation task to abort to a given extent.
+        */
+       public void abort(int abortLevel, IProblem problem) {
+
+               switch (abortLevel) {
+                       case AbortCompilation :
+                               throw new AbortCompilation(this.compilationResult, problem);
+                       case AbortCompilationUnit :
+                               throw new AbortCompilationUnit(this.compilationResult, problem);
+                       case AbortMethod :
+                               throw new AbortMethod(this.compilationResult, problem);
+                       default :
+                               throw new AbortType(this.compilationResult, problem);
+               }
+       }
+       /**
+        * This method is responsible for adding a <clinit> method declaration to the type method collections.
+        * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
+        * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as 
+        * the latter will have to reset the constant pool state accordingly (if it was added first, it does 
+        * not need to preserve some of the method specific cached entries since this will be the first method).
+        * inserts the clinit method declaration in the first position.
+        * 
+        * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
+        */
+       public final void addClinit() {
+
+               //see comment on needClassInitMethod
+               if (needClassInitMethod()) {
+                       int length;
+                       AbstractMethodDeclaration[] methodDeclarations;
+                       if ((methodDeclarations = this.methods) == null) {
+                               length = 0;
+                               methodDeclarations = new AbstractMethodDeclaration[1];
+                       } else {
+                               length = methodDeclarations.length;
+                               System.arraycopy(
+                                       methodDeclarations,
+                                       0,
+                                       (methodDeclarations = new AbstractMethodDeclaration[length + 1]),
+                                       1,
+                                       length);
+                       }
+                       Clinit clinit = new Clinit(this.compilationResult);
+                       methodDeclarations[0] = clinit;
+                       // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
+                       clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
+                       clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
+                       clinit.bodyEnd = sourceEnd;
+                       this.methods = methodDeclarations;
+               }
+       }
+
+       /*
+        * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
+        * It is used to report errors for missing abstract methods.
+        */
+       public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
+               TypeBinding[] argumentTypes = methodBinding.parameters;
+               int argumentsLength = argumentTypes.length;
+               //the constructor
+               MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
+               methodDeclaration.selector = methodBinding.selector;
+               methodDeclaration.sourceStart = sourceStart;
+               methodDeclaration.sourceEnd = sourceEnd;
+               methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~AccAbstract;
+
+               if (argumentsLength > 0) {
+                       String baseName = "arg";//$NON-NLS-1$
+                       Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
+                       for (int i = argumentsLength; --i >= 0;) {
+                               arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
+                       }
+               }
+
+               //adding the constructor in the methods list
+               if (this.missingAbstractMethods == null) {
+                       this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
+               } else {
+                       MethodDeclaration[] newMethods;
+                       System.arraycopy(
+                               this.missingAbstractMethods,
+                               0,
+                               newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
+                               1,
+                               this.missingAbstractMethods.length);
+                       newMethods[0] = methodDeclaration;
+                       this.missingAbstractMethods = newMethods;
+               }
+
+               //============BINDING UPDATE==========================
+               methodDeclaration.binding = new MethodBinding(
+                               methodDeclaration.modifiers, //methodDeclaration
+                               methodBinding.selector,
+                               methodBinding.returnType,
+                               argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
+                               methodBinding.thrownExceptions, //exceptions
+                               binding); //declaringClass
+                               
+               methodDeclaration.scope = new MethodScope(scope, methodDeclaration, true);
+               methodDeclaration.bindArguments();
+
+/*             if (binding.methods == null) {
+                       binding.methods = new MethodBinding[] { methodDeclaration.binding };
+               } else {
+                       MethodBinding[] newMethods;
+                       System.arraycopy(
+                               binding.methods,
+                               0,
+                               newMethods = new MethodBinding[binding.methods.length + 1],
+                               1,
+                               binding.methods.length);
+                       newMethods[0] = methodDeclaration.binding;
+                       binding.methods = newMethods;
+               }*/
+               //===================================================
+
+               return methodDeclaration;
+       }
+
+       /**
+        *      Flow analysis for a local innertype
+        *
+        */
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               if (ignoreFurtherInvestigation)
+                       return flowInfo;
+               try {
+                       if (flowInfo.isReachable()) {
+                               bits |= IsReachableMASK;
+                               LocalTypeBinding localType = (LocalTypeBinding) binding;
+                               localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
+                       }
+                       manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+                       updateMaxFieldCount(); // propagate down the max field count
+                       internalAnalyseCode(flowContext, flowInfo); 
+               } catch (AbortType e) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+               return flowInfo;
+       }
+
+       /**
+        *      Flow analysis for a member innertype
+        *
+        */
+       public void analyseCode(ClassScope enclosingClassScope) {
+
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       // propagate down the max field count
+                       updateMaxFieldCount();
+                       internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
+               } catch (AbortType e) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+       }
+
+       /**
+        *      Flow analysis for a local member innertype
+        *
+        */
+       public void analyseCode(
+               ClassScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       if (flowInfo.isReachable()) {
+                               bits |= IsReachableMASK;
+                               LocalTypeBinding localType = (LocalTypeBinding) binding;
+                               localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
+                       }
+                       manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
+                       updateMaxFieldCount(); // propagate down the max field count
+                       internalAnalyseCode(flowContext, flowInfo);
+               } catch (AbortType e) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+       }
+
+       /**
+        *      Flow analysis for a package member type
+        *
+        */
+       public void analyseCode(CompilationUnitScope unitScope) {
+
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       internalAnalyseCode(null, FlowInfo.initial(maxFieldCount));
+               } catch (AbortType e) {
+                       this.ignoreFurtherInvestigation = true;
+               }
+       }
+
+       /*
+        * Check for constructor vs. method with no return type.
+        * Answers true if at least one constructor is defined
+        */
+       public boolean checkConstructors(Parser parser) {
+
+               //if a constructor has not the name of the type,
+               //convert it into a method with 'null' as its return type
+               boolean hasConstructor = false;
+               if (methods != null) {
+                       for (int i = methods.length; --i >= 0;) {
+                               AbstractMethodDeclaration am;
+                               if ((am = methods[i]).isConstructor()) {
+                                       if (!CharOperation.equals(am.selector, name)) {
+                                               // the constructor was in fact a method with no return type
+                                               // unless an explicit constructor call was supplied
+                                               ConstructorDeclaration c = (ConstructorDeclaration) am;
+                                               if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
+                                                       MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
+                                                       methods[i] = m;
+                                               }
+                                       } else {
+                                               if (this.isInterface()) {
+                                                       // report the problem and continue the parsing
+                                                       parser.problemReporter().interfaceCannotHaveConstructors(
+                                                               (ConstructorDeclaration) am);
+                                               }
+                                               hasConstructor = true;
+                                       }
+                               }
+                       }
+               }
+               return hasConstructor;
+       }
+
+       public CompilationResult compilationResult() {
+
+               return this.compilationResult;
+       }
+
+       public ConstructorDeclaration createsInternalConstructor(
+               boolean needExplicitConstructorCall,
+               boolean needToInsert) {
+
+               //Add to method'set, the default constuctor that just recall the
+               //super constructor with no arguments
+               //The arguments' type will be positionned by the TC so just use
+               //the default int instead of just null (consistency purpose)
+
+               //the constructor
+               ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
+               constructor.isDefaultConstructor = true;
+               constructor.selector = name;
+               if (modifiers != AccDefault) {
+                       constructor.modifiers =
+                               (((this.bits & ASTNode.IsMemberTypeMASK) != 0) && (modifiers & AccPrivate) != 0)
+                                       ? AccDefault
+                                       : modifiers & AccVisibilityMASK;
+               }
+
+               //if you change this setting, please update the 
+               //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
+               constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
+               constructor.declarationSourceEnd =
+                       constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
+
+               //the super call inside the constructor
+               if (needExplicitConstructorCall) {
+                       constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
+                       constructor.constructorCall.sourceStart = sourceStart;
+                       constructor.constructorCall.sourceEnd = sourceEnd;
+               }
+
+               //adding the constructor in the methods list
+               if (needToInsert) {
+                       if (methods == null) {
+                               methods = new AbstractMethodDeclaration[] { constructor };
+                       } else {
+                               AbstractMethodDeclaration[] newMethods;
+                               System.arraycopy(
+                                       methods,
+                                       0,
+                                       newMethods = new AbstractMethodDeclaration[methods.length + 1],
+                                       1,
+                                       methods.length);
+                               newMethods[0] = constructor;
+                               methods = newMethods;
+                       }
+               }
+               return constructor;
+       }
+       
+       // anonymous type constructor creation
+       public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
+
+               //Add to method'set, the default constuctor that just recall the
+               //super constructor with the same arguments
+               String baseName = "$anonymous"; //$NON-NLS-1$
+               TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
+               int argumentsLength = argumentTypes.length;
+               //the constructor
+               ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationResult);
+               cd.selector = new char[] { 'x' }; //no maining
+               cd.sourceStart = sourceStart;
+               cd.sourceEnd = sourceEnd;
+               cd.modifiers = modifiers & AccVisibilityMASK;
+               cd.isDefaultConstructor = true;
+
+               if (argumentsLength > 0) {
+                       Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
+                       for (int i = argumentsLength; --i >= 0;) {
+                               arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
+                       }
+               }
+
+               //the super call inside the constructor
+               cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+               cd.constructorCall.sourceStart = sourceStart;
+               cd.constructorCall.sourceEnd = sourceEnd;
+
+               if (argumentsLength > 0) {
+                       Expression[] args;
+                       args = cd.constructorCall.arguments = new Expression[argumentsLength];
+                       for (int i = argumentsLength; --i >= 0;) {
+                               args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
+                       }
+               }
+
+               //adding the constructor in the methods list
+               if (methods == null) {
+                       methods = new AbstractMethodDeclaration[] { cd };
+               } else {
+                       AbstractMethodDeclaration[] newMethods;
+                       System.arraycopy(
+                               methods,
+                               0,
+                               newMethods = new AbstractMethodDeclaration[methods.length + 1],
+                               1,
+                               methods.length);
+                       newMethods[0] = cd;
+                       methods = newMethods;
+               }
+
+               //============BINDING UPDATE==========================
+               cd.binding = new MethodBinding(
+                               cd.modifiers, //methodDeclaration
+                               argumentsLength == 0 ? NoParameters : argumentTypes, //arguments bindings
+                               inheritedConstructorBinding.thrownExceptions, //exceptions
+                               binding); //declaringClass
+                               
+               cd.scope = new MethodScope(scope, cd, true);
+               cd.bindArguments();
+               cd.constructorCall.resolve(cd.scope);
+
+               if (binding.methods == null) {
+                       binding.methods = new MethodBinding[] { cd.binding };
+               } else {
+                       MethodBinding[] newMethods;
+                       System.arraycopy(
+                               binding.methods,
+                               0,
+                               newMethods = new MethodBinding[binding.methods.length + 1],
+                               1,
+                               binding.methods.length);
+                       newMethods[0] = cd.binding;
+                       binding.methods = newMethods;
+               }
+               //===================================================
+
+               return cd.binding;
+       }
+
+       /*
+        * Find the matching parse node, answers null if nothing found
+        */
+       public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
+
+               if (fieldBinding != null) {
+                       for (int i = 0, max = this.fields.length; i < max; i++) {
+                               FieldDeclaration fieldDecl;
+                               if ((fieldDecl = this.fields[i]).binding == fieldBinding)
+                                       return fieldDecl;
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * Find the matching parse node, answers null if nothing found
+        */
+       public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
+
+               if (memberTypeBinding != null) {
+                       for (int i = 0, max = this.memberTypes.length; i < max; i++) {
+                               TypeDeclaration memberTypeDecl;
+                               if ((memberTypeDecl = this.memberTypes[i]).binding == memberTypeBinding)
+                                       return memberTypeDecl;
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * Find the matching parse node, answers null if nothing found
+        */
+       public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
+
+               if (methodBinding != null) {
+                       for (int i = 0, max = this.methods.length; i < max; i++) {
+                               AbstractMethodDeclaration methodDecl;
+
+                               if ((methodDecl = this.methods[i]).binding == methodBinding)
+                                       return methodDecl;
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * Finds the matching type amoung this type's member types.
+        * Returns null if no type with this name is found.
+        * The type name is a compound name relative to this type
+        * eg. if this type is X and we're looking for Y.X.A.B
+        *     then a type name would be {X, A, B}
+        */
+       public TypeDeclaration declarationOfType(char[][] typeName) {
+
+               int typeNameLength = typeName.length;
+               if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
+                       return null;
+               }
+               if (typeNameLength == 1) {
+                       return this;
+               }
+               char[][] subTypeName = new char[typeNameLength - 1][];
+               System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
+               for (int i = 0; i < this.memberTypes.length; i++) {
+                       TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
+                       if (typeDecl != null) {
+                               return typeDecl;
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Generic bytecode generation for type
+        */
+       public void generateCode(ClassFile enclosingClassFile) {
+
+               if (hasBeenGenerated)
+                       return;
+               hasBeenGenerated = true;
+               if (ignoreFurtherInvestigation) {
+                       if (binding == null)
+                               return;
+                       ClassFile.createProblemType(
+                               this,
+                               scope.referenceCompilationUnit().compilationResult);
+                       return;
+               }
+               try {
+                       // create the result for a compiled type
+                       ClassFile classFile = new ClassFile(binding, enclosingClassFile, false);
+                       // generate all fiels
+                       classFile.addFieldInfos();
+
+                       // record the inner type inside its own .class file to be able
+                       // to generate inner classes attributes
+                       if (binding.isMemberType())
+                               classFile.recordEnclosingTypeAttributes(binding);
+                       if (binding.isLocalType()) {
+                               enclosingClassFile.recordNestedLocalAttribute(binding);
+                               classFile.recordNestedLocalAttribute(binding);
+                       }
+                       if (memberTypes != null) {
+                               for (int i = 0, max = memberTypes.length; i < max; i++) {
+                                       // record the inner type inside its own .class file to be able
+                                       // to generate inner classes attributes
+                                       classFile.recordNestedMemberAttribute(memberTypes[i].binding);
+                                       memberTypes[i].generateCode(scope, classFile);
+                               }
+                       }
+                       // generate all methods
+                       classFile.setForMethodInfos();
+                       if (methods != null) {
+                               for (int i = 0, max = methods.length; i < max; i++) {
+                                       methods[i].generateCode(scope, classFile);
+                               }
+                       }
+                       
+                       classFile.generateMissingAbstractMethods(this.missingAbstractMethods, scope.referenceCompilationUnit().compilationResult);
+
+                       // generate all methods
+                       classFile.addSpecialMethods();
+
+                       if (ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
+                               throw new AbortType(scope.referenceCompilationUnit().compilationResult, null);
+                       }
+
+                       // finalize the compiled type result
+                       classFile.addAttributes();
+                       scope.referenceCompilationUnit().compilationResult.record(
+                               binding.constantPoolName(),
+                               classFile);
+               } catch (AbortType e) {
+                       if (binding == null)
+                               return;
+                       ClassFile.createProblemType(
+                               this,
+                               scope.referenceCompilationUnit().compilationResult);
+               }
+       }
+
+       /**
+        * Bytecode generation for a local inner type (API as a normal statement code gen)
+        */
+       public void generateCode(BlockScope blockScope, CodeStream codeStream) {
+
+               if ((this.bits & IsReachableMASK) == 0) {
+                       return;
+               }               
+               if (hasBeenGenerated) return;
+               int pc = codeStream.position;
+               if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
+               generateCode(codeStream.classFile);
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /**
+        * Bytecode generation for a member inner type
+        */
+       public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
+
+               if (hasBeenGenerated) return;
+               if (binding != null) ((NestedTypeBinding) binding).computeSyntheticArgumentSlotSizes();
+               generateCode(enclosingClassFile);
+       }
+
+       /**
+        * Bytecode generation for a package member
+        */
+       public void generateCode(CompilationUnitScope unitScope) {
+
+               generateCode((ClassFile) null);
+       }
+
+       public boolean hasErrors() {
+               return this.ignoreFurtherInvestigation;
+       }
+
+       /**
+        *      Common flow analysis for all types
+        *
+        */
+       public void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
+
+               if (this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
+                       if (!scope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
+                               scope.problemReporter().unusedPrivateType(this);
+                       }
+               }
+
+               InitializationFlowContext initializerContext = new InitializationFlowContext(null, this, initializerScope);
+               InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, staticInitializerScope);
+               FlowInfo nonStaticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
+               FlowInfo staticFieldInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
+               if (fields != null) {
+                       for (int i = 0, count = fields.length; i < count; i++) {
+                               FieldDeclaration field = fields[i];
+                               if (field.isStatic()) {
+                                       /*if (field.isField()){
+                                               staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
+                                       } else {*/
+                                       staticInitializerContext.handledExceptions = AnyException; // tolerate them all, and record them
+                                       /*}*/
+                                       staticFieldInfo =
+                                               field.analyseCode(
+                                                       staticInitializerScope,
+                                                       staticInitializerContext,
+                                                       staticFieldInfo);
+                                       // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
+                                       // branch, since the previous initializer already got the blame.
+                                       if (staticFieldInfo == FlowInfo.DEAD_END) {
+                                               staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
+                                               staticFieldInfo = FlowInfo.initial(maxFieldCount).setReachMode(FlowInfo.UNREACHABLE);
+                                       }
+                               } else {
+                                       /*if (field.isField()){
+                                               initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
+                                       } else {*/
+                                               initializerContext.handledExceptions = AnyException; // tolerate them all, and record them
+                                       /*}*/
+                                       nonStaticFieldInfo =
+                                               field.analyseCode(initializerScope, initializerContext, nonStaticFieldInfo);
+                                       // in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
+                                       // branch, since the previous initializer already got the blame.
+                                       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());
+                               } else {
+                                       memberTypes[i].analyseCode(scope);
+                               }
+                       }
+               }
+               if (methods != null) {
+                       UnconditionalFlowInfo outerInfo = flowInfo.copy().unconditionalInits().discardFieldInitializations();
+                       FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
+                       for (int i = 0, count = methods.length; i < count; i++) {
+                               AbstractMethodDeclaration method = methods[i];
+                               if (method.ignoreFurtherInvestigation)
+                                       continue;
+                               if (method.isInitializationMethod()) {
+                                       if (method.isStatic()) { // <clinit>
+                                               method.analyseCode(
+                                                       scope, 
+                                                       staticInitializerContext, 
+                                                       staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
+                                       } else { // constructor
+                                               method.analyseCode(scope, initializerContext, constructorInfo.copy());
+                                       }
+                               } else { // regular method
+                                       method.analyseCode(scope, null, flowInfo.copy());
+                               }
+                       }
+               }
+       }
+
+       public boolean isInterface() {
+
+               return (modifiers & AccInterface) != 0;
+       }
+
+       /* 
+        * Access emulation for a local type
+        * force to emulation of access to direct enclosing instance.
+        * By using the initializer scope, we actually only request an argument emulation, the
+        * field is not added until actually used. However we will force allocations to be qualified
+        * with an enclosing instance.
+        * 15.9.2
+        */
+       public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               NestedTypeBinding nestedType = (NestedTypeBinding) binding;
+               
+               MethodScope methodScope = currentScope.methodScope();
+               if (!methodScope.isStatic && !methodScope.isConstructorCall){
+
+                       nestedType.addSyntheticArgumentAndField(binding.enclosingType());       
+               }
+               // add superclass enclosing instance arg for anonymous types (if necessary)
+               if (binding.isAnonymousType()) { 
+                       ReferenceBinding superclassBinding = binding.superclass;
+                       if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
+                               if (!superclassBinding.isLocalType()
+                                               || ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){
+
+                                       nestedType.addSyntheticArgument(superclassBinding.enclosingType());     
+                               }
+                       }
+               }
+       }
+       
+       /* 
+        * Access emulation for a local member type
+        * force to emulation of access to direct enclosing instance.
+        * By using the initializer scope, we actually only request an argument emulation, the
+        * field is not added until actually used. However we will force allocations to be qualified
+        * with an enclosing instance.
+        * 
+        * Local member cannot be static.
+        */
+       public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               NestedTypeBinding nestedType = (NestedTypeBinding) binding;
+               nestedType.addSyntheticArgumentAndField(binding.enclosingType());
+       }       
+       
+       /**
+        * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
+        * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
+        */
+       public final boolean needClassInitMethod() {
+
+               // always need a <clinit> when assertions are present
+               if ((this.bits & AddAssertionMASK) != 0)
+                       return true;
+               if (fields == null)
+                       return false;
+               if (isInterface())
+                       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;
+               }
+               return false;
+       }
+
+       public void parseMethod(Parser parser, CompilationUnitDeclaration unit) {
+
+               //connect method bodies
+               if (unit.ignoreMethodBodies)
+                       return;
+
+               //members
+               if (memberTypes != null) {
+                       int length = memberTypes.length;
+                       for (int i = 0; i < length; i++)
+                               memberTypes[i].parseMethod(parser, unit);
+               }
+
+               //methods
+               if (methods != null) {
+                       int length = methods.length;
+                       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);
+                               }
+                       }
+               }
+       }
+
+       public StringBuffer print(int indent, StringBuffer output) {
+
+               if ((this.bits & IsAnonymousTypeMASK) == 0) {
+                       printIndent(indent, output);
+                       printHeader(0, output);
+               }
+               return printBody(indent, output);
+       }
+
+       public StringBuffer printBody(int indent, StringBuffer output) {
+
+               output.append(" {"); //$NON-NLS-1$
+               if (memberTypes != null) {
+                       for (int i = 0; i < memberTypes.length; i++) {
+                               if (memberTypes[i] != null) {
+                                       output.append('\n');
+                                       memberTypes[i].print(indent + 1, output);
+                               }
+                       }
+               }
+               if (fields != null) {
+                       for (int fieldI = 0; fieldI < fields.length; fieldI++) {
+                               if (fields[fieldI] != null) {
+                                       output.append('\n');
+                                       fields[fieldI].print(indent + 1, output);
+                               }
+                       }
+               }
+               if (methods != null) {
+                       for (int i = 0; i < methods.length; i++) {
+                               if (methods[i] != null) {
+                                       output.append('\n');
+                                       methods[i].print(indent + 1, output); 
+                               }
+                       }
+               }
+               output.append('\n');
+               return printIndent(indent, output).append('}');
+       }
+
+       public StringBuffer printHeader(int indent, StringBuffer output) {
+
+               printModifiers(this.modifiers, output);
+               output.append(isInterface() ? "interface " : "class "); //$NON-NLS-1$ //$NON-NLS-2$
+               output.append(name);
+               if (superclass != null) {
+                       output.append(" extends ");  //$NON-NLS-1$
+                       superclass.print(0, output);
+               }
+               if (superInterfaces != null && superInterfaces.length > 0) {
+                       output.append(isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
+                       for (int i = 0; i < superInterfaces.length; i++) {
+                               if (i > 0) output.append( ", "); //$NON-NLS-1$
+                               superInterfaces[i].print(0, output);
+                       }
+               }
+               return output;
+       }
+
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+               return print(tab, output);
+       }
+
+       public void resolve() {
+
+               if (this.binding == null) {
+                       this.ignoreFurtherInvestigation = true;
+                       return;
+               }
+               try {
+                       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]);
+                       this.maxFieldCount = 0;
+                       int lastVisibleFieldID = -1;
+                       if (this.fields != null) {
+                               for (int i = 0, count = this.fields.length; i < count; i++) {
+                                       FieldDeclaration field = this.fields[i];
+                                       if (field.isField()) {
+                                               if (field.binding == null) {
+                                                       // still discover secondary errors
+                                                       if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
+                                                       this.ignoreFurtherInvestigation = true;
+                                                       continue;
+                                               }
+                                               this.maxFieldCount++;
+                                               lastVisibleFieldID = field.binding.id;
+                                       } else { // initializer
+                                                ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
+                                       }
+                                       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);
+                               }
+                       }
+                       int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
+                       int methodsLength = this.methods == null ? 0 : this.methods.length;
+                       if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
+                               this.scope.problemReporter().tooManyMethods(this);
+                       }
+                       
+                       if (this.methods != null) {
+                               for (int i = 0, count = this.methods.length; i < count; i++) {
+                                       this.methods[i].resolve(this.scope);
+                               }
+                       }
+                       // Resolve javadoc
+                       if (this.javadoc != null) {
+                               if (this.scope != null) {
+                                       this.javadoc.resolve(this.scope);
+                               }
+                       } else if (this.binding != null && !this.binding.isLocalType()) {
+                               this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
+                       }
+                       
+               } catch (AbortType e) {
+                       this.ignoreFurtherInvestigation = true;
+                       return;
+               }
+       }
+
+       public void resolve(BlockScope blockScope) {
+               // local type declaration
+
+               // need to build its scope first and proceed with binding's creation
+               if ((this.bits & IsAnonymousTypeMASK) == 0) blockScope.addLocalType(this);
+
+               if (binding != null) {
+                       // remember local types binding for innerclass emulation propagation
+                       blockScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
+
+                       // binding is not set if the receiver could not be created
+                       resolve();
+                       updateMaxFieldCount();
+               }
+       }
+       
+       public void resolve(ClassScope upperScope) {
+               // member scopes are already created
+               // request the construction of a binding if local member type
+
+               if (binding != null && binding instanceof LocalTypeBinding) {
+                       // remember local types binding for innerclass emulation propagation
+                       upperScope.referenceCompilationUnit().record((LocalTypeBinding)binding);
+               }
+               resolve();
+               updateMaxFieldCount();
+       }
+
+       public void resolve(CompilationUnitScope upperScope) {
+               // top level : scope are already created
+
+               resolve();
+               updateMaxFieldCount();
+       }
+
+       public void tagAsHavingErrors() {
+               ignoreFurtherInvestigation = true;
+       }
+
+
+       /**
+        *      Iteration for a package member type
+        *
+        */
+       public void traverse(
+               ASTVisitor visitor,
+               CompilationUnitScope unitScope) {
+
+               if (ignoreFurtherInvestigation)
+                       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 (memberTypes != null) {
+                                       int memberTypesLength = memberTypes.length;
+                                       for (int i = 0; i < memberTypesLength; i++)
+                                               memberTypes[i].traverse(visitor, scope);
+                               }
+                               if (fields != null) {
+                                       int fieldsLength = fields.length;
+                                       for (int i = 0; i < fieldsLength; i++) {
+                                               FieldDeclaration field;
+                                               if ((field = fields[i]).isStatic()) {
+                                                       field.traverse(visitor, staticInitializerScope);
+                                               } else {
+                                                       field.traverse(visitor, initializerScope);
+                                               }
+                                       }
+                               }
+                               if (methods != null) {
+                                       int methodsLength = methods.length;
+                                       for (int i = 0; i < methodsLength; i++)
+                                               methods[i].traverse(visitor, scope);
+                               }
+                       }
+                       visitor.endVisit(this, unitScope);
+               } catch (AbortType e) {
+                       // silent abort
+               }
+       }
+
+       /**
+        *      Iteration for a local innertype
+        *
+        */
+       public void traverse(ASTVisitor visitor, BlockScope blockScope) {
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       if (visitor.visit(this, blockScope)) {
+                               if (superclass != null)
+                                       superclass.traverse(visitor, scope);
+                               if (superInterfaces != null) {
+                                       int superInterfaceLength = superInterfaces.length;
+                                       for (int i = 0; i < superInterfaceLength; i++)
+                                               superInterfaces[i].traverse(visitor, scope);
+                               }
+                               if (memberTypes != null) {
+                                       int memberTypesLength = memberTypes.length;
+                                       for (int i = 0; i < memberTypesLength; i++)
+                                               memberTypes[i].traverse(visitor, scope);
+                               }
+                               if (fields != null) {
+                                       int fieldsLength = fields.length;
+                                       for (int i = 0; i < fieldsLength; i++) {
+                                               FieldDeclaration field;
+                                               if ((field = fields[i]).isStatic()) {
+                                                       // local type cannot have static fields
+                                               } else {
+                                                       field.traverse(visitor, initializerScope);
+                                               }
+                                       }
+                               }
+                               if (methods != null) {
+                                       int methodsLength = methods.length;
+                                       for (int i = 0; i < methodsLength; i++)
+                                               methods[i].traverse(visitor, scope);
+                               }
+                       }
+                       visitor.endVisit(this, blockScope);
+               } catch (AbortType e) {
+                       // silent abort
+               }
+       }
+
+       /**
+        *      Iteration for a member innertype
+        *
+        */
+       public void traverse(ASTVisitor visitor, ClassScope classScope) {
+               if (ignoreFurtherInvestigation)
+                       return;
+               try {
+                       if (visitor.visit(this, classScope)) {
+                               if (superclass != null)
+                                       superclass.traverse(visitor, scope);
+                               if (superInterfaces != null) {
+                                       int superInterfaceLength = superInterfaces.length;
+                                       for (int i = 0; i < superInterfaceLength; i++)
+                                               superInterfaces[i].traverse(visitor, scope);
+                               }
+                               if (memberTypes != null) {
+                                       int memberTypesLength = memberTypes.length;
+                                       for (int i = 0; i < memberTypesLength; i++)
+                                               memberTypes[i].traverse(visitor, scope);
+                               }
+                               if (fields != null) {
+                                       int fieldsLength = fields.length;
+                                       for (int i = 0; i < fieldsLength; i++) {
+                                               FieldDeclaration field;
+                                               if ((field = fields[i]).isStatic()) {
+                                                       field.traverse(visitor, staticInitializerScope);
+                                               } else {
+                                                       field.traverse(visitor, initializerScope);
+                                               }
+                                       }
+                               }
+                               if (methods != null) {
+                                       int methodsLength = methods.length;
+                                       for (int i = 0; i < methodsLength; i++)
+                                               methods[i].traverse(visitor, scope);
+                               }
+                       }
+                       visitor.endVisit(this, classScope);
+               } catch (AbortType e) {
+                       // silent abort
+               }
+       }       
+
+       /**
+        * MaxFieldCount's computation is necessary so as to reserve space for
+        * the flow info field portions. It corresponds to the maximum amount of
+        * fields this class or one of its innertypes have.
+        *
+        * During name resolution, types are traversed, and the max field count is recorded
+        * on the outermost type. It is then propagated down during the flow analysis.
+        *
+        * This method is doing either up/down propagation.
+        */
+       void updateMaxFieldCount() {
+
+               if (binding == null)
+                       return; // error scenario
+               TypeDeclaration outerMostType = scope.outerMostClassScope().referenceType();
+               if (maxFieldCount > outerMostType.maxFieldCount) {
+                       outerMostType.maxFieldCount = maxFieldCount; // up
+               } else {
+                       maxFieldCount = outerMostType.maxFieldCount; // down
+               }
+       }       
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/src/java/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
new file mode 100644 (file)
index 0000000..2e8e10c
--- /dev/null
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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.flow.FlowContext;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public abstract class TypeReference extends Expression {
+
+public TypeReference() {
+               super () ;
+               }
+
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+       return flowInfo;
+}
+
+// allows us to trap completion & selection nodes
+public void aboutToResolve(Scope scope) {
+       // default implementation: do nothing
+}
+/*
+ * Answer a base type reference (can be an array of base type).
+ */
+public static final TypeReference baseTypeReference(int baseType, int dim) {
+       
+       if (dim == 0) {
+               switch (baseType) {
+                       case (T_void) :
+                               return new SingleTypeReference(VoidBinding.simpleName, 0);
+                       case (T_boolean) :
+                               return new SingleTypeReference(BooleanBinding.simpleName, 0);
+                       case (T_char) :
+                               return new SingleTypeReference(CharBinding.simpleName, 0);
+                       case (T_float) :
+                               return new SingleTypeReference(FloatBinding.simpleName, 0);
+                       case (T_double) :
+                               return new SingleTypeReference(DoubleBinding.simpleName, 0);
+                       case (T_byte) :
+                               return new SingleTypeReference(ByteBinding.simpleName, 0);
+                       case (T_short) :
+                               return new SingleTypeReference(ShortBinding.simpleName, 0);
+                       case (T_int) :
+                               return new SingleTypeReference(IntBinding.simpleName, 0);
+                       default : //T_long      
+                               return new SingleTypeReference(LongBinding.simpleName, 0);
+               }
+       }
+       switch (baseType) {
+               case (T_void) :
+                       return new ArrayTypeReference(VoidBinding.simpleName, dim, 0);
+               case (T_boolean) :
+                       return new ArrayTypeReference(BooleanBinding.simpleName, dim, 0);
+               case (T_char) :
+                       return new ArrayTypeReference(CharBinding.simpleName, dim, 0);
+               case (T_float) :
+                       return new ArrayTypeReference(FloatBinding.simpleName, dim, 0);
+               case (T_double) :
+                       return new ArrayTypeReference(DoubleBinding.simpleName, dim, 0);
+               case (T_byte) :
+                       return new ArrayTypeReference(ByteBinding.simpleName, dim, 0);
+               case (T_short) :
+                       return new ArrayTypeReference(ShortBinding.simpleName, dim, 0);
+               case (T_int) :
+                       return new ArrayTypeReference(IntBinding.simpleName, dim, 0);
+               default : //T_long      
+                       return new ArrayTypeReference(LongBinding.simpleName, dim, 0);
+       }
+}
+public abstract TypeReference copyDims(int dim);
+public int dimensions() {
+       return 0;
+}
+public abstract TypeBinding getTypeBinding(Scope scope);
+/**
+ * @return char[][]
+ */
+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);
+               }
+       }
+       return 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);
+               }
+       }
+       return this.resolvedType;
+}
+protected void reportInvalidType(Scope scope) {
+       scope.problemReporter().invalidType(this, this.resolvedType);
+}
+protected void reportDeprecatedType(Scope scope) {
+       scope.problemReporter().deprecatedType(this.resolvedType, this);
+}
+public abstract void traverse(ASTVisitor visitor, ClassScope classScope);
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/src/java/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
new file mode 100644 (file)
index 0000000..1e3a2fc
--- /dev/null
@@ -0,0 +1,301 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class UnaryExpression extends OperatorExpression {
+       
+       public Expression expression;
+       public Constant optimizedBooleanConstant;
+
+       public UnaryExpression(Expression expression, int operator) {
+               this.expression = expression;
+               this.bits |= operator << OperatorSHIFT; // encode operator
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+                       
+               if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+                       return this.expression
+                               .analyseCode(currentScope, flowContext, flowInfo)
+                               .asNegatedCondition();
+               } else {
+                       return this.expression.analyseCode(currentScope, flowContext, flowInfo);
+               }
+       }
+
+       public Constant optimizedBooleanConstant() {
+               
+               return this.optimizedBooleanConstant == null 
+                               ? this.constant 
+                               : this.optimizedBooleanConstant;
+       }
+
+       /**
+        * Code generation for an unary operation
+        *
+        * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+        * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+        * @param valueRequired boolean
+        */
+       public void generateCode(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               boolean valueRequired) {
+                       
+               int pc = codeStream.position;
+               Label falseLabel, endifLabel;
+               if (this.constant != Constant.NotAConstant) {
+                       // inlined value
+                       if (valueRequired) {
+                               codeStream.generateConstant(this.constant, this.implicitConversion);
+                       }
+                       codeStream.recordPositionsFrom(pc, this.sourceStart);
+                       return;
+               }
+               switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+                       case NOT :
+                               switch (this.expression.implicitConversion >> 4) /* runtime type */ {
+                                       case T_boolean :
+                                               // ! <boolean>
+                                               // Generate code for the condition
+                                               this.expression.generateOptimizedBoolean(
+                                                       currentScope,
+                                                       codeStream,
+                                                       null,
+                                                       (falseLabel = new Label(codeStream)),
+                                                       valueRequired);
+                                               if (valueRequired) {
+                                                       codeStream.iconst_0();
+                                                       if (falseLabel.hasForwardReferences()) {
+                                                               codeStream.goto_(endifLabel = new Label(codeStream));
+                                                               codeStream.decrStackSize(1);
+                                                               falseLabel.place();
+                                                               codeStream.iconst_1();
+                                                               endifLabel.place();
+                                                       }
+                                               } else { // 6596: if (!(a && b)){} - must still place falseLabel
+                                                       falseLabel.place();
+                                               }                                               
+                                               break;
+                               }
+                               break;
+                       case TWIDDLE :
+                               switch (this.expression.implicitConversion >> 4 /* runtime */
+                                       ) {
+                                       case T_int :
+                                               // ~int
+                                               this.expression.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired) {
+                                                       codeStream.iconst_m1();
+                                                       codeStream.ixor();
+                                               }
+                                               break;
+                                       case T_long :
+                                               this.expression.generateCode(currentScope, codeStream, valueRequired);
+                                               if (valueRequired) {
+                                                       codeStream.ldc2_w(-1L);
+                                                       codeStream.lxor();
+                                               }
+                               }
+                               break;
+                       case MINUS :
+                               // - <num>
+                               if (this.constant != NotAConstant) {
+                                       if (valueRequired) {
+                                               switch (this.expression.implicitConversion >> 4){ /* runtime */
+                                                       case T_int :
+                                                               codeStream.generateInlinedValue(this.constant.intValue() * -1);
+                                                               break;
+                                                       case T_float :
+                                                               codeStream.generateInlinedValue(this.constant.floatValue() * -1.0f);
+                                                               break;
+                                                       case T_long :
+                                                               codeStream.generateInlinedValue(this.constant.longValue() * -1L);
+                                                               break;
+                                                       case T_double :
+                                                               codeStream.generateInlinedValue(this.constant.doubleValue() * -1.0);
+                                               }
+                                       }
+                               } else {
+                                       this.expression.generateCode(currentScope, codeStream, valueRequired);
+                                       if (valueRequired) {
+                                               switch (expression.implicitConversion >> 4){ /* runtime type */
+                                                       case T_int :
+                                                               codeStream.ineg();
+                                                               break;
+                                                       case T_float :
+                                                               codeStream.fneg();
+                                                               break;
+                                                       case T_long :
+                                                               codeStream.lneg();
+                                                               break;
+                                                       case T_double :
+                                                               codeStream.dneg();
+                                               }
+                                       }
+                               }
+                               break;
+                       case PLUS :
+                               this.expression.generateCode(currentScope, codeStream, valueRequired);
+               }
+               if (valueRequired) {
+                       codeStream.generateImplicitConversion(this.implicitConversion);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       /**
+        * Boolean operator code generation
+        *      Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
+        */
+       public void generateOptimizedBoolean(
+               BlockScope currentScope,
+               CodeStream codeStream,
+               Label trueLabel,
+               Label falseLabel,
+               boolean valueRequired) {
+
+               if ((this.constant != Constant.NotAConstant) && (this.constant.typeID() == T_boolean)) {
+                       super.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               trueLabel,
+                               falseLabel,
+                               valueRequired);
+                       return;
+               }
+               if (((this.bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+                       this.expression.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               falseLabel,
+                               trueLabel,
+                               valueRequired);
+               } else {
+                       super.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               trueLabel,
+                               falseLabel,
+                               valueRequired);
+               }
+       }
+
+       public StringBuffer printExpressionNoParenthesis(int indent, StringBuffer output) {
+               
+               output.append(operatorToString()).append(' ');
+               return this.expression.printExpression(0, output);
+       } 
+       
+       public TypeBinding resolveType(BlockScope scope) {
+               
+               boolean expressionIsCast;
+               if ((expressionIsCast = this.expression instanceof CastExpression) == true) this.expression.bits |= IgnoreNeedForCastCheckMASK; // will check later on
+               TypeBinding expressionType = this.expression.resolveType(scope);
+               if (expressionType == null) {
+                       this.constant = NotAConstant;
+                       return null;
+               }
+               int expressionTypeId = expressionType.id;
+               if (expressionTypeId > 15) {
+                       this.constant = NotAConstant;
+                       scope.problemReporter().invalidOperator(this, expressionType);
+                       return null;
+               }
+       
+               int tableId;
+               switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+                       case NOT :
+                               tableId = AND_AND;
+                               break;
+                       case TWIDDLE :
+                               tableId = LEFT_SHIFT;
+                               break;
+                       default :
+                               tableId = MINUS;
+               } //+ and - cases
+       
+               // the code is an int
+               // (cast)  left   Op (cast)  rigth --> result
+               //  0000   0000       0000   0000      0000
+               //  <<16   <<12       <<8    <<4       <<0
+               int operatorSignature = OperatorSignatures[tableId][(expressionTypeId << 4) + expressionTypeId];
+               this.expression.implicitConversion = operatorSignature >>> 12;
+               this.bits |= operatorSignature & 0xF;
+               switch (operatorSignature & 0xF) { // only switch on possible result type.....
+                       case T_boolean :
+                               this.resolvedType = BooleanBinding;
+                               break;
+                       case T_byte :
+                               this.resolvedType = ByteBinding;
+                               break;
+                       case T_char :
+                               this.resolvedType = CharBinding;
+                               break;
+                       case T_double :
+                               this.resolvedType = DoubleBinding;
+                               break;
+                       case T_float :
+                               this.resolvedType = FloatBinding;
+                               break;
+                       case T_int :
+                               this.resolvedType = IntBinding;
+                               break;
+                       case T_long :
+                               this.resolvedType = LongBinding;
+                               break;
+                       default : //error........
+                               this.constant = Constant.NotAConstant;
+                               if (expressionTypeId != T_undefined)
+                                       scope.problemReporter().invalidOperator(this, expressionType);
+                               return null;
+               }
+               // compute the constant when valid
+               if (this.expression.constant != Constant.NotAConstant) {
+                       this.constant =
+                               Constant.computeConstantOperation(
+                                       this.expression.constant,
+                                       expressionTypeId,
+                                       (bits & OperatorMASK) >> OperatorSHIFT);
+               } else {
+                       this.constant = Constant.NotAConstant;
+                       if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+                               Constant cst = expression.optimizedBooleanConstant();
+                               if (cst != Constant.NotAConstant) 
+                                       this.optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
+                       }
+               }
+               if (expressionIsCast) {
+               // check need for operand cast
+                       CastExpression.checkNeedForArgumentCast(scope, tableId, operatorSignature, this.expression, expressionTypeId);
+               }
+               return this.resolvedType;
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+                       
+               if (visitor.visit(this, blockScope)) {
+                       this.expression.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java b/src/java/org/eclipse/jdt/internal/compiler/ast/WhileStatement.java
new file mode 100644 (file)
index 0000000..b7e1441
--- /dev/null
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * 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.impl.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class WhileStatement extends Statement {
+       
+       public Expression condition;
+       public Statement action;
+       private Label breakLabel, continueLabel;
+       int preCondInitStateIndex = -1;
+       int condIfTrueInitStateIndex = -1;
+       int mergedInitStateIndex = -1;
+
+       public WhileStatement(Expression condition, Statement action, int s, int e) {
+
+               this.condition = condition;
+               this.action = action;
+               // remember useful empty statement
+               if (action instanceof EmptyStatement) action.bits |= IsUsefulEmptyStatementMASK;
+               sourceStart = s;
+               sourceEnd = e;
+       }
+
+       public FlowInfo analyseCode(
+               BlockScope currentScope,
+               FlowContext flowContext,
+               FlowInfo flowInfo) {
+
+               breakLabel = new Label();
+               continueLabel = new Label(); 
+
+               Constant cst = this.condition.constant;
+               boolean isConditionTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isConditionFalse = cst != NotAConstant && cst.booleanValue() == false;
+
+               cst = this.condition.optimizedBooleanConstant();
+               boolean isConditionOptimizedTrue = cst != NotAConstant && cst.booleanValue() == true;
+               boolean isConditionOptimizedFalse = cst != NotAConstant && cst.booleanValue() == false;
+               
+               preCondInitStateIndex =
+                       currentScope.methodScope().recordInitializationStates(flowInfo);
+               LoopingFlowContext condLoopContext;
+               FlowInfo postCondInfo =
+                       this.condition.analyseCode(
+                               currentScope,
+                               (condLoopContext =
+                                       new LoopingFlowContext(flowContext, this, null, null, currentScope)),
+                               flowInfo);
+
+               LoopingFlowContext loopingContext;
+               FlowInfo actionInfo;
+               if (action == null 
+                       || (action.isEmptyBlock() && currentScope.environment().options.complianceLevel <= ClassFileConstants.JDK1_3)) {
+                       condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+                       if (isConditionTrue) {
+                               return FlowInfo.DEAD_END;
+                       } else {
+                               FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
+                               if (isConditionOptimizedTrue){
+                                       mergedInfo.setReachMode(FlowInfo.UNREACHABLE);
+                               }
+                               mergedInitStateIndex =
+                                       currentScope.methodScope().recordInitializationStates(mergedInfo);
+                               return mergedInfo;
+                       }
+               } else {
+                       // in case the condition was inlined to false, record the fact that there is no way to reach any 
+                       // statement inside the looping action
+                       loopingContext =
+                               new LoopingFlowContext(
+                                       flowContext,
+                                       this,
+                                       breakLabel,
+                                       continueLabel,
+                                       currentScope);
+                       if (isConditionFalse) {
+                               actionInfo = FlowInfo.DEAD_END;
+                       } else {
+                               actionInfo = postCondInfo.initsWhenTrue().copy();
+                               if (isConditionOptimizedFalse){
+                                       actionInfo.setReachMode(FlowInfo.UNREACHABLE);
+                               }
+                       }
+
+                       // for computing local var attributes
+                       condIfTrueInitStateIndex =
+                               currentScope.methodScope().recordInitializationStates(
+                                       postCondInfo.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
+                       if (!actionInfo.isReachable() && !loopingContext.initsOnContinue.isReachable()) {
+                               continueLabel = null;
+                       } else {
+                               // TODO (philippe) should simplify in one Loop context
+                               condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+                               actionInfo = actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
+                               loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
+                       }
+               }
+
+               // end of loop
+               FlowInfo mergedInfo = FlowInfo.mergedOptimizedBranches(
+                               loopingContext.initsOnBreak, 
+                               isConditionOptimizedTrue, 
+                               postCondInfo.initsWhenFalse(), 
+                               isConditionOptimizedFalse,
+                               !isConditionTrue /*while(true); unreachable(); */);
+               mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
+               return mergedInfo;
+       }
+
+       /**
+        * While 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;
+               breakLabel.initialize(codeStream);
+
+               // generate condition
+               if (continueLabel == null) {
+                       // no need to reverse condition
+                       if (condition.constant == NotAConstant) {
+                               condition.generateOptimizedBoolean(
+                                       currentScope,
+                                       codeStream,
+                                       null,
+                                       breakLabel,
+                                       true);
+                       }
+               } else {
+                       continueLabel.initialize(codeStream);
+                       if (!(((condition.constant != NotAConstant)
+                               && (condition.constant.booleanValue() == true))
+                               || (action == null)
+                               || action.isEmptyBlock())) {
+                               int jumpPC = codeStream.position;
+                               codeStream.goto_(continueLabel);
+                               codeStream.recordPositionsFrom(jumpPC, condition.sourceStart);
+                       }
+               }
+               // generate the action
+               Label actionLabel;
+               (actionLabel = new Label(codeStream)).place();
+               if (action != null) {
+                       // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
+                       if (condIfTrueInitStateIndex != -1) {
+                               // insert all locals initialized inside the condition into the action generated prior to the condition
+                               codeStream.addDefinitelyAssignedVariables(
+                                       currentScope,
+                                       condIfTrueInitStateIndex);
+                       }
+                       action.generateCode(currentScope, codeStream);
+                       // May loose some local variable initializations : affecting the local variable attributes
+                       if (preCondInitStateIndex != -1) {
+                               codeStream.removeNotDefinitelyAssignedVariables(
+                                       currentScope,
+                                       preCondInitStateIndex);
+                       }
+
+               }
+               // output condition and branch back to the beginning of the repeated action
+               if (continueLabel != null) {
+                       continueLabel.place();
+                       condition.generateOptimizedBoolean(
+                               currentScope,
+                               codeStream,
+                               actionLabel,
+                               null,
+                               true);
+               }
+               breakLabel.place();
+
+               // May loose some local variable initializations : affecting the local variable attributes
+               if (mergedInitStateIndex != -1) {
+                       codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+                       codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+               }
+               codeStream.recordPositionsFrom(pc, this.sourceStart);
+       }
+
+       public void resolve(BlockScope scope) {
+
+               TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
+               condition.implicitWidening(type, type);
+               if (action != null)
+                       action.resolve(scope);
+       }
+
+       public StringBuffer printStatement(int tab, StringBuffer output) {
+
+               printIndent(tab, output).append("while ("); //$NON-NLS-1$
+               condition.printExpression(0, output).append(')');
+               if (action == null)
+                       output.append(';');
+               else
+                       action.printStatement(tab + 1, output); 
+               return output;
+       }
+
+       public void traverse(
+               ASTVisitor visitor,
+               BlockScope blockScope) {
+
+               if (visitor.visit(this, blockScope)) {
+                       condition.traverse(visitor, blockScope);
+                       if (action != null)
+                               action.traverse(visitor, blockScope);
+               }
+               visitor.endVisit(this, blockScope);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java b/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileConstants.java
new file mode 100644 (file)
index 0000000..127b0cd
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.classfmt;
+
+import org.eclipse.jdt.internal.compiler.env.*;
+
+public interface ClassFileConstants extends IConstants {
+       
+       int Utf8Tag = 1;
+       int IntegerTag = 3;
+       int FloatTag = 4;
+       int LongTag = 5;
+       int DoubleTag = 6;
+       int ClassTag = 7;
+       int StringTag = 8;
+       int FieldRefTag = 9;
+       int MethodRefTag = 10;
+       int InterfaceMethodRefTag = 11;
+       int NameAndTypeTag = 12;
+       
+       int ConstantMethodRefFixedSize = 5;
+       int ConstantClassFixedSize = 3;
+       int ConstantDoubleFixedSize = 9;
+       int ConstantFieldRefFixedSize = 5;
+       int ConstantFloatFixedSize = 5;
+       int ConstantIntegerFixedSize = 5;
+       int ConstantInterfaceMethodRefFixedSize = 5;
+       int ConstantLongFixedSize = 9;
+       int ConstantStringFixedSize = 3;
+       int ConstantUtf8FixedSize = 3;
+       int ConstantNameAndTypeFixedSize = 5;
+       
+       int MAJOR_VERSION_1_1 = 45;
+       int MAJOR_VERSION_1_2 = 46;
+       int MAJOR_VERSION_1_3 = 47;
+       int MAJOR_VERSION_1_4 = 48;
+       int MAJOR_VERSION_1_5 = 49; 
+       
+       int MINOR_VERSION_0 = 0;
+       int MINOR_VERSION_1 = 1;
+       int MINOR_VERSION_2 = 2;        
+       int MINOR_VERSION_3 = 3;        
+       
+       // JDK 1.1 -> 1.5, comparable value allowing to check both major/minor version at once 1.4.1 > 1.4.0
+       // 16 unsigned bits for major, then 16 bits for minor
+       long JDK1_1 = ((long)ClassFileConstants.MAJOR_VERSION_1_1 << 16) + ClassFileConstants.MINOR_VERSION_3; // 1.1. is 45.3
+       long JDK1_2 =  ((long)ClassFileConstants.MAJOR_VERSION_1_2 << 16) + ClassFileConstants.MINOR_VERSION_0;
+       long JDK1_3 =  ((long)ClassFileConstants.MAJOR_VERSION_1_3 << 16) + ClassFileConstants.MINOR_VERSION_0;
+       long JDK1_4 = ((long)ClassFileConstants.MAJOR_VERSION_1_4 << 16) + ClassFileConstants.MINOR_VERSION_0;
+       long JDK1_5 = ((long)ClassFileConstants.MAJOR_VERSION_1_5 << 16) + ClassFileConstants.MINOR_VERSION_0;  
+       
+       // 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; 
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
new file mode 100644 (file)
index 0000000..6899fa0
--- /dev/null
@@ -0,0 +1,824 @@
+/*******************************************************************************
+ * 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.classfmt;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+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.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;
+       private int accessFlags;
+       private char[] className;
+       private char[] superclassName;
+       private int interfacesCount;
+       private char[][] interfaceNames;
+       private int fieldsCount;
+       private FieldInfo[] fields;
+       private int methodsCount;
+       private MethodInfo[] methods;
+       private InnerClassInfo[] innerInfos;
+       private char[] sourceFileName;
+       // initialized in case the .class file is a nested type
+       private InnerClassInfo innerInfo;
+       private char[] classFileName;
+       private int classNameIndex;
+       private int innerInfoIndex;
+/**
+ * @param classFileBytes byte[]
+ *             Actual bytes of a .class file
+ * 
+ * @param fileName char[]
+ *             Actual name of the file that contains the bytes, can be null
+ * 
+ * @param fullyInitialize boolean
+ *             Flag to fully initialize the new object
+ * @exception ClassFormatException
+ */
+public ClassFileReader(byte[] classFileBytes, char[] fileName, boolean fullyInitialize) throws ClassFormatException {
+       // This method looks ugly but is actually quite simple, the constantPool is constructed
+       // in 3 passes.  All non-primitive constant pool members that usually refer to other members
+       // by index are tweaked to have their value in inst vars, this minor cost at read-time makes
+       // all subsequent uses of the constant pool element faster.
+       super(classFileBytes, 0);
+       this.classFileName = fileName;
+       int readOffset = 10;
+       try {
+               this.version = ((long)this.u2At(6) << 16) + this.u2At(4); // major<<16 + minor
+               constantPoolCount = this.u2At(8);
+               // Pass #1 - Fill in all primitive constants
+               this.constantPoolOffsets = new int[constantPoolCount];
+               for (int i = 1; i < constantPoolCount; i++) {
+                       int tag = this.u1At(readOffset);
+                       switch (tag) {
+                               case Utf8Tag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += u2At(readOffset + 1);
+                                       readOffset += ConstantUtf8FixedSize;
+                                       break;
+                               case IntegerTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantIntegerFixedSize;
+                                       break;
+                               case FloatTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantFloatFixedSize;
+                                       break;
+                               case LongTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantLongFixedSize;
+                                       i++;
+                                       break;
+                               case DoubleTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantDoubleFixedSize;
+                                       i++;
+                                       break;
+                               case ClassTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantClassFixedSize;
+                                       break;
+                               case StringTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantStringFixedSize;
+                                       break;
+                               case FieldRefTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantFieldRefFixedSize;
+                                       break;
+                               case MethodRefTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantMethodRefFixedSize;
+                                       break;
+                               case InterfaceMethodRefTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantInterfaceMethodRefFixedSize;
+                                       break;
+                               case NameAndTypeTag :
+                                       this.constantPoolOffsets[i] = readOffset;
+                                       readOffset += ConstantNameAndTypeFixedSize;
+                       }
+               }
+               // Read and validate access flags
+               this.accessFlags = u2At(readOffset);
+               readOffset += 2;
+
+               // Read the classname, use exception handlers to catch bad format
+               this.classNameIndex = u2At(readOffset);
+               this.className = getConstantClassNameAt(this.classNameIndex);
+               readOffset += 2;
+
+               // Read the superclass name, can be null for java.lang.Object
+               int superclassNameIndex = u2At(readOffset);
+               readOffset += 2;
+               // if superclassNameIndex is equals to 0 there is no need to set a value for the 
+               // field this.superclassName. null is fine.
+               if (superclassNameIndex != 0) {
+                       this.superclassName = getConstantClassNameAt(superclassNameIndex);
+               }
+
+               // Read the interfaces, use exception handlers to catch bad format
+               this.interfacesCount = u2At(readOffset);
+               readOffset += 2;
+               if (this.interfacesCount != 0) {
+                       this.interfaceNames = new char[this.interfacesCount][];
+                       for (int i = 0; i < this.interfacesCount; i++) {
+                               this.interfaceNames[i] = getConstantClassNameAt(u2At(readOffset));
+                               readOffset += 2;
+                       }
+               }
+               // Read the this.fields, use exception handlers to catch bad format
+               this.fieldsCount = u2At(readOffset);
+               readOffset += 2;
+               if (this.fieldsCount != 0) {
+                       FieldInfo field;
+                       this.fields = new FieldInfo[this.fieldsCount];
+                       for (int i = 0; i < this.fieldsCount; i++) {
+                               field = new FieldInfo(reference, this.constantPoolOffsets, readOffset);
+                               this.fields[i] = field;
+                               readOffset += field.sizeInBytes();
+                       }
+               }
+               // Read the this.methods
+               this.methodsCount = u2At(readOffset);
+               readOffset += 2;
+               if (this.methodsCount != 0) {
+                       this.methods = new MethodInfo[this.methodsCount];
+                       MethodInfo method;
+                       for (int i = 0; i < this.methodsCount; i++) {
+                               method = new MethodInfo(reference, this.constantPoolOffsets, readOffset);
+                               this.methods[i] = method;
+                               readOffset += method.sizeInBytes();
+                       }
+               }
+
+               // Read the attributes
+               int attributesCount = u2At(readOffset);
+               readOffset += 2;
+
+               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;
+                                                       }
+                                                       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;
+                                               }
+                                       }
+                               }
+                       }
+                       readOffset += (6 + u4At(readOffset + 2));
+               }
+               if (fullyInitialize) {
+                       this.initialize();
+               }
+       } catch(ClassFormatException e) {
+               throw e;
+       } catch (Exception e) {
+               throw new ClassFormatException(
+                       ClassFormatException.ErrTruncatedInput, 
+                       readOffset); 
+       }
+}
+
+/**
+ * @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 
+ */
+public int accessFlags() {
+       return this.accessFlags;
+}
+/**
+ * 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.
+ *
+ * @param constantPoolIndex int
+ * @return char[]
+ */
+private char[] getConstantClassNameAt(int constantPoolIndex) {
+       int utf8Offset = this.constantPoolOffsets[u2At(this.constantPoolOffsets[constantPoolIndex] + 1)];
+       return utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+}
+/**
+ * Answer the int array that corresponds to all the offsets of each entry in the constant pool
+ *
+ * @return int[]
+ */
+public int[] getConstantPoolOffsets() {
+       return this.constantPoolOffsets;
+}
+/*
+ * Answer the resolved compoundName of the enclosing type
+ * or null if the receiver is a top level type.
+ */
+public char[] getEnclosingTypeName() {
+       if (this.innerInfo != null && !this.isAnonymous()) {
+               return this.innerInfo.getEnclosingTypeName();
+       }
+       return null;
+}
+/**
+ * Answer the receiver's this.fields or null if the array is empty.
+ * @return org.eclipse.jdt.internal.compiler.api.IBinaryField[]
+ */
+public IBinaryField[] getFields() {
+       return this.fields;
+}
+/**
+ * Answer the file name which defines the type.
+ * The format is unspecified.
+ */
+public char[] getFileName() {
+       return this.classFileName;
+}
+/**
+ * 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.
+ * public class A {
+ *     public class B {
+ *     }
+ *     public void foo() {
+ *             class C {}
+ *     }
+ *     public Runnable bar() {
+ *             return new Runnable() {
+ *                     public void run() {}
+ *             };
+ *     }
+ * }
+ * It returns {'B'} for the member A$B
+ * It returns null for A
+ * It returns {'C'} for the local class A$1$C
+ * It returns null for the anonymous A$1
+ * @return char[]
+ */
+public char[] getInnerSourceName() {
+       if (this.innerInfo != null)
+               return this.innerInfo.getSourceName();
+       return null;
+}
+/**
+ * Answer the resolved names of the receiver's interfaces in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec
+ * or null if the array is empty.
+ *
+ * For example, java.lang.String is java/lang/String.
+ * @return char[][]
+ */
+public char[][] getInterfaceNames() {
+       return this.interfaceNames;
+}
+/**
+ * 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
+ * @return org.eclipse.jdt.internal.compiler.api.IBinaryNestedType[]
+ */
+public IBinaryNestedType[] getMemberTypes() {
+       // we might have some member types of the current type
+       if (this.innerInfos == null) return null;
+
+       int length = this.innerInfos.length;
+       int startingIndex = this.innerInfo != null ? this.innerInfoIndex + 1 : 0;
+       if (length != startingIndex) {
+               IBinaryNestedType[] memberTypes = 
+                       new IBinaryNestedType[length - this.innerInfoIndex]; 
+               int memberTypeIndex = 0;
+               for (int i = startingIndex; i < length; i++) {
+                       InnerClassInfo currentInnerInfo = this.innerInfos[i];
+                       int outerClassNameIdx = currentInnerInfo.outerClassNameIndex;
+                       int innerNameIndex = currentInnerInfo.innerNameIndex;
+                       /*
+                        * Checking that outerClassNameIDx is different from 0 should be enough to determine if an inner class
+                        * attribute entry is a member class, but due to the bug:
+                        * http://dev.eclipse.org/bugs/show_bug.cgi?id=14592
+                        * we needed to add an extra check. So we check that innerNameIndex is different from 0 as well.
+                        * 
+                        * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49879
+                        * From JavaMail 1.2, the class javax.mail.Folder contains an anonymous class in the
+                        * terminateQueue() method for which the inner attribute is boggus.
+                        * outerClassNameIdx is not 0, innerNameIndex is not 0, but the sourceName length is 0.
+                        * So I added this extra check to filter out this anonymous class from the 
+                        * member types.
+                        */
+                       if (outerClassNameIdx != 0
+                               && innerNameIndex != 0
+                               && outerClassNameIdx == this.classNameIndex
+                               && currentInnerInfo.getSourceName().length != 0) {
+                               memberTypes[memberTypeIndex++] = currentInnerInfo;
+                       }
+               }
+               if (memberTypeIndex == 0) return null;
+               if (memberTypeIndex != memberTypes.length) {
+                       // we need to resize the memberTypes array. Some local or anonymous classes
+                       // are present in the current class.
+                       System.arraycopy(
+                               memberTypes, 
+                               0, 
+                               (memberTypes = new IBinaryNestedType[memberTypeIndex]), 
+                               0, 
+                               memberTypeIndex); 
+               }
+               return memberTypes;
+       }
+       return null;
+}
+/**
+ * Answer the receiver's this.methods or null if the array is empty.
+ * @return org.eclipse.jdt.internal.compiler.api.env.IBinaryMethod[]
+ */
+public IBinaryMethod[] getMethods() {
+       return this.methods;
+}
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ * Set the AccDeprecated and AccSynthetic bits if necessary
+ * @return int
+ */
+public int getModifiers() {
+       if (this.innerInfo != null) {
+               if ((this.accessFlags & AccDeprecated) != 0) {
+                       return this.innerInfo.getModifiers() | AccDeprecated;
+               } else {
+                       return this.innerInfo.getModifiers();
+               }
+       }
+       return this.accessFlags;
+}
+/**
+ * Answer the resolved name of the type in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec.
+ *
+ * For example, java.lang.String is java/lang/String.
+ * @return char[]
+ */
+public char[] getName() {
+       return this.className;
+}
+/**
+ * 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
+ * or null if it does not have one.
+ *
+ * For example, java.lang.String is java/lang/String.
+ * @return char[]
+ */
+public char[] getSuperclassName() {
+       return this.superclassName;
+}
+/**
+ * Answer the major/minor version defined in this class file according to the VM spec.
+ * as a long: (major<<16)+minor
+ * @return the major/minor version found
+ */
+public long getVersion() {
+       return this.version;
+}
+/**
+ * Answer true if the receiver is an anonymous type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isAnonymous() {
+       if (this.innerInfo == null) return false;
+       char[] sourceName = this.innerInfo.getSourceName();
+       return (sourceName == null || sourceName.length == 0);
+}
+/**
+ * Answer whether the receiver contains the resolved binary form
+ * or the unresolved source form of the type.
+ * @return boolean
+ */
+public boolean isBinaryType() {
+       return true;
+}
+/**
+ * Answer true if the receiver is a class. False otherwise.
+ * @return boolean
+ */
+public boolean isClass() {
+       return (getModifiers() & AccInterface) == 0;
+}
+/**
+ * Answer true if the receiver is an interface. False otherwise.
+ * @return boolean
+ */
+public boolean isInterface() {
+       return (getModifiers() & AccInterface) != 0;
+}
+/**
+ * Answer true if the receiver is a local type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isLocal() {
+       if (this.innerInfo == null) return false;
+       if (this.innerInfo.getEnclosingTypeName() != null) return false;
+       char[] sourceName = this.innerInfo.getSourceName();
+       return (sourceName != null && sourceName.length > 0);   
+}
+/**
+ * Answer true if the receiver is a member type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isMember() {
+       if (this.innerInfo == null) return false;
+       if (this.innerInfo.getEnclosingTypeName() == null) return false;
+       char[] sourceName = this.innerInfo.getSourceName();
+       return (sourceName != null && sourceName.length > 0);    // protection against ill-formed attributes (67600)
+}
+/**
+ * Answer true if the receiver is a nested type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isNestedType() {
+       return this.innerInfo != null;
+}
+public static ClassFileReader read(File file) throws ClassFormatException, IOException {
+       return read(file, false);
+}
+public static ClassFileReader read(File file, boolean fullyInitialize) throws ClassFormatException, IOException {
+       byte classFileBytes[] = Util.getFileByteContent(file);
+       ClassFileReader classFileReader = new ClassFileReader(classFileBytes, file.getAbsolutePath().toCharArray());
+       if (fullyInitialize) {
+               classFileReader.initialize();
+       }
+       return classFileReader;
+}
+public static ClassFileReader read(String fileName) throws ClassFormatException, java.io.IOException {
+       return read(fileName, false);
+}
+public static ClassFileReader read(String fileName, boolean fullyInitialize) throws ClassFormatException, java.io.IOException {
+       return read(new File(fileName), fullyInitialize);
+}
+public static ClassFileReader read(
+       java.util.zip.ZipFile zip, 
+       String filename)
+       throws ClassFormatException, java.io.IOException {
+               return read(zip, filename, false);
+}
+public static ClassFileReader read(
+       java.util.zip.ZipFile zip, 
+       String filename,
+       boolean fullyInitialize)
+       throws ClassFormatException, java.io.IOException {
+       java.util.zip.ZipEntry ze = zip.getEntry(filename);
+       if (ze == null)
+               return null;
+       byte classFileBytes[] = Util.getZipEntryByteContent(ze, zip);
+       ClassFileReader classFileReader = new ClassFileReader(classFileBytes, filename.toCharArray());
+       if (fullyInitialize) {
+               classFileReader.initialize();
+       }
+       return classFileReader;
+}
+
+/**
+ * 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();
+}
+/**
+ * Check if the receiver has structural changes compare to the byte array in argument.
+ * Structural changes are:
+ * - modifiers changes for the class, the this.fields or the this.methods
+ * - signature changes for this.fields or this.methods.
+ * - changes in the number of this.fields or this.methods
+ * - changes for field constants
+ * - changes for thrown exceptions
+ * - change for the super class or any super interfaces.
+ * - changes for member types name or modifiers
+ * If any of these changes occurs, the method returns true. false otherwise. 
+ * The synthetic fields are included and the members are not required to be sorted.
+ * @param newBytes the bytes of the .class file we want to compare the receiver to
+ * @return boolean Returns true is there is a structural change between the two .class files, false otherwise
+ */
+public boolean hasStructuralChanges(byte[] newBytes) {
+       return hasStructuralChanges(newBytes, true, true);
+}
+/**
+ * Check if the receiver has structural changes compare to the byte array in argument.
+ * Structural changes are:
+ * - modifiers changes for the class, the this.fields or the this.methods
+ * - signature changes for this.fields or this.methods.
+ * - changes in the number of this.fields or this.methods
+ * - changes for field constants
+ * - changes for thrown exceptions
+ * - change for the super class or any super interfaces.
+ * - changes for member types name or modifiers
+ * If any of these changes occurs, the method returns true. false otherwise.
+ * @param newBytes the bytes of the .class file we want to compare the receiver to
+ * @param orderRequired a boolean indicating whether the members should be sorted or not
+ * @param excludesSynthetic a boolean indicating whether the synthetic members should be used in the comparison
+ * @return boolean Returns true is there is a structural change between the two .class files, false otherwise
+ */
+public boolean hasStructuralChanges(byte[] newBytes, boolean orderRequired, boolean excludesSynthetic) {
+       try {
+               ClassFileReader newClassFile =
+                       new ClassFileReader(newBytes, this.classFileName);
+               // type level comparison
+               // modifiers
+               if (this.getModifiers() != newClassFile.getModifiers())
+                       return true;
+               // superclass
+               if (!CharOperation.equals(this.getSuperclassName(), newClassFile.getSuperclassName()))
+                       return true;
+               // interfaces
+               char[][] newInterfacesNames = newClassFile.getInterfaceNames();
+               if (this.interfaceNames != newInterfacesNames) { // TypeConstants.NoSuperInterfaces
+                       int newInterfacesLength = newInterfacesNames == null ? 0 : newInterfacesNames.length;
+                       if (newInterfacesLength != this.interfacesCount)
+                               return true;
+                       for (int i = 0, max = this.interfacesCount; i < max; i++)
+                               if (!CharOperation.equals(this.interfaceNames[i], newInterfacesNames[i]))
+                                       return true;
+               }
+
+               // member types
+               IBinaryNestedType[] currentMemberTypes = this.getMemberTypes();
+               IBinaryNestedType[] otherMemberTypes = newClassFile.getMemberTypes();
+               if (currentMemberTypes != otherMemberTypes) { // TypeConstants.NoMemberTypes
+                       int currentMemberTypeLength = currentMemberTypes == null ? 0 : currentMemberTypes.length;
+                       int otherMemberTypeLength = otherMemberTypes == null ? 0 : otherMemberTypes.length;
+                       if (currentMemberTypeLength != otherMemberTypeLength)
+                               return true;
+                       for (int i = 0; i < currentMemberTypeLength; i++)
+                               if (!CharOperation.equals(currentMemberTypes[i].getName(), otherMemberTypes[i].getName())
+                                       || currentMemberTypes[i].getModifiers() != otherMemberTypes[i].getModifiers())
+                                               return true;
+               }
+
+               // fields
+               FieldInfo[] otherFieldInfos = (FieldInfo[]) newClassFile.getFields();
+               int otherFieldInfosLength = otherFieldInfos == null ? 0 : otherFieldInfos.length;
+               boolean compareFields = true;
+               if (this.fieldsCount == otherFieldInfosLength) {
+                       int i = 0;
+                       for (; i < this.fieldsCount; i++)
+                               if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i])) break;
+                       if ((compareFields = i != this.fieldsCount) && !orderRequired && !excludesSynthetic)
+                               return true;
+               }
+               if (compareFields) {
+                       if (this.fieldsCount != otherFieldInfosLength && !excludesSynthetic)
+                               return true;
+                       if (orderRequired) {
+                               if (this.fieldsCount != 0)
+                                       Arrays.sort(this.fields);
+                               if (otherFieldInfosLength != 0)
+                                       Arrays.sort(otherFieldInfos);
+                       }
+                       if (excludesSynthetic) {
+                               if (hasNonSyntheticFieldChanges(this.fields, otherFieldInfos))
+                                       return true;
+                       } else {
+                               for (int i = 0; i < this.fieldsCount; i++)
+                                       if (hasStructuralFieldChanges(this.fields[i], otherFieldInfos[i]))
+                                               return true;
+                       }
+               }
+               
+               // methods
+               MethodInfo[] otherMethodInfos = (MethodInfo[]) newClassFile.getMethods();
+               int otherMethodInfosLength = otherMethodInfos == null ? 0 : otherMethodInfos.length;
+               boolean compareMethods = true;
+               if (this.methodsCount == otherMethodInfosLength) {
+                       int i = 0;
+                       for (; i < this.methodsCount; i++)
+                               if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i])) break;
+                       if ((compareMethods = i != this.methodsCount) && !orderRequired && !excludesSynthetic)
+                               return true;
+               }
+               if (compareMethods) {
+                       if (this.methodsCount != otherMethodInfosLength && !excludesSynthetic)
+                               return true;
+                       if (orderRequired) {
+                               if (this.methodsCount != 0)
+                                       Arrays.sort(this.methods);
+                               if (otherMethodInfosLength != 0)
+                                       Arrays.sort(otherMethodInfos);  
+                       }
+                       if (excludesSynthetic) {
+                               if (hasNonSyntheticMethodChanges(this.methods, otherMethodInfos))
+                                       return true;
+                       } else {
+                               for (int i = 0; i < this.methodsCount; i++)
+                                       if (hasStructuralMethodChanges(this.methods[i], otherMethodInfos[i]))
+                                               return true;
+                       }
+               }
+
+               return false;
+       } catch (ClassFormatException e) {
+               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 (!CharOperation.equals(currentFieldInfo.getName(), otherFieldInfo.getName()))
+               return true;
+       if (!CharOperation.equals(currentFieldInfo.getTypeName(), otherFieldInfo.getTypeName()))
+               return true;
+       if (currentFieldInfo.hasConstant() != otherFieldInfo.hasConstant())
+               return true;
+       if (currentFieldInfo.hasConstant()) {
+               Constant currentConstant = currentFieldInfo.getConstant();
+               Constant otherConstant = otherFieldInfo.getConstant();
+               if (currentConstant.typeID() != otherConstant.typeID())
+                       return true;
+               if (!currentConstant.getClass().equals(otherConstant.getClass()))
+                       return true;
+               switch (currentConstant.typeID()) {
+                       case TypeIds.T_int :
+                               return currentConstant.intValue() != otherConstant.intValue();
+                       case TypeIds.T_byte :
+                               return currentConstant.byteValue() != otherConstant.byteValue();
+                       case TypeIds.T_short :
+                               return currentConstant.shortValue() != otherConstant.shortValue();
+                       case TypeIds.T_char :
+                               return currentConstant.charValue() != otherConstant.charValue();
+                       case TypeIds.T_long :
+                               return currentConstant.longValue() != otherConstant.longValue();
+                       case TypeIds.T_float :
+                               return currentConstant.floatValue() != otherConstant.floatValue();
+                       case TypeIds.T_double :
+                               return currentConstant.doubleValue() != otherConstant.doubleValue();
+                       case TypeIds.T_boolean :
+                               return currentConstant.booleanValue() != otherConstant.booleanValue();
+                       case TypeIds.T_String :
+                               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 (!CharOperation.equals(currentMethodInfo.getSelector(), otherMethodInfo.getSelector()))
+               return true;
+       if (!CharOperation.equals(currentMethodInfo.getMethodDescriptor(), otherMethodInfo.getMethodDescriptor()))
+               return true;
+
+       char[][] currentThrownExceptions = currentMethodInfo.getExceptionTypeNames();
+       char[][] otherThrownExceptions = otherMethodInfo.getExceptionTypeNames();
+       if (currentThrownExceptions != otherThrownExceptions) { // TypeConstants.NoExceptions
+               int currentThrownExceptionsLength = currentThrownExceptions == null ? 0 : currentThrownExceptions.length;
+               int otherThrownExceptionsLength = otherThrownExceptions == null ? 0 : otherThrownExceptions.length;
+               if (currentThrownExceptionsLength != otherThrownExceptionsLength)
+                       return true;
+               for (int k = 0; k < currentThrownExceptionsLength; k++)
+                       if (!CharOperation.equals(currentThrownExceptions[k], otherThrownExceptions[k]))
+                               return true;
+       }
+       return false;
+}
+/**
+ * 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.
+ */
+private void initialize() throws ClassFormatException {
+       try {
+               for (int i = 0, max = fieldsCount; i < max; i++) {
+                       fields[i].initialize();
+               }
+               for (int i = 0, max = methodsCount; i < max; i++) {
+                       methods[i].initialize();
+               }
+               if (innerInfos != null) {
+                       for (int i = 0, max = innerInfos.length; i < max; i++) {
+                               innerInfos[i].initialize();
+                       }
+               }
+               this.reset();
+       } catch(RuntimeException e) {
+               ClassFormatException exception = new ClassFormatException(e, this.classFileName);
+               throw exception;
+       }
+}
+protected void reset() {
+       this.constantPoolOffsets = null;
+       super.reset();
+}
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java b/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFileStruct.java
new file mode 100644 (file)
index 0000000..caaaa17
--- /dev/null
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * 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.classfmt;
+
+abstract public class ClassFileStruct implements ClassFileConstants {
+       byte[] reference;
+       int structOffset;
+public ClassFileStruct(byte classFileBytes[], int off) {
+       reference = classFileBytes;
+       structOffset = off;
+}
+public ClassFileStruct (byte classFileBytes[], int off, boolean verifyStructure) {
+       reference = classFileBytes;
+       structOffset = off;
+}
+public double doubleAt(int relativeOffset) {
+       return (Double.longBitsToDouble(this.i8At(relativeOffset)));
+}
+public float floatAt(int relativeOffset) {
+       return (Float.intBitsToFloat(this.i4At(relativeOffset)));
+}
+public int i1At(int relativeOffset) {
+       return reference[relativeOffset + structOffset];
+}
+public int i2At(int relativeOffset) {
+       int position = relativeOffset + structOffset;
+       return (reference[position++] << 8) + (reference[position] & 0xFF);
+}
+public int i4At(int relativeOffset) {
+       int position = relativeOffset + structOffset;
+       return ((reference[position++] & 0xFF) << 24) + ((reference[position++] & 0xFF) << 16) + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF);
+}
+public long i8At(int relativeOffset) {
+       int position = relativeOffset + structOffset;
+       return (((long) (reference[position++] & 0xFF)) << 56) 
+                                       + (((long) (reference[position++] & 0xFF)) << 48) 
+                                       + (((long) (reference[position++] & 0xFF)) << 40) 
+                                       + (((long) (reference[position++] & 0xFF)) << 32) 
+                                       + (((long) (reference[position++] & 0xFF)) << 24) 
+                                       + (((long) (reference[position++] & 0xFF)) << 16) 
+                                       + (((long) (reference[position++] & 0xFF)) << 8) 
+                                       + (reference[position++] & 0xFF);
+}
+public static String printTypeModifiers(int modifiers) {
+
+       java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
+       java.io.PrintWriter print = new java.io.PrintWriter(out);
+
+       if ((modifiers & AccPublic) != 0) print.print("public "); //$NON-NLS-1$
+       if ((modifiers & AccPrivate) != 0) print.print("private "); //$NON-NLS-1$
+       if ((modifiers & AccFinal) != 0) print.print("final "); //$NON-NLS-1$
+       if ((modifiers & AccSuper) != 0) print.print("super "); //$NON-NLS-1$
+       if ((modifiers & AccInterface) != 0) print.print("interface "); //$NON-NLS-1$
+       if ((modifiers & AccAbstract) != 0) print.print("abstract "); //$NON-NLS-1$
+       print.flush();
+       return out.toString();
+}
+public int u1At(int relativeOffset) {
+       return (reference[relativeOffset + structOffset] & 0xFF);
+}
+public int u2At(int relativeOffset) {
+       int position = relativeOffset + structOffset;
+       return ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF);
+}
+public long u4At(int relativeOffset) {
+       int position = relativeOffset + structOffset;
+       return (((reference[position++] & 0xFFL) << 24) + ((reference[position++] & 0xFF) << 16) + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF));
+}
+public char[] utf8At(int relativeOffset, int bytesAvailable) {
+       int length = bytesAvailable;
+       char outputBuf[] = new char[bytesAvailable];
+       int outputPos = 0;
+       int readOffset = this.structOffset + relativeOffset;
+       
+       while (length != 0) {
+               int x = this.reference[readOffset++] & 0xFF;
+               length--;
+               if ((0x80 & x) != 0) {
+                       if ((x & 0x20) != 0) {
+                               length-=2;
+                               x = ((x & 0xF) << 12) | ((this.reference[readOffset++] & 0x3F) << 6) | (this.reference[readOffset++] & 0x3F);
+                       } else {
+                               length--;
+                               x = ((x & 0x1F) << 6) | (this.reference[readOffset++] & 0x3F);
+                       }
+               }
+               outputBuf[outputPos++] = (char) x;
+       }
+
+       if (outputPos != bytesAvailable) {
+               System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]), 0, outputPos);
+       }
+       return outputBuf;
+}
+
+protected void reset() {
+       this.reference = null;
+}
+
+public char[] utf8At(int relativeOffset, int bytesAvailable, boolean testValidity) throws ClassFormatException {
+       int x, y, z;
+       int length = bytesAvailable;
+       char outputBuf[] = new char[bytesAvailable];
+       int outputPos = 0;
+       int readOffset = structOffset + relativeOffset;
+       
+       while (length != 0) {
+               x = reference[readOffset++] & 0xFF;
+               length--;
+               if ((0x80 & x) != 0) {
+                       if (testValidity) {
+                               if ((0x40 & x) == 0) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                               }
+                               if (length < 1) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                               }
+                       }
+                       y = this.reference[readOffset++] & 0xFF;
+                       length--;
+                       if (testValidity) {
+                               if ((y & 0xC0) != 0x80) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                               }
+                       }
+                       if ((x & 0x20) != 0) {
+                               if (testValidity && (length < 1)) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                               }
+                               z = this.reference[readOffset++] & 0xFF;
+                               length--;
+                               if (testValidity && ((z & 0xC0) != 0x80)) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                               }
+                               x = ((x & 0x1F) << 12) + ((y & 0x3F) << 6) + (z & 0x3F);
+                               if (testValidity && (x < 0x0800)) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                               }
+                       } else {
+                               x = ((x & 0x1F) << 6) + (y & 0x3F);
+                               if (testValidity && !((x == 0) || (x >= 0x80))) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                               }
+                       }
+               } else {
+                       if (testValidity && x == 0) {
+                                       throw new ClassFormatException(ClassFormatException.ErrMalformedUtf8);
+                       }
+               }
+               outputBuf[outputPos++] = (char) x;
+       }
+
+       if (outputPos != bytesAvailable) {
+               System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]), 0, outputPos);
+       }
+       return outputBuf;
+}
+public static void verifyMethodNameAndSignature(char[] name, char[] signature) throws ClassFormatException {
+
+       // ensure name is not empty 
+       if (name.length == 0) {
+               throw new ClassFormatException(ClassFormatException.ErrInvalidMethodName);
+       }
+
+       // if name begins with the < character it must be clinit or init
+       if (name[0] == '<') {
+               if (new String(name).equals("<clinit>") || new String(name).equals("<init>")) { //$NON-NLS-2$ //$NON-NLS-1$
+                       int signatureLength = signature.length;
+                       if (!((signatureLength > 2)
+                               && (signature[0] == '(')
+                               && (signature[signatureLength - 2] == ')')
+                               && (signature[signatureLength - 1] == 'V'))) {
+                               throw new ClassFormatException(ClassFormatException.ErrInvalidMethodSignature);
+                       }
+               } else {
+                       throw new ClassFormatException(ClassFormatException.ErrInvalidMethodName);
+               }
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java b/src/java/org/eclipse/jdt/internal/compiler/classfmt/ClassFormatException.java
new file mode 100644 (file)
index 0000000..fd3f30e
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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.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;
+       public static final int ErrBadConstantClass = 4;
+       public static final int ErrBadConstantString = 5;
+       public static final int ErrBadConstantNameAndType = 6;
+       public static final int ErrBadConstantFieldRef = 7;
+       public static final int ErrBadConstantMethodRef = 8;
+       public static final int ErrBadConstantInterfaceMethodRef = 9;
+       public static final int ErrBadConstantPoolIndex = 10;
+       public static final int ErrBadSuperclassName = 11;
+       public static final int ErrInterfaceCannotBeFinal = 12;
+       public static final int ErrInterfaceMustBeAbstract = 13;
+       public static final int ErrBadModifiers = 14;
+       public static final int ErrClassCannotBeAbstractFinal = 15;
+       public static final int ErrBadClassname = 16;
+       public static final int ErrBadFieldInfo = 17;
+       public static final int ErrBadMethodInfo = 17;
+       public static final int ErrEmptyConstantPool = 18;
+       public static final int ErrMalformedUtf8 = 19;
+       public static final int ErrUnknownConstantTag = 20;
+       public static final int ErrTruncatedInput = 21;
+       public static final int ErrMethodMustBeAbstract = 22;
+       public static final int ErrMalformedAttribute = 23;
+       public static final int ErrBadInterface = 24;
+       public static final int ErrInterfaceMustSubclassObject = 25;
+       public static final int ErrIncorrectInterfaceMethods = 26;
+       public static final int ErrInvalidMethodName = 27;
+       public static final int ErrInvalidMethodSignature = 28;
+
+       private static final long serialVersionUID = 6667458511042774540L; // backward compatible
+
+       private int errorCode;
+       private int bufferPosition;
+       private RuntimeException nestedException;
+       private char[] fileName;
+
+       public ClassFormatException(RuntimeException e, char[] fileName) {
+               this.nestedException = e;
+       }
+       public ClassFormatException(int code) {
+               errorCode = code;
+       }
+       public ClassFormatException(int code, int bufPos) {
+               errorCode = code;
+               bufferPosition = bufPos;
+       }
+       /**
+        * @return int
+        */
+       public int getErrorCode() {
+               return errorCode;
+       }
+       /**
+        * @return int
+        */
+       public int getBufferPosition() {
+               return bufferPosition;
+       }
+       /**
+        * Returns the underlying <code>Throwable</code> that caused the failure.
+        * 
+        * @return the wrappered <code>Throwable</code>, or <code>null</code>
+        *         if the direct case of the failure was at the Java model layer
+        */
+       public Throwable getException() {
+               return this.nestedException;
+       }
+       public void printStackTrace() {
+               printStackTrace(System.err);
+       }
+       /**
+        * Prints this exception's stack trace to the given print stream.
+        * 
+        * @param output
+        *            the print stream
+        * @since 3.0
+        */
+       public void printStackTrace(PrintStream output) {
+               synchronized (output) {
+                       super.printStackTrace(output);
+                       Throwable throwable = getException();
+                       if (throwable != null) {
+                               if (this.fileName != null) {
+                                       output.print("Caused in "); //$NON-NLS-1$
+                                       output.print(this.fileName);
+                                       output.print(" by: "); //$NON-NLS-1$
+                               } else {
+                                       output.print("Caused by: "); //$NON-NLS-1$
+                               }
+                               throwable.printStackTrace(output);
+                       }
+               }
+       }
+       /**
+        * Prints this exception's stack trace to the given print writer.
+        * 
+        * @param output
+        *            the print writer
+        * @since 3.0
+        */
+       public void printStackTrace(PrintWriter output) {
+               synchronized (output) {
+                       super.printStackTrace(output);
+                       Throwable throwable = getException();
+                       if (throwable != null) {
+                               if (this.fileName != null) {
+                                       output.print("Caused in "); //$NON-NLS-1$
+                                       output.print(this.fileName);
+                                       output.print(" by: "); //$NON-NLS-1$
+                               } else {
+                                       output.print("Caused by: "); //$NON-NLS-1$
+                               }
+                               throwable.printStackTrace(output);
+                       }
+               }
+       }
+}
\ No newline at end of file
diff --git a/src/java/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/src/java/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
new file mode 100644 (file)
index 0000000..26392d8
--- /dev/null
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * 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.classfmt;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
+import org.eclipse.jdt.internal.compiler.env.IBinaryField;
+import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
+import org.eclipse.jdt.internal.compiler.impl.ByteConstant;
+import org.eclipse.jdt.internal.compiler.impl.CharConstant;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.DoubleConstant;
+import org.eclipse.jdt.internal.compiler.impl.FloatConstant;
+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.TypeIds;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class FieldInfo extends ClassFileStruct implements AttributeNamesConstants, IBinaryField, Comparable, TypeIds {
+       private Constant constant;
+       private boolean isDeprecated;
+       private boolean isSynthetic;
+       private int[] constantPoolOffsets;
+       private int accessFlags;
+       private char[] name;
+       private char[] signature;
+       private int attributeBytes;
+       private Object wrappedConstantValue;
+/**
+ * @param classFileBytes byte[]
+ * @param offsets int[]
+ * @param offset int
+ */
+public FieldInfo (byte classFileBytes[], int offsets[], int offset) {
+       super(classFileBytes, offset);
+       constantPoolOffsets = offsets;
+       accessFlags = -1;
+       int attributesCount = u2At(6);
+       int readOffset = 8;
+       for (int i = 0; i < attributesCount; i++) {
+               readOffset += (6 + u4At(readOffset + 2));
+       }
+       attributeBytes = readOffset;
+}
+/**
+ * Return the constant of the field.
+ * Return org.eclipse.jdt.internal.compiler.impl.Constant.NotAConstant if there is none.
+ * @return org.eclipse.jdt.internal.compiler.impl.Constant
+ */
+public Constant getConstant() {
+       if (constant == null) {
+               // read constant
+               readConstantAttribute();
+       }
+       return constant;
+}
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ * Set the AccDeprecated and AccSynthetic bits if necessary
+ * @return int
+ */
+public int getModifiers() {
+       if (accessFlags == -1) {
+               // compute the accessflag. Don't forget the deprecated attribute
+               accessFlags = u2At(0);
+               readDeprecatedAndSyntheticAttributes();
+               if (isDeprecated) {
+                       accessFlags |= AccDeprecated;
+               }
+               if (isSynthetic) {
+                       accessFlags |= AccSynthetic;
+               }
+       }
+       return accessFlags;
+}
+/**
+ * Answer the name of the field.
+ * @return char[]
+ */
+public char[] getName() {
+       if (name == null) {
+               // read the name
+               int utf8Offset = constantPoolOffsets[u2At(2)] - structOffset;
+               name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+       }
+       return name;
+}
+/**
+ * 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.
+ *
+ * For example:
+ *   - java.lang.String is Ljava/lang/String;
+ *   - an int is I
+ *   - a 2 dimensional array of strings is [[Ljava/lang/String;
+ *   - an array of floats is [F
+ * @return char[]
+ */
+public char[] getTypeName() {
+       if (signature == null) {
+               // read the signature
+               int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
+               signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+       }
+       return signature;
+}
+/**
+ * Return a wrapper that contains the constant of the field.
+ * @return java.lang.Object
+ */
+public Object getWrappedConstantValue() {
+
+       if (this.wrappedConstantValue == null) {
+               if (hasConstant()) {
+                       Constant fieldConstant = getConstant();
+                       switch (fieldConstant.typeID()) {
+                               case T_int :
+                                       this.wrappedConstantValue = new Integer(fieldConstant.intValue());
+                                       break;
+                               case T_byte :
+                                       this.wrappedConstantValue = new Byte(fieldConstant.byteValue());
+                                       break;
+                               case T_short :
+                                       this.wrappedConstantValue = new Short(fieldConstant.shortValue());
+                                       break;
+                               case T_char :
+                                       this.wrappedConstantValue = new Character(fieldConstant.charValue());
+                                       break;
+                               case T_float :
+                                       this.wrappedConstantValue = new Float(fieldConstant.floatValue());
+                                       break;
+                               case T_double :
+                                       this.wrappedConstantValue = new Double(fieldConstant.doubleValue());
+                                       break;
+                               case T_boolean :
+                                       this.wrappedConstantValue = Util.toBoolean(fieldConstant.booleanValue());
+                                       break;
+                               case T_long :
+                                       this.wrappedConstantValue = new Long(fieldConstant.longValue());
+                                       break;
+                               case T_String :
+                                       this.wrappedConstantValue = fieldConstant.stringValue();
+                       }
+               }
+       }
+       return this.wrappedConstantValue;
+}
+/**
+ * Return true if the field has a constant value attribute, false otherwise.
+ * @return boolean
+ */
+public boolean hasConstant() {
+       return getConstant() != Constant.NotAConstant;
+}
+/**
+ * Return true if the field is a synthetic field, false otherwise.
+ * @return boolean
+ */
+public boolean isSynthetic() {
+       return (getModifiers() & AccSynthetic) != 0;
+}
+
+private void readConstantAttribute() {
+       int attributesCount = u2At(6);
+       int readOffset = 8;
+       boolean isConstant = false;
+       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, ConstantValueName)) {
+                       isConstant = true;
+                       // read the right constant
+                       int relativeOffset = constantPoolOffsets[u2At(readOffset + 6)] - structOffset;
+                       switch (u1At(relativeOffset)) {
+                               case IntegerTag :
+                                       char[] sign = getTypeName();
+                                       if (sign.length == 1) {
+                                               switch (sign[0]) {
+                                                       case 'Z' : // boolean constant
+                                                               constant = new BooleanConstant(i4At(relativeOffset + 1) == 1);
+                                                               break;
+                                                       case 'I' : // integer constant
+                                                               constant = new IntConstant(i4At(relativeOffset + 1));
+                                                               break;
+                                                       case 'C' : // char constant
+                                                               constant = new CharConstant((char) i4At(relativeOffset + 1));
+                                                               break;
+                                                       case 'B' : // byte constant
+                                                               constant = new ByteConstant((byte) i4At(relativeOffset + 1));
+                                                               break;
+                                                       case 'S' : // short constant
+                                                               constant = new ShortConstant((short) i4At(relativeOffset + 1));
+                                                               break;
+                                                       default:
+                                                               constant = Constant.NotAConstant;                   
+                                               }
+                                       } else {
+                                               constant = Constant.NotAConstant;
+                                       }
+                                       break;
+                               case FloatTag :
+                                       constant = new FloatConstant(floatAt(relativeOffset + 1));
+                                       break;
+                               case DoubleTag :
+                                       constant = new DoubleConstant(doubleAt(relativeOffset + 1));
+                                       break;
+                               case LongTag :
+                                       constant = new LongConstant(i8At(relativeOffset + 1));
+                                       break;
+                               case StringTag :
+                                       utf8Offset = constantPoolOffsets[u2At(relativeOffset + 1)] - structOffset;
+                                       constant = 
+                                               new StringConstant(
+                                                       String.valueOf(utf8At(utf8Offset + 3, u2At(utf8Offset + 1)))); 
+                                       break;
+                       }
+               }
+               readOffset += (6 + u4At(readOffset + 2));
+       }
+       if (!isConstant) {
+               constant = Constant.NotAConstant;
+       }
+}
+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));
+       }
+}
+/**
+ * Answer the size of the receiver in bytes.
+ * 
+ * @return int
+ */
+public int sizeInBytes() {
+       return attributeBytes;
+}
+public void throwFormatException() throws ClassFormatException {
+       throw new ClassFormatException(ClassFormatException.ErrBadFieldInfo);
+}
+public String toString() {
+       StringBuffer buffer = new StringBuffer(this.getClass().getName());
+       int modifiers = getModifiers();
+       return buffer
+               .append("{") //$NON-NLS-1$
+               .append(
+                       ((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((modifiers & 0x0001) == 1 ? "public " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((modifiers & 0x0002) == 0x0002 ? "private " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((modifiers & 0x0004) == 0x0004 ? "protected " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((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$
+               .append(getTypeName())
+               .append(" ") //$NON-NLS-1$
+               .append(getName())
+               .append(" ") //$NON-NLS-1$
+               .append(getConstant())
+               .append("}") //$NON-NLS-1$
+               .toString(); 
+}
+
+public int compareTo(Object o) {
+       if (!(o instanceof FieldInfo)) {
+               throw new ClassCastException();
+       }
+       return new String(this.getName()).compareTo(new String(((FieldInfo) o).getName()));
+}
+/**
+ * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
+ * will be therefore fully initialized and we can get rid of the bytes.
+ */
+void initialize() {
+       getModifiers();
+       getName();
+       getConstant();
+       getTypeName();
+       reset();
+}
+protected void reset() {
+       this.constantPoolOffsets = null;
+       super.reset();
+}
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java b/src/java/org/eclipse/jdt/internal/compiler/classfmt/InnerClassInfo.java
new file mode 100644 (file)
index 0000000..476c664
--- /dev/null
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * 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.classfmt;
+
+import org.eclipse.jdt.internal.compiler.env.IBinaryNestedType;
+
+/**
+ * Describes one entry in the classes table of the InnerClasses attribute.
+ * See the inner class specification (The class file attribute "InnerClasses").
+ */
+
+public class InnerClassInfo extends ClassFileStruct implements IBinaryNestedType {
+       int innerClassNameIndex = -1;
+       int outerClassNameIndex = -1;
+       int innerNameIndex = -1;
+       private char[] innerClassName;
+       private char[] outerClassName;
+       private char[] innerName;
+       private int accessFlags = -1;
+       private int[] constantPoolOffsets;
+       private boolean readInnerClassName = false;
+       private boolean readOuterClassName = false;
+       private boolean readInnerName = false;
+public InnerClassInfo(byte classFileBytes[], int offsets[], int offset) {
+       super(classFileBytes, offset);
+       constantPoolOffsets = offsets;
+       innerClassNameIndex = u2At(0);
+       outerClassNameIndex = u2At(2);
+       this.innerNameIndex = u2At(4);
+}
+/**
+ * Answer the resolved name of the enclosing type in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec.
+ *
+ * For example, java.lang.String is java/lang/String.
+ * @return char[]
+ */
+public char[] getEnclosingTypeName() {
+       if (!readOuterClassName) {
+               // read outer class name
+               readOuterClassName = true;
+               if (outerClassNameIndex != 0) {
+                       int utf8Offset = 
+                               constantPoolOffsets[u2At(
+                                       constantPoolOffsets[outerClassNameIndex] - structOffset + 1)]
+                                       - structOffset; 
+                       outerClassName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+               }
+
+       }
+       return outerClassName;
+}
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ * @return int
+ */
+public int getModifiers() {
+       if (accessFlags == -1) {
+               // read access flag
+               accessFlags = u2At(6);
+       }
+       return accessFlags;
+}
+/**
+ * Answer the resolved name of the member type in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec.
+ *
+ * For example, p1.p2.A.M is p1/p2/A$M.
+ * @return char[]
+ */
+public char[] getName() {
+       if (!readInnerClassName) {
+               // read the inner class name
+               readInnerClassName = true;
+               if (innerClassNameIndex != 0) {
+                       int  classOffset = constantPoolOffsets[innerClassNameIndex] - structOffset;
+                       int utf8Offset = constantPoolOffsets[u2At(classOffset + 1)] - structOffset;
+                       innerClassName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+               }
+       }
+       return innerClassName;
+}
+/**
+ * Answer the source name of the member type.
+ *
+ * For example, p1.p2.A.M is M.
+ * @return char[]
+ */
+public char[] getSourceName() {
+       if (!this.readInnerName) {
+               this.readInnerName = true;
+               if (innerNameIndex != 0) {
+                       int utf8Offset = constantPoolOffsets[innerNameIndex] - structOffset;
+                       innerName = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+               }
+       }
+       return innerName;
+}
+/**
+ * Answer the string representation of the receiver
+ * @return java.lang.String
+ */
+public String toString() {
+       StringBuffer buffer = new StringBuffer();
+       if (getName() != null) {
+               buffer.append(getName());
+       }
+       buffer.append("\n"); //$NON-NLS-1$
+       if (getEnclosingTypeName() != null) {
+               buffer.append(getEnclosingTypeName());
+       }
+       buffer.append("\n"); //$NON-NLS-1$
+       if (getSourceName() != null) {
+               buffer.append(getSourceName());
+       }
+       return buffer.toString();   
+}
+/**
+ * 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();
+       getSourceName();
+       getEnclosingTypeName();
+       reset();
+}
+protected void reset() {
+       this.constantPoolOffsets = null;
+       super.reset();
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/src/java/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
new file mode 100644 (file)
index 0000000..c9255be
--- /dev/null
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * 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.classfmt;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
+import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
+
+public class MethodInfo extends ClassFileStruct implements IBinaryMethod, AttributeNamesConstants, Comparable {
+       private char[][] exceptionNames;
+       private int[] constantPoolOffsets;
+       private boolean isDeprecated;
+       private boolean isSynthetic;
+       private int accessFlags;
+       private char[] name;
+       private char[] signature;
+       private int attributeBytes;
+       static private final char[][] noException = CharOperation.NO_CHAR_CHAR;
+/**
+ * @param classFileBytes byte[]
+ * @param offsets int[]
+ * @param offset int
+ */
+public MethodInfo (byte classFileBytes[], int offsets[], int offset) {
+       super(classFileBytes, offset);
+       constantPoolOffsets = offsets;
+       accessFlags = -1;
+       int attributesCount = u2At(6);
+       int readOffset = 8;
+       for (int i = 0; i < attributesCount; i++) {
+               readOffset += (6 + u4At(readOffset + 2));
+       }
+       attributeBytes = readOffset;
+}
+/**
+ * @see org.eclipse.jdt.internal.compiler.env.IGenericMethod#getArgumentNames()
+ */
+public char[][] getArgumentNames() {
+       return null;
+}
+/**
+ * Answer the resolved names of the exception types in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec
+ * or null if the array is empty.
+ *
+ * For example, java.lang.String is java/lang/String.
+ * @return char[][]
+ */
+public char[][] getExceptionTypeNames() {
+       if (exceptionNames == null) {
+               readExceptionAttributes();
+       }
+       return exceptionNames;
+}
+/**
+ * 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.
+ *
+ * For example:
+ *   - int foo(String) is (Ljava/lang/String;)I
+ *   - void foo(Object[]) is (I)[Ljava/lang/Object;
+ * @return char[]
+ */
+public char[] getMethodDescriptor() {
+       if (signature == null) {
+               // read the name
+               int utf8Offset = constantPoolOffsets[u2At(4)] - structOffset;
+               signature = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+       }
+       return signature;
+}
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ * Set the AccDeprecated and AccSynthetic bits if necessary
+ * @return int
+ */
+public int getModifiers() {
+       if (accessFlags == -1) {
+               // compute the accessflag. Don't forget the deprecated attribute
+               accessFlags = u2At(0);
+               readDeprecatedAndSyntheticAttributes();
+               if (isDeprecated) {
+                       accessFlags |= AccDeprecated;
+               }
+               if (isSynthetic) {
+                       accessFlags |= AccSynthetic;
+               }
+       }
+       return accessFlags;
+}
+/**
+ * Answer the name of the method.
+ *
+ * For a constructor, answer <init> & <clinit> for a clinit method.
+ * @return char[]
+ */
+public char[] getSelector() {
+       if (name == null) {
+               // read the name
+               int utf8Offset = constantPoolOffsets[u2At(2)] - structOffset;
+               name = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+       }
+       return name;
+}
+/**
+ * Answer true if the method is a class initializer, false otherwise.
+ * @return boolean
+ */
+public boolean isClinit() {
+       char[] selector = getSelector();
+       return selector[0] == '<' && selector.length == 8; // Can only match <clinit>
+}
+/**
+ * Answer true if the method is a constructor, false otherwise.
+ * @return boolean
+ */
+public boolean isConstructor() {
+       char[] selector = getSelector();
+       return selector[0] == '<' && selector.length == 6; // Can only match <init>
+}
+/**
+ * Return true if the field is a synthetic method, false otherwise.
+ * @return boolean
+ */
+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;
+       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, ExceptionsName)) {
+                       // read the number of exception entries
+                       int entriesNumber = u2At(readOffset + 6);
+                       // place the readOffset at the beginning of the exceptions table
+                       readOffset += 8;
+                       if (entriesNumber == 0) {
+                               exceptionNames = noException;
+                       } else {
+                               exceptionNames = new char[entriesNumber][];
+                               for (int j = 0; j < entriesNumber; j++) {
+                                       utf8Offset = 
+                                               constantPoolOffsets[u2At(
+                                                       constantPoolOffsets[u2At(readOffset)] - structOffset + 1)]
+                                                       - structOffset; 
+                                       exceptionNames[j] = utf8At(utf8Offset + 3, u2At(utf8Offset + 1));
+                                       readOffset += 2;
+                               }
+                       }
+               } else {
+                       readOffset += (6 + u4At(readOffset + 2));
+               }
+       }
+       if (exceptionNames == null) {
+               exceptionNames = noException;
+       }
+}
+/**
+ * Answer the size of the receiver in bytes.
+ * 
+ * @return int
+ */
+public int sizeInBytes() {
+       return attributeBytes;
+}
+public String toString() {
+       int modifiers = getModifiers();
+       StringBuffer buffer = new StringBuffer(this.getClass().getName());
+       return buffer
+               .append("{") //$NON-NLS-1$
+               .append(
+                       ((modifiers & AccDeprecated) != 0 ? "deprecated " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((modifiers & 0x0001) == 1 ? "public " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((modifiers & 0x0002) == 0x0002 ? "private " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((modifiers & 0x0004) == 0x0004 ? "protected " : "") //$NON-NLS-1$ //$NON-NLS-2$
+                               + ((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$
+               .append(getSelector())
+               .append(getMethodDescriptor())
+               .append("}") //$NON-NLS-1$
+               .toString(); 
+}
+public int compareTo(Object o) {
+       if (!(o instanceof MethodInfo)) {
+               throw new ClassCastException();
+       }
+
+       MethodInfo otherMethod = (MethodInfo) o;
+       int result = new String(this.getSelector()).compareTo(new String(otherMethod.getSelector()));
+       if (result != 0) return result;
+       return new String(this.getMethodDescriptor()).compareTo(new String(otherMethod.getMethodDescriptor()));
+}
+
+/**
+ * This method is used to fully initialize the contents of the receiver. All methodinfos, fields infos
+ * will be therefore fully initialized and we can get rid of the bytes.
+ */
+void initialize() {
+       getModifiers();
+       getSelector();
+       getMethodDescriptor();
+       getExceptionTypeNames();
+       reset();
+}
+protected void reset() {
+       this.constantPoolOffsets = null;
+       super.reset();
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/AttributeNamesConstants.java
new file mode 100644 (file)
index 0000000..577b9bd
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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 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'};
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/CaseLabel.java
new file mode 100644 (file)
index 0000000..725588e
--- /dev/null
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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 class CaseLabel extends Label {
+       public int instructionPosition = POS_NOT_SET;
+       public int backwardsBranch = POS_NOT_SET;
+/**
+ * CaseLabel constructor comment.
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ */
+public CaseLabel(CodeStream codeStream) {
+       super(codeStream);
+}
+/*
+* Put down  a refernece to the array at the location in the codestream.
+*/
+void branch() {
+       if (position == POS_NOT_SET) {
+               addForwardReference(codeStream.position);
+               // Leave 4 bytes free to generate the jump offset afterwards
+               codeStream.position += 4;
+               codeStream.classFileOffset += 4;
+       } else { //Position is set. Write it!
+               codeStream.writeSignedWord(position - codeStream.position + 1);
+       }
+}
+/*
+* Put down  a refernece to the array at the location in the codestream.
+*/
+void branchWide() {
+       if (position == POS_NOT_SET) {
+               addForwardReference(codeStream.position);
+               // Leave 4 bytes free to generate the jump offset afterwards
+               codeStream.position += 4;
+       } else { //Position is set. Write it!
+               codeStream.writeSignedWord(position - codeStream.position + 1);
+       }
+}
+public boolean isStandardLabel(){
+       return false;
+}
+/*
+* Put down  a reference to the array at the location in the codestream.
+*/
+public void place() {
+       position = codeStream.position;
+       if (instructionPosition == POS_NOT_SET)
+               backwardsBranch = position;
+       else {
+               int offset = position - instructionPosition;
+               for (int i = 0; i < forwardReferenceCount; i++) {
+                       codeStream.writeSignedWord(forwardReferences[i], offset);
+               }
+               // add the label int the codeStream labels collection
+               codeStream.addLabel(this);
+       }
+}
+/*
+* Put down  a refernece to the array at the location in the codestream.
+*/
+void placeInstruction() {
+       if (instructionPosition == POS_NOT_SET) {
+               instructionPosition = codeStream.position;
+               if (backwardsBranch != POS_NOT_SET) {
+                       int offset = backwardsBranch - instructionPosition;
+                       for (int i = 0; i < forwardReferenceCount; i++)
+                               codeStream.writeSignedWord(forwardReferences[i], offset);
+                       backwardsBranch = POS_NOT_SET;
+               }
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/CharArrayCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/CharArrayCache.java
new file mode 100644 (file)
index 0000000..b5f8126
--- /dev/null
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * 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;
+
+public class CharArrayCache {
+       // to avoid using Enumerations, walk the individual tables skipping nulls
+       public char[] keyTable[];
+       public int valueTable[];
+       int elementSize; // number of elements in the table
+       int threshold;
+/**
+ * Constructs a new, empty hashtable. A default capacity is used.
+ * Note that the hashtable will automatically grow when it gets full.
+ */
+public CharArrayCache() {
+       this(13);
+}
+/**
+ * Constructs a new, empty hashtable with the specified initial
+ * capacity.
+ * @param initialCapacity int
+ *     the initial number of buckets
+ */
+public CharArrayCache(int initialCapacity) {
+       this.elementSize = 0;
+       this.threshold = (int) (initialCapacity * 0.66f);
+       this.keyTable = new char[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(char[] key) {
+       int index = hashCodeChar(key);
+       while (keyTable[index] != null) {
+               if (CharOperation.equals(keyTable[index], key))
+                       return true;
+               index = (index + 1) % keyTable.length;
+       }
+       return false;
+}
+/** 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(char[] key) {
+       int index = hashCodeChar(key);
+       while (keyTable[index] != null) {
+               if (CharOperation.equals(keyTable[index], key))
+                       return valueTable[index];
+               index = (index + 1) % keyTable.length;
+       }
+       return -1;
+}
+private int hashCodeChar(char[] val) {
+       int length = val.length;
+       int hash = 0;
+       int n = 2; // number of characters skipped
+       for (int i = 0; i < length; i += n) {
+               hash += val[i];
+       }
+       return (hash & 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(char[] key, int value) { 
+       int index = hashCodeChar(key);
+       while (keyTable[index] != null) {
+               if (CharOperation.equals(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() {
+       CharArrayCache newHashtable = new CharArrayCache(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;
+}
+/** Remove the object associated with the specified key in the
+ * hashtable.
+ * @param key <CODE>char[]</CODE> the specified key
+ */
+public void remove(char[] key) {
+       int index = hashCodeChar(key);
+       while (keyTable[index] != null) {
+               if (CharOperation.equals(keyTable[index], key)) {
+                       valueTable[index] = 0;
+                       keyTable[index] = null;
+                       return;
+               }
+               index = (index + 1) % keyTable.length;
+       }
+}
+/**
+ * Returns the key corresponding to the value. Returns null if the
+ * receiver doesn't contain the value.
+ * @param value int the value that we are looking for
+ * @return Object
+ */
+public char[] returnKeyFor(int value) {
+       for (int i = keyTable.length; i-- > 0;) {
+               if (valueTable[i] == value) {
+                       return keyTable[i];
+               }
+       }
+       return null;
+}
+/**
+ * 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/java/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
new file mode 100644 (file)
index 0000000..4d7a6ef
--- /dev/null
@@ -0,0 +1,5336 @@
+/*******************************************************************************
+ * 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.internal.compiler.*;
+
+import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.*;
+import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, BaseTypes, TypeConstants, TypeIds {
+
+       public static final boolean DEBUG = false;
+       
+       // It will be responsible for the following items.
+       // -> Tracking Max Stack.
+
+       public int stackMax; // Use Ints to keep from using extra bc when adding
+       public int stackDepth; // Use Ints to keep from using extra bc when adding
+       public int maxLocals;
+       public static final int LABELS_INCREMENT = 5;
+       public byte[] bCodeStream;
+       public int pcToSourceMapSize;
+       public int[] pcToSourceMap = new int[24];
+       public int lastEntryPC; // last entry recorded
+       public int[] lineSeparatorPositions;
+       public int position; // So when first set can be incremented
+       public int classFileOffset;
+       public int startingClassFileOffset; // I need to keep the starting point inside the byte array
+       public ConstantPool constantPool; // The constant pool used to generate bytecodes that need to store information into the constant pool
+       public ClassFile classFile; // The current classfile it is associated to.
+       // local variable attributes output
+       public static final int LOCALS_INCREMENT = 10;
+       public LocalVariableBinding[] locals = new LocalVariableBinding[LOCALS_INCREMENT];
+       static LocalVariableBinding[] noLocals = new LocalVariableBinding[LOCALS_INCREMENT];
+       public LocalVariableBinding[] visibleLocals = new LocalVariableBinding[LOCALS_INCREMENT];
+       static LocalVariableBinding[] noVisibleLocals = new LocalVariableBinding[LOCALS_INCREMENT];
+       int visibleLocalsCount;
+       public AbstractMethodDeclaration methodDeclaration;
+       public ExceptionLabel[] exceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
+       static ExceptionLabel[] noExceptionHandlers = new ExceptionLabel[LABELS_INCREMENT];
+       public int exceptionHandlersNumber;
+       public static FieldBinding[] ImplicitThis = new FieldBinding[] {};
+       public boolean generateLineNumberAttributes;
+       public boolean generateLocalVariableTableAttributes;
+       public boolean preserveUnusedLocals;
+       // store all the labels placed at the current position to be able to optimize
+       // a jump to the next bytecode.
+       public Label[] labels = new Label[LABELS_INCREMENT];
+       static Label[] noLabels = new Label[LABELS_INCREMENT];
+       public int countLabels;
+       public int allLocalsCounter;
+       public int maxFieldCount;
+       // to handle goto_w
+       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;
+       }
+}
+final public void aaload() {
+       if (DEBUG) System.out.println(position + "\t\taaload"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_aaload;
+}
+final public void aastore() {
+       if (DEBUG) System.out.println(position + "\t\taastore"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_aastore;
+}
+final public void aconst_null() {
+       if (DEBUG) System.out.println(position + "\t\taconst_null"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax) {
+               stackMax = stackDepth;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_aconst_null;
+}
+public final void addDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
+       // Required to fix 1PR0XVS: LFRE:WINNT - Compiler: variable table for method appears incorrect
+       if (!generateLocalVariableTableAttributes)
+               return;
+/*     if (initStateIndex == lastInitStateIndexWhenAddingInits)
+               return;
+       lastInitStateIndexWhenAddingInits = initStateIndex;
+       if (lastInitStateIndexWhenRemovingInits != initStateIndex){
+               lastInitStateIndexWhenRemovingInits = -2; // reinitialize remove index 
+               // remove(1)-add(1)-remove(1) -> ignore second remove
+               // remove(1)-add(2)-remove(1) -> perform second remove
+       }
+       
+*/     for (int i = 0; i < visibleLocalsCount; i++) {
+               LocalVariableBinding localBinding = visibleLocals[i];
+               if (localBinding != null) {
+                       // Check if the local is definitely assigned
+                       if ((initStateIndex != -1) && isDefinitelyAssigned(scope, initStateIndex, localBinding)) {
+                               if ((localBinding.initializationCount == 0) || (localBinding.initializationPCs[((localBinding.initializationCount - 1) << 1) + 1] != -1)) {
+                                       /* There are two cases:
+                                        * 1) there is no initialization interval opened ==> add an opened interval
+                                        * 2) there is already some initialization intervals but the last one is closed ==> add an opened interval
+                                        * An opened interval means that the value at localBinding.initializationPCs[localBinding.initializationCount - 1][1]
+                                        * is equals to -1.
+                                        * initializationPCs is a collection of pairs of int:
+                                        *      first value is the startPC and second value is the endPC. -1 one for the last value means that the interval
+                                        *      is not closed yet.
+                                        */
+                                       localBinding.recordInitializationStartPC(position);
+                               }
+                       }
+               }
+       }
+}
+public void addLabel(Label aLabel) {
+       if (countLabels == labels.length)
+               System.arraycopy(labels, 0, labels = new Label[countLabels + LABELS_INCREMENT], 0, countLabels);
+       labels[countLabels++] = aLabel;
+}
+public void addVisibleLocalVariable(LocalVariableBinding localBinding) {
+       if (!generateLocalVariableTableAttributes)
+               return;
+
+       if (visibleLocalsCount >= visibleLocals.length)
+               System.arraycopy(visibleLocals, 0, visibleLocals = new LocalVariableBinding[visibleLocalsCount * 2], 0, visibleLocalsCount);
+       visibleLocals[visibleLocalsCount++] = localBinding;
+}
+final public void aload(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\taload:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals <= iArg) {
+               maxLocals = iArg + 1;
+       }
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_aload;
+               writeUnsignedShort(iArg);
+       } else {
+               // Don't need to use the wide bytecode
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_aload;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void aload_0() {
+       if (DEBUG) System.out.println(position + "\t\taload_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax) {
+               stackMax = stackDepth;
+       }
+       if (maxLocals == 0) {
+               maxLocals = 1;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_aload_0;
+}
+final public void aload_1() {
+       if (DEBUG) System.out.println(position + "\t\taload_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals <= 1) {
+               maxLocals = 2;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_aload_1;
+}
+final public void aload_2() {
+       if (DEBUG) System.out.println(position + "\t\taload_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals <= 2) {
+               maxLocals = 3;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_aload_2;
+}
+final public void aload_3() {
+       if (DEBUG) System.out.println(position + "\t\taload_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals <= 3) {
+               maxLocals = 4;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_aload_3;
+}
+public final void anewarray(TypeBinding typeBinding) {
+       if (DEBUG) System.out.println(position + "\t\tanewarray: " + typeBinding); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_anewarray;
+       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+final public void areturn() {
+       if (DEBUG) System.out.println(position + "\t\tareturn"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       // the stackDepth should be equal to 0 
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_areturn;
+}
+public void arrayAt(int typeBindingID) {
+       switch (typeBindingID) {
+               case T_int :
+                       this.iaload();
+                       break;
+               case T_byte :
+               case T_boolean :
+                       this.baload();
+                       break;
+               case T_short :
+                       this.saload();
+                       break;
+               case T_char :
+                       this.caload();
+                       break;
+               case T_long :
+                       this.laload();
+                       break;
+               case T_float :
+                       this.faload();
+                       break;
+               case T_double :
+                       this.daload();
+                       break;
+               default :
+                       this.aaload();
+       }
+}
+public void arrayAtPut(int elementTypeID, boolean valueRequired) {
+       switch (elementTypeID) {
+               case T_int :
+                       if (valueRequired)
+                               dup_x2();
+                       iastore();
+                       break;
+               case T_byte :
+               case T_boolean :
+                       if (valueRequired)
+                               dup_x2();
+                       bastore();
+                       break;
+               case T_short :
+                       if (valueRequired)
+                               dup_x2();
+                       sastore();
+                       break;
+               case T_char :
+                       if (valueRequired)
+                               dup_x2();
+                       castore();
+                       break;
+               case T_long :
+                       if (valueRequired)
+                               dup2_x2();
+                       lastore();
+                       break;
+               case T_float :
+                       if (valueRequired)
+                               dup_x2();
+                       fastore();
+                       break;
+               case T_double :
+                       if (valueRequired)
+                               dup2_x2();
+                       dastore();
+                       break;
+               default :
+                       if (valueRequired)
+                               dup_x2();
+                       aastore();
+       }
+}
+final public void arraylength() {
+       if (DEBUG) System.out.println(position + "\t\tarraylength"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_arraylength;
+}
+final public void astore(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tastore:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= iArg) {
+               maxLocals = iArg + 1;
+       }
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position+=2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_astore;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position+=2;
+               bCodeStream[classFileOffset++] = OPC_astore;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void astore_0() {
+       if (DEBUG) System.out.println(position + "\t\tastore_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals == 0) {
+               maxLocals = 1;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_astore_0;
+}
+final public void astore_1() {
+       if (DEBUG) System.out.println(position + "\t\tastore_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 1) {
+               maxLocals = 2;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_astore_1;
+}
+final public void astore_2() {
+       if (DEBUG) System.out.println(position + "\t\tastore_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 2) {
+               maxLocals = 3;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_astore_2;
+}
+final public void astore_3() {
+       if (DEBUG) System.out.println(position + "\t\tastore_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 3) {
+               maxLocals = 4;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_astore_3;
+}
+final public void athrow() {
+       if (DEBUG) System.out.println(position + "\t\tathrow"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_athrow;
+}
+final public void baload() {
+       if (DEBUG) System.out.println(position + "\t\tbaload"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_baload;
+}
+final public void bastore() {
+       if (DEBUG) System.out.println(position + "\t\tbastore"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_bastore;
+}
+final public void bipush(byte b) {
+       if (DEBUG) System.out.println(position + "\t\tbipush "+b); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 1 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position += 2;
+       bCodeStream[classFileOffset++] = OPC_bipush;
+       bCodeStream[classFileOffset++] = b;
+}
+final public void caload() {
+       if (DEBUG) System.out.println(position + "\t\tcaload"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_caload;
+}
+final public void castore() {
+       if (DEBUG) System.out.println(position + "\t\tcastore"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_castore;
+}
+public final void checkcast(TypeBinding typeBinding) {
+       if (DEBUG) System.out.println(position + "\t\tcheckcast:"+typeBinding); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_checkcast;
+       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+final public void d2f() {
+       if (DEBUG) System.out.println(position + "\t\td2f"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_d2f;
+}
+final public void d2i() {
+       if (DEBUG) System.out.println(position + "\t\td2i"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_d2i;
+}
+final public void d2l() {
+       if (DEBUG) System.out.println(position + "\t\td2l"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_d2l;
+}
+final public void dadd() {
+       if (DEBUG) System.out.println(position + "\t\tdadd"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dadd;
+}
+final public void daload() {
+       if (DEBUG) System.out.println(position + "\t\tdaload"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_daload;
+}
+final public void dastore() {
+       if (DEBUG) System.out.println(position + "\t\tdastore"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 4;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dastore;
+}
+final public void dcmpg() {
+       if (DEBUG) System.out.println(position + "\t\tdcmpg"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dcmpg;
+}
+final public void dcmpl() {
+       if (DEBUG) System.out.println(position + "\t\tdcmpl"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dcmpl;
+}
+final public void dconst_0() {
+       if (DEBUG) System.out.println(position + "\t\tdconst_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dconst_0;
+}
+final public void dconst_1() {
+       if (DEBUG) System.out.println(position + "\t\tdconst_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dconst_1;
+}
+final public void ddiv() {
+       if (DEBUG) System.out.println(position + "\t\tddiv"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ddiv;
+}
+public void decrStackSize(int offset) {
+       stackDepth -= offset;
+}
+final public void dload(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tdload:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals < iArg + 2) {
+               maxLocals = iArg + 2; // + 2 because it is a double
+       }
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_dload;
+               writeUnsignedShort(iArg);
+       } else {
+               // Don't need to use the wide bytecode
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_dload;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void dload_0() {
+       if (DEBUG) System.out.println(position + "\t\tdload_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals < 2) {
+               maxLocals = 2;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dload_0;
+}
+final public void dload_1() {
+       if (DEBUG) System.out.println(position + "\t\tdload_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals < 3) {
+               maxLocals = 3;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dload_1;
+}
+final public void dload_2() {
+       if (DEBUG) System.out.println(position + "\t\tdload_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals < 4) {
+               maxLocals = 4;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dload_2;
+}
+final public void dload_3() {
+       if (DEBUG) System.out.println(position + "\t\tdload_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (maxLocals < 5) {
+               maxLocals = 5;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dload_3;
+}
+final public void dmul() {
+       if (DEBUG) System.out.println(position + "\t\tdmul"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dmul;
+}
+final public void dneg() {
+       if (DEBUG) System.out.println(position + "\t\tdneg"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dneg;
+}
+final public void drem() {
+       if (DEBUG) System.out.println(position + "\t\tdrem"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_drem;
+}
+final public void dreturn() {
+       if (DEBUG) System.out.println(position + "\t\tdreturn"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       // the stackDepth should be equal to 0 
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dreturn;
+}
+final public void dstore(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tdstore:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals <= iArg + 1) {
+               maxLocals = iArg + 2;
+       }
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_dstore;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_dstore;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void dstore_0() {
+       if (DEBUG) System.out.println(position + "\t\tdstore_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 2) {
+               maxLocals = 2;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dstore_0;
+}
+final public void dstore_1() {
+       if (DEBUG) System.out.println(position + "\t\tdstore_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 3) {
+               maxLocals = 3;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dstore_1;
+}
+final public void dstore_2() {
+       if (DEBUG) System.out.println(position + "\t\tdstore_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 4) {
+               maxLocals = 4;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dstore_2;
+}
+final public void dstore_3() {
+       if (DEBUG) System.out.println(position + "\t\tdstore_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 5) {
+               maxLocals = 5;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dstore_3;
+}
+final public void dsub() {
+       if (DEBUG) System.out.println(position + "\t\tdsub"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dsub;
+}
+final public void dup() {
+       if (DEBUG) System.out.println(position + "\t\tdup"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax) {
+               stackMax = stackDepth;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dup;
+}
+final public void dup_x1() {
+       if (DEBUG) System.out.println(position + "\t\tdup_x1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dup_x1;
+}
+final public void dup_x2() {
+       if (DEBUG) System.out.println(position + "\t\tdup_x2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dup_x2;
+}
+final public void dup2() {
+       if (DEBUG) System.out.println(position + "\t\tdup2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dup2;
+}
+final public void dup2_x1() {
+       if (DEBUG) System.out.println(position + "\t\tdup2_x1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dup2_x1;
+}
+final public void dup2_x2() {
+       if (DEBUG) System.out.println(position + "\t\tdup2_x2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_dup2_x2;
+}
+public void exitUserScope(BlockScope blockScope) {
+       // mark all the scope's locals as loosing their definite assignment
+
+       if (!generateLocalVariableTableAttributes)
+               return;
+       for (int i = 0; i < visibleLocalsCount; i++) {
+               LocalVariableBinding visibleLocal = visibleLocals[i];
+               if ((visibleLocal != null) && (visibleLocal.declaringScope == blockScope)) { 
+                       // there maybe some some preserved locals never initialized
+                       if (visibleLocal.initializationCount > 0){
+                               visibleLocals[i].recordInitializationEndPC(position);
+                       }
+                       visibleLocals[i] = null; // this variable is no longer visible afterwards
+               }
+       }
+}
+final public void f2d() {
+       if (DEBUG) System.out.println(position + "\t\tf2d"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_f2d;
+}
+final public void f2i() {
+       if (DEBUG) System.out.println(position + "\t\tf2i"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_f2i;
+}
+final public void f2l() {
+       if (DEBUG) System.out.println(position + "\t\tf2l"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_f2l;
+}
+final public void fadd() {
+       if (DEBUG) System.out.println(position + "\t\tfadd"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fadd;
+}
+final public void faload() {
+       if (DEBUG) System.out.println(position + "\t\tfaload"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_faload;
+}
+final public void fastore() {
+       if (DEBUG) System.out.println(position + "\t\tfaload"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fastore;
+}
+final public void fcmpg() {
+       if (DEBUG) System.out.println(position + "\t\tfcmpg"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fcmpg;
+}
+final public void fcmpl() {
+       if (DEBUG) System.out.println(position + "\t\tfcmpl"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fcmpl;
+}
+final public void fconst_0() {
+       if (DEBUG) System.out.println(position + "\t\tfconst_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fconst_0;
+}
+final public void fconst_1() {
+       if (DEBUG) System.out.println(position + "\t\tfconst_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fconst_1;
+}
+final public void fconst_2() {
+       if (DEBUG) System.out.println(position + "\t\tfconst_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fconst_2;
+}
+final public void fdiv() {
+       if (DEBUG) System.out.println(position + "\t\tfdiv"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fdiv;
+}
+final public void fload(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tfload:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= iArg) {
+               maxLocals = iArg + 1;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_fload;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_fload;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void fload_0() {
+       if (DEBUG) System.out.println(position + "\t\tfload_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals == 0) {
+               maxLocals = 1;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fload_0;
+}
+final public void fload_1() {
+       if (DEBUG) System.out.println(position + "\t\tfload_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= 1) {
+               maxLocals = 2;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fload_1;
+}
+final public void fload_2() {
+       if (DEBUG) System.out.println(position + "\t\tfload_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= 2) {
+               maxLocals = 3;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fload_2;
+}
+final public void fload_3() {
+       if (DEBUG) System.out.println(position + "\t\tfload_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= 3) {
+               maxLocals = 4;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fload_3;
+}
+final public void fmul() {
+       if (DEBUG) System.out.println(position + "\t\tfmul"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fmul;
+}
+final public void fneg() {
+       if (DEBUG) System.out.println(position + "\t\tfneg"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fneg;
+}
+final public void frem() {
+       if (DEBUG) System.out.println(position + "\t\tfrem"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_frem;
+}
+final public void freturn() {
+       if (DEBUG) System.out.println(position + "\t\tfreturn"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       // the stackDepth should be equal to 0 
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_freturn;
+}
+final public void fstore(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tfstore:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= iArg) {
+               maxLocals = iArg + 1;
+       }
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_fstore;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_fstore;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void fstore_0() {
+       if (DEBUG) System.out.println(position + "\t\tfstore_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals == 0) {
+               maxLocals = 1;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fstore_0;
+}
+final public void fstore_1() {
+       if (DEBUG) System.out.println(position + "\t\tfstore_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 1) {
+               maxLocals = 2;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fstore_1;
+}
+final public void fstore_2() {
+       if (DEBUG) System.out.println(position + "\t\tfstore_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 2) {
+               maxLocals = 3;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fstore_2;
+}
+final public void fstore_3() {
+       if (DEBUG) System.out.println(position + "\t\tfstore_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 3) {
+               maxLocals = 4;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fstore_3;
+}
+final public void fsub() {
+       if (DEBUG) System.out.println(position + "\t\tfsub"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_fsub;
+}
+/**
+ * Macro for building a class descriptor object
+ */
+public void generateClassLiteralAccessForType(TypeBinding accessedType, FieldBinding syntheticFieldBinding) {
+       Label endLabel;
+       ExceptionLabel anyExceptionHandler;
+       int saveStackSize;
+       if (accessedType.isBaseType() && accessedType != NullBinding) {
+               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('/', '.'));
+       } 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();
+       endLabel.place();
+       stackDepth = saveStackSize;
+}
+/**
+ * This method generates the code attribute bytecode
+ */
+final public void generateCodeAttributeForProblemMethod(String problemMessage) {
+       newJavaLangError();
+       dup();
+       ldc(problemMessage);
+       invokeJavaLangErrorConstructor();
+       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());
+       }
+}
+/**
+ * @param implicitConversionCode int
+ */
+public void generateImplicitConversion(int implicitConversionCode) {
+       switch (implicitConversionCode) {
+               case Float2Char :
+                       this.f2i();
+                       this.i2c();
+                       break;
+               case Double2Char :
+                       this.d2i();
+                       this.i2c();
+                       break;
+               case Int2Char :
+               case Short2Char :
+               case Byte2Char :
+                       this.i2c();
+                       break;
+               case Long2Char :
+                       this.l2i();
+                       this.i2c();
+                       break;
+               case Char2Float :
+               case Short2Float :
+               case Int2Float :
+               case Byte2Float :
+                       this.i2f();
+                       break;
+               case Double2Float :
+                       this.d2f();
+                       break;
+               case Long2Float :
+                       this.l2f();
+                       break;
+               case Float2Byte :
+                       this.f2i();
+                       this.i2b();
+                       break;
+               case Double2Byte :
+                       this.d2i();
+                       this.i2b();
+                       break;
+               case Int2Byte :
+               case Short2Byte :
+               case Char2Byte :
+                       this.i2b();
+                       break;
+               case Long2Byte :
+                       this.l2i();
+                       this.i2b();
+                       break;
+               case Byte2Double :
+               case Char2Double :
+               case Short2Double :
+               case Int2Double :
+                       this.i2d();
+                       break;
+               case Float2Double :
+                       this.f2d();
+                       break;
+               case Long2Double :
+                       this.l2d();
+                       break;
+               case Byte2Short :
+               case Char2Short :
+               case Int2Short :
+                       this.i2s();
+                       break;
+               case Double2Short :
+                       this.d2i();
+                       this.i2s();
+                       break;
+               case Long2Short :
+                       this.l2i();
+                       this.i2s();
+                       break;
+               case Float2Short :
+                       this.f2i();
+                       this.i2s();
+                       break;
+               case Double2Int :
+                       this.d2i();
+                       break;
+               case Float2Int :
+                       this.f2i();
+                       break;
+               case Long2Int :
+                       this.l2i();
+                       break;
+               case Int2Long :
+               case Char2Long :
+               case Byte2Long :
+               case Short2Long :
+                       this.i2l();
+                       break;
+               case Double2Long :
+                       this.d2l();
+                       break;
+               case Float2Long :
+                       this.f2l();
+       }
+}
+public void generateInlinedValue(byte inlinedValue) {
+       switch (inlinedValue) {
+               case -1 :
+                       this.iconst_m1();
+                       break;
+               case 0 :
+                       this.iconst_0();
+                       break;
+               case 1 :
+                       this.iconst_1();
+                       break;
+               case 2 :
+                       this.iconst_2();
+                       break;
+               case 3 :
+                       this.iconst_3();
+                       break;
+               case 4 :
+                       this.iconst_4();
+                       break;
+               case 5 :
+                       this.iconst_5();
+                       break;
+               default :
+                       if ((-128 <= inlinedValue) && (inlinedValue <= 127)) {
+                               this.bipush(inlinedValue);
+                               return;
+                       }
+       }
+}
+public void generateInlinedValue(char inlinedValue) {
+       switch (inlinedValue) {
+               case 0 :
+                       this.iconst_0();
+                       break;
+               case 1 :
+                       this.iconst_1();
+                       break;
+               case 2 :
+                       this.iconst_2();
+                       break;
+               case 3 :
+                       this.iconst_3();
+                       break;
+               case 4 :
+                       this.iconst_4();
+                       break;
+               case 5 :
+                       this.iconst_5();
+                       break;
+               default :
+                       if ((6 <= inlinedValue) && (inlinedValue <= 127)) {
+                               this.bipush((byte) inlinedValue);
+                               return;
+                       }
+                       if ((128 <= inlinedValue) && (inlinedValue <= 32767)) {
+                               this.sipush(inlinedValue);
+                               return;
+                       }
+                       this.ldc(inlinedValue);
+       }
+}
+public void generateInlinedValue(double inlinedValue) {
+       if (inlinedValue == 0.0) {
+               if (Double.doubleToLongBits(inlinedValue) != 0L)
+                       this.ldc2_w(inlinedValue);
+               else
+                       this.dconst_0();
+               return;
+       }
+       if (inlinedValue == 1.0) {
+               this.dconst_1();
+               return;
+       }
+       this.ldc2_w(inlinedValue);
+}
+public void generateInlinedValue(float inlinedValue) {
+       if (inlinedValue == 0.0f) {
+               if (Float.floatToIntBits(inlinedValue) != 0)
+                       this.ldc(inlinedValue);
+               else
+                       this.fconst_0();
+               return;
+       }
+       if (inlinedValue == 1.0f) {
+               this.fconst_1();
+               return;
+       }
+       if (inlinedValue == 2.0f) {
+               this.fconst_2();
+               return;
+       }
+       this.ldc(inlinedValue);
+}
+public void generateInlinedValue(int inlinedValue) {
+       switch (inlinedValue) {
+               case -1 :
+                       this.iconst_m1();
+                       break;
+               case 0 :
+                       this.iconst_0();
+                       break;
+               case 1 :
+                       this.iconst_1();
+                       break;
+               case 2 :
+                       this.iconst_2();
+                       break;
+               case 3 :
+                       this.iconst_3();
+                       break;
+               case 4 :
+                       this.iconst_4();
+                       break;
+               case 5 :
+                       this.iconst_5();
+                       break;
+               default :
+                       if ((-128 <= inlinedValue) && (inlinedValue <= 127)) {
+                               this.bipush((byte) inlinedValue);
+                               return;
+                       }
+                       if ((-32768 <= inlinedValue) && (inlinedValue <= 32767)) {
+                               this.sipush(inlinedValue);
+                               return;
+                       }
+                       this.ldc(inlinedValue);
+       }
+}
+public void generateInlinedValue(long inlinedValue) {
+       if (inlinedValue == 0) {
+               this.lconst_0();
+               return;
+       }
+       if (inlinedValue == 1) {
+               this.lconst_1();
+               return;
+       }
+       this.ldc2_w(inlinedValue);
+}
+public void generateInlinedValue(short inlinedValue) {
+       switch (inlinedValue) {
+               case -1 :
+                       this.iconst_m1();
+                       break;
+               case 0 :
+                       this.iconst_0();
+                       break;
+               case 1 :
+                       this.iconst_1();
+                       break;
+               case 2 :
+                       this.iconst_2();
+                       break;
+               case 3 :
+                       this.iconst_3();
+                       break;
+               case 4 :
+                       this.iconst_4();
+                       break;
+               case 5 :
+                       this.iconst_5();
+                       break;
+               default :
+                       if ((-128 <= inlinedValue) && (inlinedValue <= 127)) {
+                               this.bipush((byte) inlinedValue);
+                               return;
+                       }
+                       this.sipush(inlinedValue);
+       }
+}
+public void generateInlinedValue(boolean inlinedValue) {
+       if (inlinedValue)
+               this.iconst_1();
+       else
+               this.iconst_0();
+}
+public void generateOuterAccess(Object[] mappingSequence, ASTNode invocationSite, Binding target, Scope scope) {
+       if (mappingSequence == null) {
+               if (target instanceof LocalVariableBinding) {
+                       scope.problemReporter().needImplementation(); //TODO (philippe) should improve local emulation failure reporting
+               } else {
+                       scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, false);
+               }
+               return;
+       }
+       if (mappingSequence == BlockScope.NoEnclosingInstanceInConstructorCall) {
+               scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, true);
+               return;
+       } else if (mappingSequence == BlockScope.NoEnclosingInstanceInStaticContext) {
+               scope.problemReporter().noSuchEnclosingInstance((ReferenceBinding)target, invocationSite, false);
+               return;
+       }
+       
+       if (mappingSequence == BlockScope.EmulationPathToImplicitThis) {
+               this.aload_0();
+               return;
+       } else if (mappingSequence[0] instanceof FieldBinding) {
+               FieldBinding fieldBinding = (FieldBinding) mappingSequence[0];
+               this.aload_0();
+               this.getfield(fieldBinding);
+       } else {
+               load((LocalVariableBinding) mappingSequence[0]);
+       }
+       for (int i = 1, length = mappingSequence.length; i < length; i++) {
+               if (mappingSequence[i] instanceof FieldBinding) {
+                       FieldBinding fieldBinding = (FieldBinding) mappingSequence[i];
+                       this.getfield(fieldBinding);
+               } else {
+                       this.invokestatic((MethodBinding) mappingSequence[i]);
+               }
+       }
+}
+
+/**
+ * The equivalent code performs a string conversion:
+ *
+ * @param blockScope the given blockScope
+ * @param oper1 the first expression
+ * @param oper2 the second expression
+ */
+public void generateStringAppend(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.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();
+       } else {
+               pc = position;
+               oper1.generateOptimizedStringBufferCreation(blockScope, this, oper1.implicitConversion & 0xF);
+               this.recordPositionsFrom(pc, oper1.sourceStart);
+       }
+       pc = position;
+       oper2.generateOptimizedStringBuffer(blockScope, this, oper2.implicitConversion & 0xF);
+       this.recordPositionsFrom(pc, oper2.sourceStart);
+       this.invokeStringBufferToString();
+}
+/**
+ * Code responsible to generate the suitable code to supply values for the synthetic enclosing
+ * instance arguments of a constructor invocation of a nested type.
+ */
+public void generateSyntheticEnclosingInstanceValues(
+               BlockScope currentScope, 
+               ReferenceBinding targetType, 
+               Expression enclosingInstance, 
+               ASTNode invocationSite) {
+
+       // supplying enclosing instance for the anonymous type's superclass
+       ReferenceBinding checkedTargetType = targetType.isAnonymousType() ? targetType.superclass() : targetType;
+       boolean hasExtraEnclosingInstance = enclosingInstance != null;
+       if (hasExtraEnclosingInstance 
+                       && (!checkedTargetType.isNestedType() || checkedTargetType.isStatic())) {
+               currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType);
+               return;
+       }
+
+       // perform some emulation work in case there is some and we are inside a local type only
+       ReferenceBinding[] syntheticArgumentTypes;
+       if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) {
+
+               ReferenceBinding targetEnclosingType = checkedTargetType.enclosingType();
+               boolean complyTo14 = currentScope.environment().options.complianceLevel >= ClassFileConstants.JDK1_4;
+               // deny access to enclosing instance argument for allocation and super constructor call (if 1.4)
+               boolean ignoreEnclosingArgInConstructorCall = invocationSite instanceof AllocationExpression
+                                       || (complyTo14 && ((invocationSite instanceof ExplicitConstructorCall && ((ExplicitConstructorCall)invocationSite).isSuperAccess())));
+                                               
+               for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) {
+                       ReferenceBinding syntheticArgType = syntheticArgumentTypes[i];
+                       if (hasExtraEnclosingInstance && syntheticArgType == targetEnclosingType) {
+                               hasExtraEnclosingInstance = false;
+                               enclosingInstance.generateCode(currentScope, this, true);
+                               if (complyTo14){
+                                       dup();
+                                       invokeObjectGetClass(); // will perform null check
+                                       pop();
+                               }
+                       } else {
+                               Object[] emulationPath = currentScope.getEmulationPath(
+                                               syntheticArgType, 
+                                               false /*not only exact match (that is, allow compatible)*/,
+                                               ignoreEnclosingArgInConstructorCall);
+                               this.generateOuterAccess(emulationPath, invocationSite, syntheticArgType, currentScope);
+                       }
+               }
+               if (hasExtraEnclosingInstance){
+                       currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, checkedTargetType);
+               }
+       }
+}
+
+/**
+ * Code responsible to generate the suitable code to supply values for the synthetic outer local
+ * variable arguments of a constructor invocation of a nested type.
+ * (bug 26122) - synthetic values for outer locals must be passed after user arguments, e.g. new X(i = 1){}
+ */
+public void generateSyntheticOuterArgumentValues(BlockScope currentScope, ReferenceBinding targetType, ASTNode invocationSite) {
+
+       // generate the synthetic outer arguments then
+       SyntheticArgumentBinding syntheticArguments[];
+       if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) {
+               for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+                       LocalVariableBinding targetVariable = syntheticArguments[i].actualOuterLocalVariable;
+                       VariableBinding[] emulationPath = currentScope.getEmulationPath(targetVariable);
+                       this.generateOuterAccess(emulationPath, invocationSite, targetVariable, currentScope);
+               }
+       }
+}
+
+/**
+ * @param accessBinding the access method binding to generate
+ */
+public void generateSyntheticBodyForConstructorAccess(SyntheticAccessMethodBinding accessBinding) {
+
+       initializeMaxLocals(accessBinding);
+
+       MethodBinding constructorBinding = accessBinding.targetMethod;
+       TypeBinding[] parameters = constructorBinding.parameters;
+       int length = parameters.length;
+       int resolvedPosition = 1;
+       this.aload_0();
+       if (constructorBinding.declaringClass.isNestedType()) {
+               NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+               SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticEnclosingInstances();
+               for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
+                       TypeBinding type;
+                       load((type = syntheticArguments[i].type), resolvedPosition);
+                       if ((type == DoubleBinding) || (type == LongBinding))
+                               resolvedPosition += 2;
+                       else
+                               resolvedPosition++;
+               }
+       }
+       for (int i = 0; i < length; i++) {
+               load(parameters[i], resolvedPosition);
+               if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding))
+                       resolvedPosition += 2;
+               else
+                       resolvedPosition++;
+       }
+       
+       if (constructorBinding.declaringClass.isNestedType()) {
+               NestedTypeBinding nestedType = (NestedTypeBinding) constructorBinding.declaringClass;
+               SyntheticArgumentBinding[] syntheticArguments = nestedType.syntheticOuterLocalVariables();
+               for (int i = 0; i < (syntheticArguments == null ? 0 : syntheticArguments.length); i++) {
+                       TypeBinding type;
+                       load((type = syntheticArguments[i].type), resolvedPosition);
+                       if ((type == DoubleBinding) || (type == LongBinding))
+                               resolvedPosition += 2;
+                       else
+                               resolvedPosition++;
+               }
+       }
+       this.invokespecial(constructorBinding);
+       this.return_();
+}
+public void generateSyntheticBodyForFieldReadAccess(SyntheticAccessMethodBinding accessBinding) {
+       initializeMaxLocals(accessBinding);
+       FieldBinding fieldBinding = accessBinding.targetReadField;
+       TypeBinding type;
+       if (fieldBinding.isStatic())
+               this.getstatic(fieldBinding);
+       else {
+               this.aload_0();
+               this.getfield(fieldBinding);
+       }
+       if ((type = fieldBinding.type).isBaseType()) {
+               if (type == IntBinding)
+                       this.ireturn();
+               else
+                       if (type == FloatBinding)
+                               this.freturn();
+                       else
+                               if (type == LongBinding)
+                                       this.lreturn();
+                               else
+                                       if (type == DoubleBinding)
+                                               this.dreturn();
+                                       else
+                                               this.ireturn();
+       } else
+               this.areturn();
+}
+public void generateSyntheticBodyForFieldWriteAccess(SyntheticAccessMethodBinding accessBinding) {
+       initializeMaxLocals(accessBinding);
+       FieldBinding fieldBinding = accessBinding.targetWriteField;
+       if (fieldBinding.isStatic()) {
+               load(fieldBinding.type, 0);
+               this.putstatic(fieldBinding);
+       } else {
+               this.aload_0();
+               load(fieldBinding.type, 1);
+               this.putfield(fieldBinding);
+       }
+       this.return_();
+}
+public void generateSyntheticBodyForMethodAccess(SyntheticAccessMethodBinding accessBinding) {
+
+       initializeMaxLocals(accessBinding);
+       MethodBinding methodBinding = accessBinding.targetMethod;
+       TypeBinding[] parameters = methodBinding.parameters;
+       int length = parameters.length;
+       int resolvedPosition;
+       if (methodBinding.isStatic())
+               resolvedPosition = 0;
+       else {
+               this.aload_0();
+               resolvedPosition = 1;
+       }
+       for (int i = 0; i < length; i++) {
+               load(parameters[i], resolvedPosition);
+               if ((parameters[i] == DoubleBinding) || (parameters[i] == LongBinding))
+                       resolvedPosition += 2;
+               else
+                       resolvedPosition++;
+       }
+       TypeBinding type;
+       if (methodBinding.isStatic())
+               this.invokestatic(methodBinding);
+       else {
+               if (methodBinding.isConstructor()
+                       || methodBinding.isPrivate()
+                       // qualified super "X.super.foo()" targets methods from superclass
+                       || accessBinding.accessType == SyntheticAccessMethodBinding.SuperMethodAccess){
+                       this.invokespecial(methodBinding);
+               } else {
+                       if (methodBinding.declaringClass.isInterface()){
+                               this.invokeinterface(methodBinding);
+                       } else {
+                               this.invokevirtual(methodBinding);
+                       }
+               }
+       }
+       if ((type = methodBinding.returnType).isBaseType())
+               if (type == VoidBinding)
+                       this.return_();
+               else
+                       if (type == IntBinding)
+                               this.ireturn();
+                       else
+                               if (type == FloatBinding)
+                                       this.freturn();
+                               else
+                                       if (type == LongBinding)
+                                               this.lreturn();
+                                       else
+                                               if (type == DoubleBinding)
+                                                       this.dreturn();
+                                               else
+                                                       this.ireturn();
+       else
+               this.areturn();
+}
+final public byte[] getContents() {
+       byte[] contents;
+       System.arraycopy(bCodeStream, 0, contents = new byte[position], 0, position);
+       return contents;
+}
+final public void getfield(FieldBinding fieldBinding) {
+       if (DEBUG) System.out.println(position + "\t\tgetfield:"+fieldBinding); //$NON-NLS-1$
+       countLabels = 0;
+       if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+               if (++stackDepth > stackMax)
+                       stackMax = stackDepth;
+       }
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_getfield;
+       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+}
+final public void getstatic(FieldBinding fieldBinding) {
+       if (DEBUG) System.out.println(position + "\t\tgetstatic:"+fieldBinding); //$NON-NLS-1$
+       countLabels = 0;
+       if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long))
+               stackDepth += 2;
+       else
+               stackDepth += 1;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_getstatic;
+       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+}
+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());
+                       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());
+                       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());
+                       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());
+                       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());
+                       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());
+                       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());
+                       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());
+                       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());
+                       break;
+       }
+}
+/**
+ * We didn't call it goto, because there is a conflit with the goto keyword
+ */
+final public void goto_(Label label) {
+       if (this.wideMode) {
+               this.goto_w(label);
+               return;
+       }
+       if (DEBUG) System.out.println(position + "\t\tgoto:"+label); //$NON-NLS-1$
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       label.inlineForwardReferencesFromLabelsTargeting(position);
+       /*
+        Possible optimization for code such as:
+        public Object foo() {
+               boolean b = true;
+               if (b) {
+                       if (b)
+                               return null;
+               } else {
+                       if (b) {
+                               return null;
+                       }
+               }
+               return null;
+       }
+       The goto around the else block for the first if will
+       be unreachable, because the thenClause of the second if
+       returns.
+       See inlineForwardReferencesFromLabelsTargeting defined
+       on the Label class for the remaining part of this
+       optimization.
+        if (!lbl.isBranchTarget(position)) {
+               switch(bCodeStream[classFileOffset-1]) {
+                       case OPC_return :
+                       case OPC_areturn:
+                               return;
+               }
+       }*/
+       position++;
+       bCodeStream[classFileOffset++] = OPC_goto;
+       label.branch();
+}
+
+final public void goto_w(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tgotow:"+lbl); //$NON-NLS-1$
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_goto_w;
+       lbl.branchWide();
+}
+final public void i2b() {
+       if (DEBUG) System.out.println(position + "\t\ti2b"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_i2b;
+}
+final public void i2c() {
+       if (DEBUG) System.out.println(position + "\t\ti2c"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_i2c;
+}
+final public void i2d() {
+       if (DEBUG) System.out.println(position + "\t\ti2d"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_i2d;
+}
+final public void i2f() {
+       if (DEBUG) System.out.println(position + "\t\ti2f"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_i2f;
+}
+final public void i2l() {
+       if (DEBUG) System.out.println(position + "\t\ti2l"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_i2l;
+}
+final public void i2s() {
+       if (DEBUG) System.out.println(position + "\t\ti2s"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_i2s;
+}
+final public void iadd() {
+       if (DEBUG) System.out.println(position + "\t\tiadd"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iadd;
+}
+final public void iaload() {
+       if (DEBUG) System.out.println(position + "\t\tiaload"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iaload;
+}
+final public void iand() {
+       if (DEBUG) System.out.println(position + "\t\tiand"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iand;
+}
+final public void iastore() {
+       if (DEBUG) System.out.println(position + "\t\tiastore"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iastore;
+}
+final public void iconst_0() {
+       if (DEBUG) System.out.println(position + "\t\ticonst_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iconst_0;
+}
+final public void iconst_1() {
+       if (DEBUG) System.out.println(position + "\t\ticonst_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iconst_1;
+}
+final public void iconst_2() {
+       if (DEBUG) System.out.println(position + "\t\ticonst_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iconst_2;
+}
+final public void iconst_3() {
+       if (DEBUG) System.out.println(position + "\t\ticonst_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iconst_3;
+}
+final public void iconst_4() {
+       if (DEBUG) System.out.println(position + "\t\ticonst_4"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iconst_4;
+}
+final public void iconst_5() {
+       if (DEBUG) System.out.println(position + "\t\ticonst_5"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iconst_5;
+}
+final public void iconst_m1() {
+       if (DEBUG) System.out.println(position + "\t\ticonst_m1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iconst_m1;
+}
+final public void idiv() {
+       if (DEBUG) System.out.println(position + "\t\tidiv"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_idiv;
+}
+final public void if_acmpeq(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_acmpeq:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth-=2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_acmpne, lbl);
+       } else {        
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_acmpeq;
+               lbl.branch();
+       }
+}
+final public void if_acmpne(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_acmpne:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth-=2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_acmpeq, lbl);
+       } else {        
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_acmpne;
+               lbl.branch();
+       }
+}
+final public void if_icmpeq(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_cmpeq:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_icmpne, lbl);
+       } else {        
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_icmpeq;
+               lbl.branch();
+       }
+}
+final public void if_icmpge(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_iacmpge:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_icmplt, lbl);
+       } else {        
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_icmpge;
+               lbl.branch();
+       }
+}
+final public void if_icmpgt(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_iacmpgt:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_icmple, lbl);
+       } else {        
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_icmpgt;
+               lbl.branch();
+       }
+}
+final public void if_icmple(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_iacmple:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_icmpgt, lbl);
+       } else {        
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_icmple;
+               lbl.branch();
+       }
+}
+final public void if_icmplt(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_iacmplt:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_icmpge, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_icmplt;
+               lbl.branch();
+       }
+}
+final public void if_icmpne(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tif_iacmpne:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_if_icmpeq, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_if_icmpne;
+               lbl.branch();
+       }
+}
+final public void ifeq(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tifeq:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_ifne, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ifeq;
+               lbl.branch();
+       }
+}
+final public void ifge(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tifge:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_iflt, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ifge;
+               lbl.branch();
+       }
+}
+final public void ifgt(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tifgt:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_ifle, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ifgt;
+               lbl.branch();
+       }
+}
+final public void ifle(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tifle:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_ifgt, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ifle;
+               lbl.branch();
+       }
+}
+final public void iflt(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tiflt:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_ifge, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_iflt;
+               lbl.branch();
+       }
+}
+final public void ifne(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tifne:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_ifeq, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ifne;
+               lbl.branch();
+       }
+}
+final public void ifnonnull(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tifnonnull:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_ifnull, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ifnonnull;
+               lbl.branch();
+       }
+}
+final public void ifnull(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tifnull:"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (this.wideMode) {
+               generateWideRevertedConditionalBranch(OPC_ifnonnull, lbl);
+       } else {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ifnull;
+               lbl.branch();
+       }
+}
+final public void iinc(int index, int value) {
+       if (DEBUG) System.out.println(position + "\t\tiinc:"+index+","+value); //$NON-NLS-1$ //$NON-NLS-2$
+       countLabels = 0;
+       if ((index > 255) || (value < -128 || value > 127)) { // have to widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_iinc;
+               writeUnsignedShort(index);
+               writeSignedShort(value);
+       } else {
+               if (classFileOffset + 2 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 3;
+               bCodeStream[classFileOffset++] = OPC_iinc;
+               bCodeStream[classFileOffset++] = (byte) index;
+               bCodeStream[classFileOffset++] = (byte) value;
+       }
+}
+final public void iload(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tiload:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= iArg) {
+               maxLocals = iArg + 1;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_iload;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_iload;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void iload_0() {
+       if (DEBUG) System.out.println(position + "\t\tiload_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= 0) {
+               maxLocals = 1;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iload_0;
+}
+final public void iload_1() {
+       if (DEBUG) System.out.println(position + "\t\tiload_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= 1) {
+               maxLocals = 2;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iload_1;
+}
+final public void iload_2() {
+       if (DEBUG) System.out.println(position + "\t\tiload_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= 2) {
+               maxLocals = 3;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iload_2;
+}
+final public void iload_3() {
+       if (DEBUG) System.out.println(position + "\t\tiload_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (maxLocals <= 3) {
+               maxLocals = 4;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iload_3;
+}
+final public void imul() {
+       if (DEBUG) System.out.println(position + "\t\timul"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_imul;
+}
+public void incrementTemp(LocalVariableBinding localBinding, int value) {
+       if (value == (short) value) {
+               this.iinc(localBinding.resolvedPosition, value);
+               return;
+       }
+       load(localBinding);
+       this.ldc(value);
+       this.iadd();
+       store(localBinding, false);
+}
+public void incrStackSize(int offset) {
+       if ((stackDepth += offset) > stackMax)
+               stackMax = stackDepth;
+}
+public int indexOfSameLineEntrySincePC(int pc, int line) {
+       for (int index = pc, max = pcToSourceMapSize; index < max; index+=2) {
+               if (pcToSourceMap[index+1] == line)
+                       return index;
+       }
+       return -1;
+}
+final public void ineg() {
+       if (DEBUG) System.out.println(position + "\t\tineg"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ineg;
+}
+public void init(ClassFile targetClassFile) {
+       this.classFile = targetClassFile;
+       this.constantPool = targetClassFile.constantPool;
+       this.bCodeStream = targetClassFile.contents;
+       this.classFileOffset = targetClassFile.contentsOffset;
+       this.startingClassFileOffset = this.classFileOffset;
+       pcToSourceMapSize = 0;
+       lastEntryPC = 0;
+       int length = visibleLocals.length;
+       if (noVisibleLocals.length < length) {
+               noVisibleLocals = new LocalVariableBinding[length];
+       }
+       System.arraycopy(noVisibleLocals, 0, visibleLocals, 0, length);
+       visibleLocalsCount = 0;
+       
+       length = locals.length;
+       if (noLocals.length < length) {
+               noLocals = new LocalVariableBinding[length];
+       }
+       System.arraycopy(noLocals, 0, locals, 0, length);
+       allLocalsCounter = 0;
+
+       length = exceptionHandlers.length;
+       if (noExceptionHandlers.length < length) {
+               noExceptionHandlers = new ExceptionLabel[length];
+       }
+       System.arraycopy(noExceptionHandlers, 0, exceptionHandlers, 0, length);
+       exceptionHandlersNumber = 0;
+       
+       length = labels.length;
+       if (noLabels.length < length) {
+               noLabels = new Label[length];
+       }
+       System.arraycopy(noLabels, 0, labels, 0, length);
+       countLabels = 0;
+
+       stackMax = 0;
+       stackDepth = 0;
+       maxLocals = 0;
+       position = 0;
+}
+/**
+ * @param methodBinding the given method binding to initialize the max locals
+ */
+public void initializeMaxLocals(MethodBinding methodBinding) {
+
+       maxLocals = (methodBinding == null || methodBinding.isStatic()) ? 0 : 1;
+       // 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++;
+                                       }
+                               }
+                       }
+               }
+               TypeBinding[] arguments;
+               if ((arguments = methodBinding.parameters) != null) {
+                       for (int i = 0, max = arguments.length; i < max; i++) {
+                               TypeBinding argType;
+                               if (((argType = arguments[i]) == LongBinding) || (argType == DoubleBinding)) {
+                                       maxLocals += 2;
+                               } else {
+                                       maxLocals++;
+                               }
+                       }
+               }
+       }
+}
+/**
+ * This methods searches for an existing entry inside the pcToSourceMap table with a pc equals to @pc.
+ * If there is an existing entry it returns -1 (no insertion required).
+ * Otherwise it returns the index where the entry for the pc has to be inserted.
+ * This is based on the fact that the pcToSourceMap table is sorted according to the pc.
+ *
+ * @param pcToSourceMap the given pcToSourceMap array
+ * @param length the given length
+ * @param pc the given pc
+ * @return int
+ */
+public static int insertionIndex(int[] pcToSourceMap, int length, int pc) {
+       int g = 0;
+       int d = length - 2;
+       int m = 0;
+       while (g <= d) {
+               m = (g + d) / 2;
+               // we search only on even indexes
+               if ((m % 2) != 0)
+                       m--;
+               int currentPC = pcToSourceMap[m];
+               if (pc < currentPC) {
+                       d = m - 2;
+               } else
+                       if (pc > currentPC) {
+                               g = m + 2;
+                       } else {
+                               return -1;
+                       }
+       }
+       if (pc < pcToSourceMap[m])
+               return m;
+       return m + 2;
+}
+/**
+ * We didn't call it instanceof because there is a conflit with the
+ * instanceof keyword
+ */
+final public void instance_of(TypeBinding typeBinding) {
+       if (DEBUG) System.out.println(position + "\t\tinstance_of:"+typeBinding); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_instanceof;
+       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+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());
+}
+
+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());
+}
+
+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());
+}
+
+final public void invokeinterface(MethodBinding methodBinding) {
+       // initialized to 1 to take into account this  immediately
+       if (DEBUG) System.out.println(position + "\t\tinvokeinterface: " + methodBinding); //$NON-NLS-1$
+       countLabels = 0;
+       int argCount = 1;
+       int id;
+       if (classFileOffset + 4 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position += 3;
+       bCodeStream[classFileOffset++] = OPC_invokeinterface;
+       writeUnsignedShort(constantPool.literalIndex(methodBinding));
+       for (int i = methodBinding.parameters.length - 1; i >= 0; i--)
+               if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long))
+                       argCount += 2;
+               else
+                       argCount += 1;
+       bCodeStream[classFileOffset++] = (byte) argCount;
+       // Generate a  0 into the byte array. Like the array is already fill with 0, we just need to increment
+       // the number of bytes.
+       bCodeStream[classFileOffset++] = 0;
+       if (((id = methodBinding.returnType.id) == T_double) || (id == T_long)) {
+               stackDepth += (2 - argCount);
+       } else {
+               if (id == T_void) {
+                       stackDepth -= argCount;
+               } else {
+                       stackDepth += (1 - argCount);
+               }
+       }
+       if (stackDepth > stackMax) {
+               stackMax = stackDepth;
+       }
+}
+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());
+}
+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());
+}
+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());
+}
+
+final public void invokespecial(MethodBinding methodBinding) {
+       if (DEBUG) System.out.println(position + "\t\tinvokespecial:"+methodBinding); //$NON-NLS-1$
+       // initialized to 1 to take into account this  immediately
+       countLabels = 0;
+       int argCount = 1;
+       int id;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_invokespecial;
+       writeUnsignedShort(constantPool.literalIndex(methodBinding));
+       if (methodBinding.isConstructor() && methodBinding.declaringClass.isNestedType()) {
+               // enclosing instances
+               TypeBinding[] syntheticArgumentTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes();
+               if (syntheticArgumentTypes != null) {
+                       for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) {
+                               if (((id = syntheticArgumentTypes[i].id) == T_double) || (id == T_long)) {
+                                       argCount += 2;
+                               } else {
+                                       argCount++;
+                               }
+                       }
+               }
+               // outer local variables
+               SyntheticArgumentBinding[] syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables();
+               if (syntheticArguments != null) {
+                       for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+                               if (((id = syntheticArguments[i].type.id) == T_double) || (id == T_long)) {
+                                       argCount += 2;
+                               } else {
+                                       argCount++;
+                               }
+                       }
+               }
+       }
+       for (int i = methodBinding.parameters.length - 1; i >= 0; i--)
+               if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long))
+                       argCount += 2;
+               else
+                       argCount++;
+       if (((id = methodBinding.returnType.id) == T_double) || (id == T_long))
+               stackDepth += (2 - argCount);
+       else
+               if (id == T_void)
+                       stackDepth -= argCount;
+               else
+                       stackDepth += (1 - argCount);
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+}
+final public void invokestatic(MethodBinding methodBinding) {
+       if (DEBUG) System.out.println(position + "\t\tinvokestatic:"+methodBinding); //$NON-NLS-1$
+       // initialized to 0 to take into account that there is no this for
+       // a static method
+       countLabels = 0;
+       int argCount = 0;
+       int id;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_invokestatic;
+       writeUnsignedShort(constantPool.literalIndex(methodBinding));
+       for (int i = methodBinding.parameters.length - 1; i >= 0; i--)
+               if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long))
+                       argCount += 2;
+               else
+                       argCount += 1;
+       if (((id = methodBinding.returnType.id) == T_double) || (id == T_long))
+               stackDepth += (2 - argCount);
+       else
+               if (id == T_void)
+                       stackDepth -= argCount;
+               else
+                       stackDepth += (1 - argCount);
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+}
+/**
+ * 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();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_invokevirtual;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferAppend(typeID));
+       if ((usedTypeID == T_long) || (usedTypeID == T_double))
+               stackDepth -= 2;
+       else
+               stackDepth--;
+}
+
+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();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_invokespecial;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorConstructor(typeBindingID));
+       stackDepth -= 2;
+}
+
+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 --;
+}
+
+public void invokeStringBufferDefaultConstructor() {
+       // invokespecial: java.lang.StringBuffer.<init>()V
+       if (DEBUG) System.out.println(position + "\t\tinvokespecial: java.lang.StringBuffer.<init>()V"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       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();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_invokespecial;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferConstructor());
+       stackDepth -= 2;
+}
+
+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();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_invokevirtual;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferToString());
+}
+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());
+}
+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));
+}
+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();
+       }
+       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$
+       // initialized to 1 to take into account this  immediately
+       countLabels = 0;
+       int argCount = 1;
+       int id;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_invokevirtual;
+       writeUnsignedShort(constantPool.literalIndex(methodBinding));
+       for (int i = methodBinding.parameters.length - 1; i >= 0; i--)
+               if (((id = methodBinding.parameters[i].id) == T_double) || (id == T_long))
+                       argCount += 2;
+               else
+                       argCount++;
+       if (((id = methodBinding.returnType.id) == T_double) || (id == T_long))
+               stackDepth += (2 - argCount);
+       else
+               if (id == T_void)
+                       stackDepth -= argCount;
+               else
+                       stackDepth += (1 - argCount);
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+}
+final public void ior() {
+       if (DEBUG) System.out.println(position + "\t\tior"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ior;
+}
+final public void irem() {
+       if (DEBUG) System.out.println(position + "\t\tirem"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_irem;
+}
+final public void ireturn() {
+       if (DEBUG) System.out.println(position + "\t\tireturn"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       // the stackDepth should be equal to 0 
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ireturn;
+}
+public boolean isDefinitelyAssigned(Scope scope, int initStateIndex, LocalVariableBinding local) {
+       // Dependant of UnconditionalFlowInfo.isDefinitelyAssigned(..)
+       if (initStateIndex == -1)
+               return false;
+       if (local.isArgument) {
+               return true;
+       }
+       int localPosition = local.id + maxFieldCount;
+       MethodScope methodScope = scope.methodScope();
+       // id is zero-based
+       if (localPosition < UnconditionalFlowInfo.BitCacheSize) {
+               return (methodScope.definiteInits[initStateIndex] & (1L << localPosition)) != 0; // use bits
+       }
+       // use extra vector
+       long[] extraInits = methodScope.extraDefiniteInits[initStateIndex];
+       if (extraInits == null)
+               return false; // if vector not yet allocated, then not initialized
+       int vectorIndex;
+       if ((vectorIndex = (localPosition / UnconditionalFlowInfo.BitCacheSize) - 1) >= extraInits.length)
+               return false; // if not enough room in vector, then not initialized 
+       return ((extraInits[vectorIndex]) & (1L << (localPosition % UnconditionalFlowInfo.BitCacheSize))) != 0;
+}
+final public void ishl() {
+       if (DEBUG) System.out.println(position + "\t\tishl"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ishl;
+}
+final public void ishr() {
+       if (DEBUG) System.out.println(position + "\t\tishr"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ishr;
+}
+final public void istore(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tistore:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= iArg) {
+               maxLocals = iArg + 1;
+       }
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_istore;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_istore;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void istore_0() {
+       if (DEBUG) System.out.println(position + "\t\tistore_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals == 0) {
+               maxLocals = 1;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_istore_0;
+}
+final public void istore_1() {
+       if (DEBUG) System.out.println(position + "\t\tistore_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 1) {
+               maxLocals = 2;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_istore_1;
+}
+final public void istore_2() {
+       if (DEBUG) System.out.println(position + "\t\tistore_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 2) {
+               maxLocals = 3;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_istore_2;
+}
+final public void istore_3() {
+       if (DEBUG) System.out.println(position + "\t\tistore_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (maxLocals <= 3) {
+               maxLocals = 4;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_istore_3;
+}
+final public void isub() {
+       if (DEBUG) System.out.println(position + "\t\tisub"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_isub;
+}
+final public void iushr() {
+       if (DEBUG) System.out.println(position + "\t\tiushr"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_iushr;
+}
+final public void ixor() {
+       if (DEBUG) System.out.println(position + "\t\tixor"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ixor;
+}
+final public void jsr(Label lbl) {
+       if (this.wideMode) {
+               this.jsr_w(lbl);
+               return;
+       }
+       if (DEBUG) System.out.println(position + "\t\tjsr"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_jsr;
+       lbl.branch();
+}
+final public void jsr_w(Label lbl) {
+       if (DEBUG) System.out.println(position + "\t\tjsr_w"+lbl); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_jsr_w;
+       lbl.branchWide();
+}
+final public void l2d() {
+       if (DEBUG) System.out.println(position + "\t\tl2d"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_l2d;
+}
+final public void l2f() {
+       if (DEBUG) System.out.println(position + "\t\tl2f"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_l2f;
+}
+final public void l2i() {
+       if (DEBUG) System.out.println(position + "\t\tl2i"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_l2i;
+}
+final public void ladd() {
+       if (DEBUG) System.out.println(position + "\t\tladd"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ladd;
+}
+final public void laload() {
+       if (DEBUG) System.out.println(position + "\t\tlaload"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_laload;
+}
+final public void land() {
+       if (DEBUG) System.out.println(position + "\t\tland"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_land;
+}
+final public void lastore() {
+       if (DEBUG) System.out.println(position + "\t\tlastore"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 4;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lastore;
+}
+final public void lcmp() {
+       if (DEBUG) System.out.println(position + "\t\tlcmp"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lcmp;
+}
+final public void lconst_0() {
+       if (DEBUG) System.out.println(position + "\t\tlconst_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lconst_0;
+}
+final public void lconst_1() {
+       if (DEBUG) System.out.println(position + "\t\tlconst_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       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) {
+               // Generate a ldc_w
+               if (classFileOffset + 2 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ldc_w;
+               writeUnsignedShort(index);
+       } else {
+               // Generate a ldc
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_ldc;
+               bCodeStream[classFileOffset++] = (byte) index;
+       }
+}
+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) {
+               // Generate a ldc_w
+               if (classFileOffset + 2 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = OPC_ldc_w;
+               writeUnsignedShort(index);
+       } else {
+               // Generate a ldc
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_ldc;
+               bCodeStream[classFileOffset++] = (byte) index;
+       }
+}
+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;
+       int currentCodeStreamPosition = position;
+       int index = constantPool.literalIndexForLdc(constant.toCharArray());
+       if (index > 0) {
+               // the string already exists inside the constant pool
+               // we reuse the same index
+               stackDepth++;
+               if (stackDepth > stackMax)
+                       stackMax = stackDepth;
+               if (index > 255) {
+                       // Generate a ldc_w
+                       if (classFileOffset + 2 >= bCodeStream.length) {
+                               resizeByteArray();
+                       }
+                       position++;
+                       bCodeStream[classFileOffset++] = OPC_ldc_w;
+                       writeUnsignedShort(index);
+               } else {
+                       // Generate a ldc
+                       if (classFileOffset + 1 >= bCodeStream.length) {
+                               resizeByteArray();
+                       }
+                       position += 2;
+                       bCodeStream[classFileOffset++] = OPC_ldc;
+                       bCodeStream[classFileOffset++] = (byte) index;
+               }
+       } else {
+               // the string is too big to be utf8-encoded in one pass.
+               // we have to split it into different pieces.
+               // first we clean all side-effects due to the code above
+               // this case is very rare, so we can afford to lose time to handle it
+               char[] constantChars = constant.toCharArray();
+               position = currentCodeStreamPosition;
+               constantPool.currentIndex = currentConstantPoolIndex;
+               constantPool.currentOffset = currentConstantPoolOffset;
+               constantPool.stringCache.remove(constantChars);
+               constantPool.UTF8Cache.remove(constantChars);
+               int i = 0;
+               int length = 0;
+               int constantLength = constant.length();
+               byte[] utf8encoding = new byte[Math.min(constantLength + 100, 65535)];
+               int utf8encodingLength = 0;
+               while ((length < 65532) && (i < constantLength)) {
+                       char current = constantChars[i];
+                       // we resize the byte array immediately if necessary
+                       if (length + 3 > (utf8encodingLength = utf8encoding.length)) {
+                               System.arraycopy(utf8encoding, 0, utf8encoding = new byte[Math.min(utf8encodingLength + 100, 65535)], 0, length);
+                       }
+                       if ((current >= 0x0001) && (current <= 0x007F)) {
+                               // we only need one byte: ASCII table
+                               utf8encoding[length++] = (byte) current;
+                       } else {
+                               if (current > 0x07FF) {
+                                       // we need 3 bytes
+                                       utf8encoding[length++] = (byte) (0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
+                                       utf8encoding[length++] = (byte) (0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
+                                       utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+                               } else {
+                                       // we can be 0 or between 0x0080 and 0x07FF
+                                       // In that case we only need 2 bytes
+                                       utf8encoding[length++] = (byte) (0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
+                                       utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+                               }
+                       }
+                       i++;
+               }
+               // check if all the string is encoded (PR 1PR2DWJ)
+               // the string is too big to be encoded in one pass
+               newStringBuffer();
+               dup();
+               // write the first part
+               char[] subChars = new char[i];
+               System.arraycopy(constantChars, 0, subChars, 0, i);
+               System.arraycopy(utf8encoding, 0, utf8encoding = new byte[length], 0, length);
+               index = constantPool.literalIndex(subChars, utf8encoding);
+               stackDepth++;
+               if (stackDepth > stackMax)
+                       stackMax = stackDepth;
+               if (index > 255) {
+                       // Generate a ldc_w
+                       if (classFileOffset + 2 >= bCodeStream.length) {
+                               resizeByteArray();
+                       }
+                       position++;
+                       bCodeStream[classFileOffset++] = OPC_ldc_w;
+                       writeUnsignedShort(index);
+               } else {
+                       // Generate a ldc
+                       if (classFileOffset + 1 >= bCodeStream.length) {
+                               resizeByteArray();
+                       }
+                       position += 2;
+                       bCodeStream[classFileOffset++] = OPC_ldc;
+                       bCodeStream[classFileOffset++] = (byte) index;
+               }
+               // write the remaining part
+               invokeStringBufferStringConstructor();
+               while (i < constantLength) {
+                       length = 0;
+                       utf8encoding = new byte[Math.min(constantLength - i + 100, 65535)];
+                       int startIndex = i;
+                       while ((length < 65532) && (i < constantLength)) {
+                               char current = constantChars[i];
+                               // we resize the byte array immediately if necessary
+                               if (constantLength + 2 > (utf8encodingLength = utf8encoding.length)) {
+                                       System.arraycopy(utf8encoding, 0, utf8encoding = new byte[Math.min(utf8encodingLength + 100, 65535)], 0, length);
+                               }
+                               if ((current >= 0x0001) && (current <= 0x007F)) {
+                                       // we only need one byte: ASCII table
+                                       utf8encoding[length++] = (byte) current;
+                               } else {
+                                       if (current > 0x07FF) {
+                                               // we need 3 bytes
+                                               utf8encoding[length++] = (byte) (0xE0 | ((current >> 12) & 0x0F)); // 0xE0 = 1110 0000
+                                               utf8encoding[length++] = (byte) (0x80 | ((current >> 6) & 0x3F)); // 0x80 = 1000 0000
+                                               utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+                                       } else {
+                                               // we can be 0 or between 0x0080 and 0x07FF
+                                               // In that case we only need 2 bytes
+                                               utf8encoding[length++] = (byte) (0xC0 | ((current >> 6) & 0x1F)); // 0xC0 = 1100 0000
+                                               utf8encoding[length++] = (byte) (0x80 | (current & 0x3F)); // 0x80 = 1000 0000
+                                       }
+                               }
+                               i++;
+                       }
+                       // the next part is done
+                       subChars = new char[i - startIndex];
+                       System.arraycopy(constantChars, startIndex, subChars, 0, i - startIndex);
+                       System.arraycopy(utf8encoding, 0, utf8encoding = new byte[length], 0, length);
+                       index = constantPool.literalIndex(subChars, utf8encoding);
+                       stackDepth++;
+                       if (stackDepth > stackMax)
+                               stackMax = stackDepth;
+                       if (index > 255) {
+                               // Generate a ldc_w
+                               if (classFileOffset + 2 >= bCodeStream.length) {
+                                       resizeByteArray();
+                               }
+                               position++;
+                               bCodeStream[classFileOffset++] = OPC_ldc_w;
+                               writeUnsignedShort(index);
+                       } else {
+                               // Generate a ldc
+                               if (classFileOffset + 1 >= bCodeStream.length) {
+                                       resizeByteArray();
+                               }
+                               position += 2;
+                               bCodeStream[classFileOffset++] = OPC_ldc;
+                               bCodeStream[classFileOffset++] = (byte) index;
+                       }
+                       // now on the stack it should be a StringBuffer and a string.
+                       invokeStringBufferAppendForType(T_String);
+               }
+               invokeStringBufferToString();
+               invokeStringIntern();
+       }
+}
+final public void ldc2_w(double constant) {
+       if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$
+       countLabels = 0;
+       int index = constantPool.literalIndex(constant);
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       // Generate a ldc2_w
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ldc2_w;
+       writeUnsignedShort(index);
+}
+final public void ldc2_w(long constant) {
+       if (DEBUG) System.out.println(position + "\t\tldc2_w:"+constant); //$NON-NLS-1$
+       countLabels = 0;
+       int index = constantPool.literalIndex(constant);
+       stackDepth += 2;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       // Generate a ldc2_w
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ldc2_w;
+       writeUnsignedShort(index);
+}
+final public void ldiv() {
+       if (DEBUG) System.out.println(position + "\t\tldiv"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_ldiv;
+}
+final public void lload(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tlload:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (maxLocals <= iArg + 1) {
+               maxLocals = iArg + 2;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_lload;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_lload;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void lload_0() {
+       if (DEBUG) System.out.println(position + "\t\tlload_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (maxLocals < 2) {
+               maxLocals = 2;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lload_0;
+}
+final public void lload_1() {
+       if (DEBUG) System.out.println(position + "\t\tlload_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (maxLocals < 3) {
+               maxLocals = 3;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lload_1;
+}
+final public void lload_2() {
+       if (DEBUG) System.out.println(position + "\t\tlload_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (maxLocals < 4) {
+               maxLocals = 4;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lload_2;
+}
+final public void lload_3() {
+       if (DEBUG) System.out.println(position + "\t\tlload_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth += 2;
+       if (maxLocals < 5) {
+               maxLocals = 5;
+       }
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lload_3;
+}
+final public void lmul() {
+       if (DEBUG) System.out.println(position + "\t\tlmul"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lmul;
+}
+final public void lneg() {
+       if (DEBUG) System.out.println(position + "\t\tlneg"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lneg;
+}
+public final void load(LocalVariableBinding localBinding) {
+       countLabels = 0;
+       TypeBinding typeBinding = localBinding.type;
+       int resolvedPosition = localBinding.resolvedPosition;
+       // Using dedicated int bytecode
+       if (typeBinding == IntBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.iload_0();
+                               break;
+                       case 1 :
+                               this.iload_1();
+                               break;
+                       case 2 :
+                               this.iload_2();
+                               break;
+                       case 3 :
+                               this.iload_3();
+                               break;
+                       //case -1 :
+                       // internal failure: trying to load variable not supposed to be generated
+                       //      break;
+                       default :
+                               this.iload(resolvedPosition);
+               }
+               return;
+       }
+       // Using dedicated float bytecode
+       if (typeBinding == FloatBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.fload_0();
+                               break;
+                       case 1 :
+                               this.fload_1();
+                               break;
+                       case 2 :
+                               this.fload_2();
+                               break;
+                       case 3 :
+                               this.fload_3();
+                               break;
+                       default :
+                               this.fload(resolvedPosition);
+               }
+               return;
+       }
+       // Using dedicated long bytecode
+       if (typeBinding == LongBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.lload_0();
+                               break;
+                       case 1 :
+                               this.lload_1();
+                               break;
+                       case 2 :
+                               this.lload_2();
+                               break;
+                       case 3 :
+                               this.lload_3();
+                               break;
+                       default :
+                               this.lload(resolvedPosition);
+               }
+               return;
+       }
+       // Using dedicated double bytecode
+       if (typeBinding == DoubleBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.dload_0();
+                               break;
+                       case 1 :
+                               this.dload_1();
+                               break;
+                       case 2 :
+                               this.dload_2();
+                               break;
+                       case 3 :
+                               this.dload_3();
+                               break;
+                       default :
+                               this.dload(resolvedPosition);
+               }
+               return;
+       }
+       // boolean, byte, char and short are handled as int
+       if ((typeBinding == ByteBinding) || (typeBinding == CharBinding) || (typeBinding == BooleanBinding) || (typeBinding == ShortBinding)) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.iload_0();
+                               break;
+                       case 1 :
+                               this.iload_1();
+                               break;
+                       case 2 :
+                               this.iload_2();
+                               break;
+                       case 3 :
+                               this.iload_3();
+                               break;
+                       default :
+                               this.iload(resolvedPosition);
+               }
+               return;
+       }
+
+       // Reference object
+       switch (resolvedPosition) {
+               case 0 :
+                       this.aload_0();
+                       break;
+               case 1 :
+                       this.aload_1();
+                       break;
+               case 2 :
+                       this.aload_2();
+                       break;
+               case 3 :
+                       this.aload_3();
+                       break;
+               default :
+                       this.aload(resolvedPosition);
+       }
+}
+public final void load(TypeBinding typeBinding, int resolvedPosition) {
+       countLabels = 0;
+       // Using dedicated int bytecode
+       if (typeBinding == IntBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.iload_0();
+                               break;
+                       case 1 :
+                               this.iload_1();
+                               break;
+                       case 2 :
+                               this.iload_2();
+                               break;
+                       case 3 :
+                               this.iload_3();
+                               break;
+                       default :
+                               this.iload(resolvedPosition);
+               }
+               return;
+       }
+       // Using dedicated float bytecode
+       if (typeBinding == FloatBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.fload_0();
+                               break;
+                       case 1 :
+                               this.fload_1();
+                               break;
+                       case 2 :
+                               this.fload_2();
+                               break;
+                       case 3 :
+                               this.fload_3();
+                               break;
+                       default :
+                               this.fload(resolvedPosition);
+               }
+               return;
+       }
+       // Using dedicated long bytecode
+       if (typeBinding == LongBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.lload_0();
+                               break;
+                       case 1 :
+                               this.lload_1();
+                               break;
+                       case 2 :
+                               this.lload_2();
+                               break;
+                       case 3 :
+                               this.lload_3();
+                               break;
+                       default :
+                               this.lload(resolvedPosition);
+               }
+               return;
+       }
+       // Using dedicated double bytecode
+       if (typeBinding == DoubleBinding) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.dload_0();
+                               break;
+                       case 1 :
+                               this.dload_1();
+                               break;
+                       case 2 :
+                               this.dload_2();
+                               break;
+                       case 3 :
+                               this.dload_3();
+                               break;
+                       default :
+                               this.dload(resolvedPosition);
+               }
+               return;
+       }
+       // boolean, byte, char and short are handled as int
+       if ((typeBinding == ByteBinding) || (typeBinding == CharBinding) || (typeBinding == BooleanBinding) || (typeBinding == ShortBinding)) {
+               switch (resolvedPosition) {
+                       case 0 :
+                               this.iload_0();
+                               break;
+                       case 1 :
+                               this.iload_1();
+                               break;
+                       case 2 :
+                               this.iload_2();
+                               break;
+                       case 3 :
+                               this.iload_3();
+                               break;
+                       default :
+                               this.iload(resolvedPosition);
+               }
+               return;
+       }
+
+       // Reference object
+       switch (resolvedPosition) {
+               case 0 :
+                       this.aload_0();
+                       break;
+               case 1 :
+                       this.aload_1();
+                       break;
+               case 2 :
+                       this.aload_2();
+                       break;
+               case 3 :
+                       this.aload_3();
+                       break;
+               default :
+                       this.aload(resolvedPosition);
+       }
+}
+public final void loadInt(int resolvedPosition) {
+       // Using dedicated int bytecode
+       switch (resolvedPosition) {
+               case 0 :
+                       this.iload_0();
+                       break;
+               case 1 :
+                       this.iload_1();
+                       break;
+               case 2 :
+                       this.iload_2();
+                       break;
+               case 3 :
+                       this.iload_3();
+                       break;
+               default :
+                       this.iload(resolvedPosition);
+       }
+}
+public final void loadObject(int resolvedPosition) {
+       switch (resolvedPosition) {
+               case 0 :
+                       this.aload_0();
+                       break;
+               case 1 :
+                       this.aload_1();
+                       break;
+               case 2 :
+                       this.aload_2();
+                       break;
+               case 3 :
+                       this.aload_3();
+                       break;
+               default :
+                       this.aload(resolvedPosition);
+       }
+}
+final public void lookupswitch(CaseLabel defaultLabel, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) {
+       if (DEBUG) System.out.println(position + "\t\tlookupswitch"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       int length = keys.length;
+       int pos = position;
+       defaultLabel.placeInstruction();
+       for (int i = 0; i < length; i++) {
+               casesLabel[i].placeInstruction();
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lookupswitch;
+       for (int i = (3 - (pos % 4)); i > 0; i--) {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = 0;
+       }
+       defaultLabel.branch();
+       writeSignedWord(length);
+       for (int i = 0; i < length; i++) {
+               writeSignedWord(keys[sortedIndexes[i]]);
+               casesLabel[sortedIndexes[i]].branch();
+       }
+}
+final public void lor() {
+       if (DEBUG) System.out.println(position + "\t\tlor"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lor;
+}
+final public void lrem() {
+       if (DEBUG) System.out.println(position + "\t\tlrem"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lrem;
+}
+final public void lreturn() {
+       if (DEBUG) System.out.println(position + "\t\tlreturn"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       // the stackDepth should be equal to 0 
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lreturn;
+}
+final public void lshl() {
+       if (DEBUG) System.out.println(position + "\t\tlshl"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lshl;
+}
+final public void lshr() {
+       if (DEBUG) System.out.println(position + "\t\tlshr"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lshr;
+}
+final public void lstore(int iArg) {
+       if (DEBUG) System.out.println(position + "\t\tlstore:"+iArg); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals <= iArg + 1) {
+               maxLocals = iArg + 2;
+       }
+       if (iArg > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_lstore;
+               writeUnsignedShort(iArg);
+       } else {
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_lstore;
+               bCodeStream[classFileOffset++] = (byte) iArg;
+       }
+}
+final public void lstore_0() {
+       if (DEBUG) System.out.println(position + "\t\tlstore_0"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 2) {
+               maxLocals = 2;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lstore_0;
+}
+final public void lstore_1() {
+       if (DEBUG) System.out.println(position + "\t\tlstore_1"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 3) {
+               maxLocals = 3;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lstore_1;
+}
+final public void lstore_2() {
+       if (DEBUG) System.out.println(position + "\t\tlstore_2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 4) {
+               maxLocals = 4;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lstore_2;
+}
+final public void lstore_3() {
+       if (DEBUG) System.out.println(position + "\t\tlstore_3"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (maxLocals < 5) {
+               maxLocals = 5;
+       }
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lstore_3;
+}
+final public void lsub() {
+       if (DEBUG) System.out.println(position + "\t\tlsub"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lsub;
+}
+final public void lushr() {
+       if (DEBUG) System.out.println(position + "\t\tlushr"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lushr;
+}
+final public void lxor() {
+       if (DEBUG) System.out.println(position + "\t\tlxor"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_lxor;
+}
+final public void monitorenter() {
+       if (DEBUG) System.out.println(position + "\t\tmonitorenter"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_monitorenter;
+}
+final public void monitorexit() {
+       if (DEBUG) System.out.println(position + "\t\tmonitorexit"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_monitorexit;
+}
+final public void multianewarray(TypeBinding typeBinding, int dimensions) {
+       if (DEBUG) System.out.println(position + "\t\tmultinewarray:"+typeBinding+","+dimensions); //$NON-NLS-1$ //$NON-NLS-2$
+       countLabels = 0;
+       stackDepth += (1 - dimensions);
+       if (classFileOffset + 3 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position += 2;
+       bCodeStream[classFileOffset++] = OPC_multianewarray;
+       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+       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$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_new;
+       writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+final public void newarray(int array_Type) {
+       if (DEBUG) System.out.println(position + "\t\tnewarray:"+array_Type); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset + 1 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position += 2;
+       bCodeStream[classFileOffset++] = OPC_newarray;
+       bCodeStream[classFileOffset++] = (byte) array_Type;
+}
+public void newArray(Scope scope, ArrayBinding arrayBinding) {
+       TypeBinding component = arrayBinding.elementsType(scope);
+       switch (component.id) {
+               case T_int :
+                       this.newarray(10);
+                       break;
+               case T_byte :
+                       this.newarray(8);
+                       break;
+               case T_boolean :
+                       this.newarray(4);
+                       break;
+               case T_short :
+                       this.newarray(9);
+                       break;
+               case T_char :
+                       this.newarray(5);
+                       break;
+               case T_long :
+                       this.newarray(11);
+                       break;
+               case T_float :
+                       this.newarray(6);
+                       break;
+               case T_double :
+                       this.newarray(7);
+                       break;
+               default :
+                       this.anewarray(component);
+       }
+}
+public void newJavaLangError() {
+       // new: java.lang.Error
+       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Error"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_new;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangError());
+}
+
+public void newJavaLangAssertionError() {
+       // new: java.lang.AssertionError
+       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.AssertionError"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_new;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError());
+}
+
+public void newNoClassDefFoundError() {
+       // new: java.lang.NoClassDefFoundError
+       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.NoClassDefFoundError"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_new;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError());
+}
+public void newStringBuffer() {
+       // new: java.lang.StringBuffer
+       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.StringBuffer"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_new;
+       writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuffer());
+}
+public void newWrapperFor(int typeID) {
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_new;
+       switch (typeID) {
+               case T_int : // new: java.lang.Integer
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Integer"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangInteger());
+                       break;
+               case T_boolean : // new: java.lang.Boolean
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Boolean"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean());
+                       break;
+               case T_byte : // new: java.lang.Byte
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Byte"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangByte());
+                       break;
+               case T_char : // new: java.lang.Character
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Character"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter());
+                       break;
+               case T_float : // new: java.lang.Float
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Float"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangFloat());
+                       break;
+               case T_double : // new: java.lang.Double
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Double"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangDouble());
+                       break;
+               case T_short : // new: java.lang.Short
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Short"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangShort());
+                       break;
+               case T_long : // new: java.lang.Long
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Long"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangLong());
+                       break;
+               case T_void : // new: java.lang.Void
+                       if (DEBUG) System.out.println(position + "\t\tnew: java.lang.Void"); //$NON-NLS-1$
+                       writeUnsignedShort(constantPool.literalIndexForJavaLangVoid());
+       }
+}
+final public void nop() {
+       if (DEBUG) System.out.println(position + "\t\tnop"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_nop;
+}
+final public void pop() {
+       if (DEBUG) System.out.println(position + "\t\tpop"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_pop;
+}
+final public void pop2() {
+       if (DEBUG) System.out.println(position + "\t\tpop2"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 2;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_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();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_putfield;
+       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+}
+final public void putstatic(FieldBinding fieldBinding) {
+       if (DEBUG) System.out.println(position + "\t\tputstatic:"+fieldBinding); //$NON-NLS-1$
+       countLabels = 0;
+       int id;
+       if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
+               stackDepth -= 2;
+       else
+               stackDepth -= 1;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset + 2 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_putstatic;
+       writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+}
+public void record(LocalVariableBinding local) {
+       if (!generateLocalVariableTableAttributes)
+               return;
+       if (allLocalsCounter == locals.length) {
+               // resize the collection
+               System.arraycopy(locals, 0, locals = new LocalVariableBinding[allLocalsCounter + LOCALS_INCREMENT], 0, allLocalsCounter);
+       }
+       locals[allLocalsCounter++] = local;
+       local.initializationPCs = new int[4];
+       local.initializationCount = 0;
+}
+public void recordPositionsFrom(int startPC, int sourcePos) {
+
+       /* Record positions in the table, only if nothing has 
+        * already been recorded. Since we output them on the way 
+        * up (children first for more specific info)
+        * The pcToSourceMap table is always sorted.
+        */
+
+       if (!generateLineNumberAttributes)
+               return;
+       if (sourcePos == 0)
+               return;
+
+       // no code generated for this node. e.g. field without any initialization
+       if (position == startPC)
+               return;
+
+       // Widening an existing entry that already has the same source positions
+       if (pcToSourceMapSize + 4 > pcToSourceMap.length) {
+               // resize the array pcToSourceMap
+               System.arraycopy(pcToSourceMap, 0, pcToSourceMap = new int[pcToSourceMapSize << 1], 0, pcToSourceMapSize);
+       }
+       int newLine = ClassFile.searchLineNumber(lineSeparatorPositions, sourcePos);
+       // lastEntryPC represents the endPC of the lastEntry.
+       if (pcToSourceMapSize > 0) {
+               // in this case there is already an entry in the table
+               if (pcToSourceMap[pcToSourceMapSize - 1] != newLine) {
+                       if (startPC < lastEntryPC) {
+                               // we forgot to add an entry.
+                               // search if an existing entry exists for startPC
+                               int insertionIndex = insertionIndex(pcToSourceMap, pcToSourceMapSize, startPC);
+                               if (insertionIndex != -1) {
+                                       // there is no existing entry starting with startPC.
+                                       int existingEntryIndex = indexOfSameLineEntrySincePC(startPC, newLine); // index for PC
+                                       /* the existingEntryIndex corresponds to en entry with the same line and a PC >= startPC.
+                                               in this case it is relevant to widen this entry instead of creating a new one.
+                                               line1: this(a,
+                                                 b,
+                                                 c);
+                                               with this code we generate each argument. We generate a aload0 to invoke the constructor. There is no entry for this
+                                               aload0 bytecode. The first entry is the one for the argument a.
+                                               But we want the constructor call to start at the aload0 pc and not just at the pc of the first argument.
+                                               So we widen the existing entry (if there is one) or we create a new entry with the startPC.
+                                       */
+                                       if (existingEntryIndex != -1) {
+                                               // widen existing entry
+                                               pcToSourceMap[existingEntryIndex] = startPC;
+                                       } else {
+                                               // 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
+                                       pcToSourceMap[pcToSourceMapSize++] = lastEntryPC;
+                                       pcToSourceMap[pcToSourceMapSize++] = newLine;
+                               }
+                       } else {
+                               // we can safely add the new entry. The endPC of the previous entry is not in conflit with the startPC of the new entry.
+                               pcToSourceMap[pcToSourceMapSize++] = startPC;
+                               pcToSourceMap[pcToSourceMapSize++] = newLine;
+                       }
+               } else {
+                       /* the last recorded entry is on the same line. But it could be relevant to widen this entry.
+                          we want to extend this entry forward in case we generated some bytecode before the last entry that are not related to any statement
+                       */      
+                       if (startPC < pcToSourceMap[pcToSourceMapSize - 2]) {
+                               int insertionIndex = insertionIndex(pcToSourceMap, pcToSourceMapSize, startPC);
+                               if (insertionIndex != -1) {
+                                       // widen the existing entry
+                                       // we have to figure out if we need to move the last entry at another location to keep a sorted table
+                                       /* First we need to check if at the insertion position there is not an existing entry
+                                        * that includes the one we want to insert. This is the case if pcToSourceMap[insertionIndex - 1] == newLine.
+                                        * In this case we don't want to change the table. If not, we want to insert a new entry. Prior to insertion
+                                        * we want to check if it is worth doing an arraycopy. If not we simply update the recorded pc.
+                                        */
+                                       if (!((insertionIndex > 1) && (pcToSourceMap[insertionIndex - 1] == newLine))) {
+                                               if ((pcToSourceMapSize > 4) && (pcToSourceMap[pcToSourceMapSize - 4] > startPC)) {
+                                                       System.arraycopy(pcToSourceMap, insertionIndex, pcToSourceMap, insertionIndex + 2, pcToSourceMapSize - 2 - insertionIndex);
+                                                       pcToSourceMap[insertionIndex++] = startPC;
+                                                       pcToSourceMap[insertionIndex] = newLine;                                                
+                                               } else {
+                                                       pcToSourceMap[pcToSourceMapSize - 2] = startPC;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               lastEntryPC = position;
+       } else {
+               // record the first entry
+               pcToSourceMap[pcToSourceMapSize++] = startPC;
+               pcToSourceMap[pcToSourceMapSize++] = newLine;
+               lastEntryPC = position;
+       }
+}
+/**
+ * @param anExceptionLabel org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel
+ */
+public void registerExceptionHandler(ExceptionLabel anExceptionLabel) {
+       int length;
+       if (exceptionHandlersNumber >= (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;
+}
+public final void removeNotDefinitelyAssignedVariables(Scope scope, int initStateIndex) {
+       // given some flow info, make sure we did not loose some variables initialization
+       // if this happens, then we must update their pc entries to reflect it in debug attributes
+       if (!generateLocalVariableTableAttributes)
+               return;
+/*     if (initStateIndex == lastInitStateIndexWhenRemovingInits)
+               return;
+               
+       lastInitStateIndexWhenRemovingInits = initStateIndex;
+       if (lastInitStateIndexWhenAddingInits != initStateIndex){
+               lastInitStateIndexWhenAddingInits = -2;// reinitialize add index 
+               // add(1)-remove(1)-add(1) -> ignore second add
+               // add(1)-remove(2)-add(1) -> perform second add
+       }*/
+       for (int i = 0; i < visibleLocalsCount; i++) {
+               LocalVariableBinding localBinding = visibleLocals[i];
+               if (localBinding != null) {
+                       if (initStateIndex == -1 || !isDefinitelyAssigned(scope, initStateIndex, localBinding)) {
+                               if (localBinding.initializationCount > 0) {
+                                       localBinding.recordInitializationEndPC(position);
+                               }
+                       }
+               }
+       }
+}
+/**
+ * @param referenceMethod org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param targetClassFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+ */
+public void reset(AbstractMethodDeclaration referenceMethod, ClassFile targetClassFile) {
+       init(targetClassFile);
+       this.methodDeclaration = referenceMethod;
+       preserveUnusedLocals = referenceMethod.scope.problemReporter().options.preserveAllLocalVariables;
+       initializeMaxLocals(referenceMethod.binding);
+}
+/**
+ * @param targetClassFile The given classfile to reset the code stream
+ */
+public void resetForProblemClinit(ClassFile targetClassFile) {
+       init(targetClassFile);
+       maxLocals = 0;
+}
+private final void resizeByteArray() {
+       int length = bCodeStream.length;
+       int requiredSize = length + length;
+       if (classFileOffset > requiredSize) {
+               // must be sure to grow by enough
+               requiredSize = classFileOffset + length;
+       }
+       System.arraycopy(bCodeStream, 0, bCodeStream = new byte[requiredSize], 0, length);
+}
+final public void ret(int index) {
+       if (DEBUG) System.out.println(position + "\t\tret:"+index); //$NON-NLS-1$
+       countLabels = 0;
+       if (index > 255) { // Widen
+               if (classFileOffset + 3 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_wide;
+               bCodeStream[classFileOffset++] = OPC_ret;
+               writeUnsignedShort(index);
+       } else { // Don't Widen
+               if (classFileOffset + 1 >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position += 2;
+               bCodeStream[classFileOffset++] = OPC_ret;
+               bCodeStream[classFileOffset++] = (byte) index;
+       }
+}
+final public void return_() {
+       if (DEBUG) System.out.println(position + "\t\treturn"); //$NON-NLS-1$
+       countLabels = 0;
+       // the stackDepth should be equal to 0 
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_return;
+}
+final public void saload() {
+       if (DEBUG) System.out.println(position + "\t\tsaload"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_saload;
+}
+final public void sastore() {
+       if (DEBUG) System.out.println(position + "\t\tsastore"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth -= 3;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_sastore;
+}
+/**
+ * @param operatorConstant int
+ * @param type_ID int
+ */
+public void sendOperator(int operatorConstant, int type_ID) {
+       switch (type_ID) {
+               case T_int :
+               case T_boolean :
+               case T_char :
+               case T_byte :
+               case T_short :
+                       switch (operatorConstant) {
+                               case PLUS :
+                                       this.iadd();
+                                       break;
+                               case MINUS :
+                                       this.isub();
+                                       break;
+                               case MULTIPLY :
+                                       this.imul();
+                                       break;
+                               case DIVIDE :
+                                       this.idiv();
+                                       break;
+                               case REMAINDER :
+                                       this.irem();
+                                       break;
+                               case LEFT_SHIFT :
+                                       this.ishl();
+                                       break;
+                               case RIGHT_SHIFT :
+                                       this.ishr();
+                                       break;
+                               case UNSIGNED_RIGHT_SHIFT :
+                                       this.iushr();
+                                       break;
+                               case AND :
+                                       this.iand();
+                                       break;
+                               case OR :
+                                       this.ior();
+                                       break;
+                               case XOR :
+                                       this.ixor();
+                                       break;
+                       }
+                       break;
+               case T_long :
+                       switch (operatorConstant) {
+                               case PLUS :
+                                       this.ladd();
+                                       break;
+                               case MINUS :
+                                       this.lsub();
+                                       break;
+                               case MULTIPLY :
+                                       this.lmul();
+                                       break;
+                               case DIVIDE :
+                                       this.ldiv();
+                                       break;
+                               case REMAINDER :
+                                       this.lrem();
+                                       break;
+                               case LEFT_SHIFT :
+                                       this.lshl();
+                                       break;
+                               case RIGHT_SHIFT :
+                                       this.lshr();
+                                       break;
+                               case UNSIGNED_RIGHT_SHIFT :
+                                       this.lushr();
+                                       break;
+                               case AND :
+                                       this.land();
+                                       break;
+                               case OR :
+                                       this.lor();
+                                       break;
+                               case XOR :
+                                       this.lxor();
+                                       break;
+                       }
+                       break;
+               case T_float :
+                       switch (operatorConstant) {
+                               case PLUS :
+                                       this.fadd();
+                                       break;
+                               case MINUS :
+                                       this.fsub();
+                                       break;
+                               case MULTIPLY :
+                                       this.fmul();
+                                       break;
+                               case DIVIDE :
+                                       this.fdiv();
+                                       break;
+                               case REMAINDER :
+                                       this.frem();
+                       }
+                       break;
+               case T_double :
+                       switch (operatorConstant) {
+                               case PLUS :
+                                       this.dadd();
+                                       break;
+                               case MINUS :
+                                       this.dsub();
+                                       break;
+                               case MULTIPLY :
+                                       this.dmul();
+                                       break;
+                               case DIVIDE :
+                                       this.ddiv();
+                                       break;
+                               case REMAINDER :
+                                       this.drem();
+                       }
+       }
+}
+final public void sipush(int s) {
+       if (DEBUG) System.out.println(position + "\t\tsipush:"+s); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth++;
+       if (stackDepth > stackMax)
+               stackMax = stackDepth;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_sipush;
+       writeSignedShort(s);
+}
+public static final void sort(int[] tab, int lo0, int hi0, int[] result) {
+       int lo = lo0;
+       int hi = hi0;
+       int mid;
+       if (hi0 > lo0) {
+               /* Arbitrarily establishing partition element as the midpoint of
+                 * the array.
+                 */
+               mid = tab[ (lo0 + hi0) / 2];
+               // loop through the array until indices cross
+               while (lo <= hi) {
+                       /* find the first element that is greater than or equal to 
+                        * the partition element starting from the left Index.
+                        */
+                       while ((lo < hi0) && (tab[lo] < mid))
+                               ++lo;
+                       /* find an element that is smaller than or equal to 
+                        * the partition element starting from the right Index.
+                        */
+                       while ((hi > lo0) && (tab[hi] > mid))
+                               --hi;
+                       // if the indexes have not crossed, swap
+                       if (lo <= hi) {
+                               swap(tab, lo, hi, result);
+                               ++lo;
+                               --hi;
+                       }
+               }
+               /* If the right index has not reached the left side of array
+                 * must now sort the left partition.
+                 */
+               if (lo0 < hi)
+                       sort(tab, lo0, hi, result);
+               /* If the left index has not reached the right side of array
+                 * must now sort the right partition.
+                 */
+               if (lo < hi0)
+                       sort(tab, lo, hi0, result);
+       }
+}
+
+public final void store(LocalVariableBinding localBinding, boolean valueRequired) {
+       int localPosition = localBinding.resolvedPosition;
+       // Using dedicated int bytecode
+       switch(localBinding.type.id) {
+               case TypeIds.T_int :
+               case TypeIds.T_char :
+               case TypeIds.T_byte :
+               case TypeIds.T_short :
+               case TypeIds.T_boolean :
+                       if (valueRequired)
+                               this.dup();
+                       switch (localPosition) {
+                               case 0 :
+                                       this.istore_0();
+                                       break;
+                               case 1 :
+                                       this.istore_1();
+                                       break;
+                               case 2 :
+                                       this.istore_2();
+                                       break;
+                               case 3 :
+                                       this.istore_3();
+                                       break;
+                               //case -1 :
+                               // internal failure: trying to store into variable not supposed to be generated
+                               //      break;
+                               default :
+                                       this.istore(localPosition);
+                       }
+                       break;
+               case TypeIds.T_float :
+                       if (valueRequired)
+                               this.dup();
+                       switch (localPosition) {
+                               case 0 :
+                                       this.fstore_0();
+                                       break;
+                               case 1 :
+                                       this.fstore_1();
+                                       break;
+                               case 2 :
+                                       this.fstore_2();
+                                       break;
+                               case 3 :
+                                       this.fstore_3();
+                                       break;
+                               default :
+                                       this.fstore(localPosition);
+                       }
+                       break;
+               case TypeIds.T_double :
+                       if (valueRequired)
+                               this.dup2();
+                       switch (localPosition) {
+                               case 0 :
+                                       this.dstore_0();
+                                       break;
+                               case 1 :
+                                       this.dstore_1();
+                                       break;
+                               case 2 :
+                                       this.dstore_2();
+                                       break;
+                               case 3 :
+                                       this.dstore_3();
+                                       break;
+                               default :
+                                       this.dstore(localPosition);
+                       }
+                       break;
+               case TypeIds.T_long :
+                       if (valueRequired)
+                               this.dup2();
+                       switch (localPosition) {
+                               case 0 :
+                                       this.lstore_0();
+                                       break;
+                               case 1 :
+                                       this.lstore_1();
+                                       break;
+                               case 2 :
+                                       this.lstore_2();
+                                       break;
+                               case 3 :
+                                       this.lstore_3();
+                                       break;
+                               default :
+                                       this.lstore(localPosition);
+                       }
+                       break;
+               default:
+                       // Reference object
+                       if (valueRequired)
+                               this.dup();
+                       switch (localPosition) {
+                               case 0 :
+                                       this.astore_0();
+                                       break;
+                               case 1 :
+                                       this.astore_1();
+                                       break;
+                               case 2 :
+                                       this.astore_2();
+                                       break;
+                               case 3 :
+                                       this.astore_3();
+                                       break;
+                               default :
+                                       this.astore(localPosition);
+                       }
+       }
+}
+public final void store(TypeBinding type, int localPosition) {
+       // Using dedicated int bytecode
+       if ((type == IntBinding) || (type == CharBinding) || (type == ByteBinding) || (type == ShortBinding) || (type == BooleanBinding)) {
+               switch (localPosition) {
+                       case 0 :
+                               this.istore_0();
+                               break;
+                       case 1 :
+                               this.istore_1();
+                               break;
+                       case 2 :
+                               this.istore_2();
+                               break;
+                       case 3 :
+                               this.istore_3();
+                               break;
+                       default :
+                               this.istore(localPosition);
+               }
+               return;
+       }
+       // Using dedicated float bytecode
+       if (type == FloatBinding) {
+               switch (localPosition) {
+                       case 0 :
+                               this.fstore_0();
+                               break;
+                       case 1 :
+                               this.fstore_1();
+                               break;
+                       case 2 :
+                               this.fstore_2();
+                               break;
+                       case 3 :
+                               this.fstore_3();
+                               break;
+                       default :
+                               this.fstore(localPosition);
+               }
+               return;
+       }
+       // Using dedicated long bytecode
+       if (type == LongBinding) {
+               switch (localPosition) {
+                       case 0 :
+                               this.lstore_0();
+                               break;
+                       case 1 :
+                               this.lstore_1();
+                               break;
+                       case 2 :
+                               this.lstore_2();
+                               break;
+                       case 3 :
+                               this.lstore_3();
+                               break;
+                       default :
+                               this.lstore(localPosition);
+               }
+               return;
+       }
+       // Using dedicated double bytecode
+       if (type == DoubleBinding) {
+               switch (localPosition) {
+                       case 0 :
+                               this.dstore_0();
+                               break;
+                       case 1 :
+                               this.dstore_1();
+                               break;
+                       case 2 :
+                               this.dstore_2();
+                               break;
+                       case 3 :
+                               this.dstore_3();
+                               break;
+                       default :
+                               this.dstore(localPosition);
+               }
+               return;
+       }
+       // Reference object
+       switch (localPosition) {
+               case 0 :
+                       this.astore_0();
+                       break;
+               case 1 :
+                       this.astore_1();
+                       break;
+               case 2 :
+                       this.astore_2();
+                       break;
+               case 3 :
+                       this.astore_3();
+                       break;
+               default :
+                       this.astore(localPosition);
+       }
+}
+public final void storeInt(int localPosition) {
+       switch (localPosition) {
+               case 0 :
+                       this.istore_0();
+                       break;
+               case 1 :
+                       this.istore_1();
+                       break;
+               case 2 :
+                       this.istore_2();
+                       break;
+               case 3 :
+                       this.istore_3();
+                       break;
+               default :
+                       this.istore(localPosition);
+       }
+}
+public final void storeObject(int localPosition) {
+       switch (localPosition) {
+               case 0 :
+                       this.astore_0();
+                       break;
+               case 1 :
+                       this.astore_1();
+                       break;
+               case 2 :
+                       this.astore_2();
+                       break;
+               case 3 :
+                       this.astore_3();
+                       break;
+               default :
+                       this.astore(localPosition);
+       }
+}
+final public void swap() {
+       if (DEBUG) System.out.println(position + "\t\tswap"); //$NON-NLS-1$
+       countLabels = 0;
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_swap;
+}
+private static final void swap(int a[], int i, int j, int result[]) {
+       int T;
+       T = a[i];
+       a[i] = a[j];
+       a[j] = T;
+       T = result[j];
+       result[j] = result[i];
+       result[i] = T;
+}
+final public void tableswitch(CaseLabel defaultLabel, int low, int high, int[] keys, int[] sortedIndexes, CaseLabel[] casesLabel) {
+       if (DEBUG) System.out.println(position + "\t\ttableswitch"); //$NON-NLS-1$
+       countLabels = 0;
+       stackDepth--;
+       int length = casesLabel.length;
+       int pos = position;
+       defaultLabel.placeInstruction();
+       for (int i = 0; i < length; i++)
+               casesLabel[i].placeInstruction();
+       if (classFileOffset >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position++;
+       bCodeStream[classFileOffset++] = OPC_tableswitch;
+       for (int i = (3 - (pos % 4)); i > 0; i--) {
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = 0;
+       }
+       defaultLabel.branch();
+       writeSignedWord(low);
+       writeSignedWord(high);
+       int i = low, j = low;
+       // the index j is used to know if the index i is one of the missing entries in case of an 
+       // optimized tableswitch
+       while (true) {
+               int index;
+               int key = keys[index = sortedIndexes[j - low]];
+               if (key == i) {
+                       casesLabel[index].branch();
+                       j++;
+                       if (i == high) break; // if high is maxint, then avoids wrapping to minint.
+               } else {
+                       defaultLabel.branch();
+               }
+               i++;
+       }
+}
+public String toString() {
+       StringBuffer buffer = new StringBuffer("( position:"); //$NON-NLS-1$
+       buffer.append(position);
+       buffer.append(",\nstackDepth:"); //$NON-NLS-1$
+       buffer.append(stackDepth);
+       buffer.append(",\nmaxStack:"); //$NON-NLS-1$
+       buffer.append(stackMax);
+       buffer.append(",\nmaxLocals:"); //$NON-NLS-1$
+       buffer.append(maxLocals);
+       buffer.append(")"); //$NON-NLS-1$
+       return buffer.toString();
+}
+public void updateLastRecordedEndPC(int pos) {
+
+       /* Tune positions in the table, this is due to some 
+        * extra bytecodes being
+        * added to some user code (jumps). */
+       /** OLD CODE
+               if (!generateLineNumberAttributes)
+                       return;
+               pcToSourceMap[pcToSourceMapSize - 1][1] = position;
+               // need to update the initialization endPC in case of generation of local variable attributes.
+               updateLocalVariablesAttribute(pos);     
+       */      
+
+       if (!generateLineNumberAttributes)
+               return;
+       this.lastEntryPC = pos;
+       // need to update the initialization endPC in case of generation of local variable attributes.
+       updateLocalVariablesAttribute(pos);
+}
+public void updateLocalVariablesAttribute(int pos) {
+       // need to update the initialization endPC in case of generation of local variable attributes.
+       if (generateLocalVariableTableAttributes) {
+               for (int i = 0, max = locals.length; i < max; i++) {
+                       LocalVariableBinding local = locals[i];
+                       if ((local != null) && (local.initializationCount > 0)) {
+                               if (local.initializationPCs[((local.initializationCount - 1) << 1) + 1] == pos) {
+                                       local.initializationPCs[((local.initializationCount - 1) << 1) + 1] = position;
+                               }
+                       }
+               }
+       }
+}
+/**
+ * Write a signed 16 bits value into the byte array
+ * @param value the signed short
+ */
+public final void writeSignedShort(int value) {
+       // we keep the resize in here because it is used outside the code stream
+       if (classFileOffset + 1 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position += 2;
+       bCodeStream[classFileOffset++] = (byte) (value >> 8);
+       bCodeStream[classFileOffset++] = (byte) value;
+}
+public final void writeSignedShort(int pos, int value) {
+       int currentOffset = startingClassFileOffset + pos;
+       if (currentOffset + 1 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       bCodeStream[currentOffset] = (byte) (value >> 8);
+       bCodeStream[currentOffset + 1] = (byte) value;
+}
+public final void writeSignedWord(int value) {
+       // we keep the resize in here because it is used outside the code stream
+       if (classFileOffset + 3 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       position += 4;
+       bCodeStream[classFileOffset++] = (byte) ((value & 0xFF000000) >> 24);
+       bCodeStream[classFileOffset++] = (byte) ((value & 0xFF0000) >> 16);
+       bCodeStream[classFileOffset++] = (byte) ((value & 0xFF00) >> 8);
+       bCodeStream[classFileOffset++] = (byte) (value & 0xFF);
+}
+public final void writeSignedWord(int pos, int value) {
+       int currentOffset = startingClassFileOffset + pos;
+       if (currentOffset + 4 >= bCodeStream.length) {
+               resizeByteArray();
+       }
+       bCodeStream[currentOffset++] = (byte) ((value & 0xFF000000) >> 24);
+       bCodeStream[currentOffset++] = (byte) ((value & 0xFF0000) >> 16);
+       bCodeStream[currentOffset++] = (byte) ((value & 0xFF00) >> 8);
+       bCodeStream[currentOffset++] = (byte) (value & 0xFF);
+}
+/**
+ * Write a unsigned 16 bits value into the byte array
+ * @param value the unsigned short
+ */
+protected final void writeUnsignedShort(int value) {
+       position += 2;
+       bCodeStream[classFileOffset++] = (byte) (value >>> 8);
+       bCodeStream[classFileOffset++] = (byte) value;
+}
+/*
+ * Wide conditional branch compare, improved by swapping comparison opcode
+ *   ifeq WideTarget
+ * becomes
+ *    ifne Intermediate
+ *    gotow WideTarget
+ *    Intermediate:
+ */
+public void generateWideRevertedConditionalBranch(byte revertedOpcode, Label wideTarget) {
+               Label intermediate = new Label(this);
+               if (classFileOffset >= bCodeStream.length) {
+                       resizeByteArray();
+               }
+               position++;
+               bCodeStream[classFileOffset++] = revertedOpcode;
+               intermediate.branch();
+               this.goto_w(wideTarget);
+               intermediate.place();
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
new file mode 100644 (file)
index 0000000..66a2f72
--- /dev/null
@@ -0,0 +1,3084 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.ClassFile;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+
+/**
+ * This type is used to store all the constant pool entries.
+ */
+public class ConstantPool implements ClassFileConstants, TypeIds {
+       public static final int DOUBLE_INITIAL_SIZE = 5;
+       public static final int FLOAT_INITIAL_SIZE = 3;
+       public static final int INT_INITIAL_SIZE = 248;
+       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 CLASS_INITIAL_SIZE = 86;
+       public static final int NAMEANDTYPE_INITIAL_SIZE = 272;
+       public static final int CONSTANTPOOL_INITIAL_SIZE = 2000;
+       public static final int CONSTANTPOOL_GROW_SIZE = 6000;
+       protected DoubleCache doubleCache;
+       protected FloatCache floatCache;
+       protected IntegerCache intCache;
+       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];
+       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;
+
+/**
+ * ConstantPool constructor comment.
+ */
+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.poolContent = classFile.header;
+       this.currentOffset = classFile.headerOffset;
+       // currentOffset is initialized to 0 by default
+       this.currentIndex = 1;
+       this.classFile = classFile;
+}
+/**
+ * Return the content of the receiver
+ */
+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;
+                       }       
+       }
+       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;
+                       }                       
+       }
+       return -1;
+}
+/**
+ * Return the index of the @typeBinding
+ *
+ * Returns -1 if the @typeBinding is not a predefined binding, the right index 
+ * otherwise.
+ *
+ * @param typeBinding org.eclipse.jdt.internal.compiler.lookup.TypeBinding
+ * @return <CODE>int</CODE>
+ */
+public int indexOfWellKnownTypes(TypeBinding typeBinding) {
+       switch(typeBinding.id) {
+               case T_JavaLangBoolean : return JAVA_LANG_BOOLEAN_TYPE;
+               case T_JavaLangByte : return JAVA_LANG_BYTE_TYPE;
+               case T_JavaLangCharacter : return JAVA_LANG_CHARACTER_TYPE;
+               case T_JavaLangDouble : return JAVA_LANG_DOUBLE_TYPE;
+               case T_JavaLangFloat : return JAVA_LANG_FLOAT_TYPE;
+               case T_JavaLangInteger : return JAVA_LANG_INTEGER_TYPE;
+               case T_JavaLangLong : return JAVA_LANG_LONG_TYPE;
+               case T_JavaLangShort : return JAVA_LANG_SHORT_TYPE;
+               case T_JavaLangVoid : return JAVA_LANG_VOID_TYPE;
+               case T_JavaLangClass : return JAVA_LANG_CLASS_TYPE;
+               case T_JavaLangClassNotFoundException : return JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE;
+               case T_JavaLangNoClassDefError : return JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE;
+               case T_JavaLangObject : return JAVA_LANG_OBJECT_TYPE;
+               case T_JavaLangString : return JAVA_LANG_STRING_TYPE;
+               case T_JavaLangStringBuffer : return JAVA_LANG_STRINGBUFFER_TYPE;
+               case T_JavaLangSystem : return JAVA_LANG_SYSTEM_TYPE;
+               case T_JavaLangThrowable : return JAVA_LANG_THROWABLE_TYPE;
+               case T_JavaLangError : return JAVA_LANG_ERROR_TYPE;
+               case T_JavaLangException : return JAVA_LANG_EXCEPTION_TYPE;
+               case T_JavaLangReflectConstructor : return JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE;
+               case T_JavaLangAssertionError : return JAVA_LANG_ASSERTIONERROR_TYPE;
+       }
+       return -1;
+}
+public int literalIndex(byte[] utf8encoding, char[] stringCharArray) {
+       int index;
+       if ((index = UTF8Cache.get(stringCharArray)) < 0) {
+               // The entry doesn't exit yet
+               index = UTF8Cache.put(stringCharArray, currentIndex);
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               currentIndex++;
+               // Write the tag first
+               writeU1(Utf8Tag);
+               // Then the size of the stringName array
+               //writeU2(utf8Constant.length);
+               int savedCurrentOffset = currentOffset;
+               int utf8encodingLength = utf8encoding.length;
+               if (currentOffset + 2 + utf8encodingLength >= poolContent.length) {
+                       // we need to resize the poolContent array because we won't have
+                       // enough space to write the length
+                       resizePoolContents(2 + utf8encodingLength);
+               }
+               currentOffset += 2;
+               // add in once the whole byte array
+               System.arraycopy(utf8encoding, 0, poolContent, currentOffset, utf8encodingLength);
+               currentOffset += utf8encodingLength;
+               // Now we know the length that we have to write in the constant pool
+               // we use savedCurrentOffset to do that
+               poolContent[savedCurrentOffset] = (byte) (utf8encodingLength >> 8);
+               poolContent[savedCurrentOffset + 1] = (byte) utf8encodingLength;
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @param utf8Constant char[]
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(char[] utf8Constant) {
+       int index;
+       if ((index = UTF8Cache.get(utf8Constant)) < 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 < utf8Constant.length; i++) {
+                       char current = utf8Constant[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;
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceForConstant(this.classFile.referenceBinding.scope.referenceType());
+               }
+               index = UTF8Cache.put(utf8Constant, currentIndex);
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               currentIndex++;     
+               // Now we know the length that we have to write in the constant pool
+               // we use savedCurrentOffset to do that
+               poolContent[savedCurrentOffset] = (byte) (length >> 8);
+               poolContent[savedCurrentOffset + 1] = (byte) length;
+       }
+       return index;
+}
+public int literalIndex(char[] stringCharArray, byte[] utf8encoding) {
+       int index;
+       int stringIndex;
+       if ((index = stringCache.get(stringCharArray)) < 0) {
+               // The entry doesn't exit yet
+               stringIndex = literalIndex(utf8encoding, stringCharArray);
+               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 to the double
+ * value. If the double is not already present into the pool, it is added. The 
+ * double cache is updated and it returns the right index.
+ *
+ * @param key <CODE>double</CODE>
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(double key) {
+       //Retrieve the index from the cache
+       // The double constant takes two indexes into the constant pool, but we only store
+       // the first index into the long table
+       int index;
+       // lazy initialization for base type caches
+       // If it is null, initialize it, otherwise use it
+       if (doubleCache == null) {
+                       doubleCache = new DoubleCache(DOUBLE_INITIAL_SIZE);
+       }
+       if ((index = doubleCache.get(key)) < 0) {
+               index = doubleCache.put(key, currentIndex++);
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               currentIndex++; // a double needs an extra place into the constant pool
+               // Write the double into the constant pool
+               // First add the tag
+               writeU1(DoubleTag);
+               // Then add the 8 bytes representing the double
+               long temp = java.lang.Double.doubleToLongBits(key);
+               int length = poolContent.length;
+               if (currentOffset + 8 >= length) {
+                       resizePoolContents(8);
+               }
+               for (int i = 0; i < 8; i++) {
+                       poolContent[currentOffset++] = (byte) (temp >>> (56 - (i << 3)));
+               }
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the float
+ * value. If the float is not already present into the pool, it is added. The 
+ * int cache is updated and it returns the right index.
+ *
+ * @param key <CODE>float</CODE>
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(float key) {
+       //Retrieve the index from the cache
+       int index;
+       // lazy initialization for base type caches
+       // If it is null, initialize it, otherwise use it
+       if (floatCache == null) {
+               floatCache = new FloatCache(FLOAT_INITIAL_SIZE);
+       }
+       if ((index = floatCache.get(key)) < 0) {
+               index = floatCache.put(key, currentIndex++);
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the float constant entry into the constant pool
+               // First add the tag
+               writeU1(FloatTag);
+               // Then add the 4 bytes representing the float
+               int temp = java.lang.Float.floatToIntBits(key);
+               if (currentOffset + 4 >= poolContent.length) {
+                       resizePoolContents(4);
+               }
+               for (int i = 0; i < 4; i++) {
+                       poolContent[currentOffset++] = (byte) (temp >>> (24 - i * 8));
+               }
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the int
+ * value. If the int is not already present into the pool, it is added. The 
+ * int cache is updated and it returns the right index.
+ *
+ * @param key <CODE>int</CODE>
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(int key) {
+       //Retrieve the index from the cache
+       int index;
+       // lazy initialization for base type caches
+       // If it is null, initialize it, otherwise use it
+       if (intCache == null) {
+               intCache = new IntegerCache(INT_INITIAL_SIZE);
+       }
+       if ((index = intCache.get(key)) < 0) {
+               index = intCache.put(key, currentIndex++);
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the integer constant entry into the constant pool
+               // First add the tag
+               writeU1(IntegerTag);
+               // Then add the 4 bytes representing the int
+               if (currentOffset + 4 >= poolContent.length) {
+                       resizePoolContents(4);
+               }
+               for (int i = 0; i < 4; i++) {
+                       poolContent[currentOffset++] = (byte) (key >>> (24 - i * 8));
+               }
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the long
+ * value. If the long is not already present into the pool, it is added. The 
+ * long cache is updated and it returns the right index.
+ *
+ * @param key <CODE>long</CODE>
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(long key) {
+       // Retrieve the index from the cache
+       // The long constant takes two indexes into the constant pool, but we only store
+       // the first index into the long table
+       int index;
+       // lazy initialization for base type caches
+       // If it is null, initialize it, otherwise use it
+       if (longCache == null) {
+               longCache = new LongCache(LONG_INITIAL_SIZE);
+       }
+       if ((index = longCache.get(key)) < 0) {
+               index = longCache.put(key, currentIndex++);
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               currentIndex++; // long value need an extra place into thwe constant pool
+               // Write the long into the constant pool
+               // First add the tag
+               writeU1(LongTag);
+               // Then add the 8 bytes representing the long
+               if (currentOffset + 8 >= poolContent.length) {
+                       resizePoolContents(8);
+               }
+               for (int i = 0; i < 8; i++) {
+                       poolContent[currentOffset++] = (byte) (key >>> (56 - (i << 3)));
+               }
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @param stringConstant java.lang.String
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(String stringConstant) {
+       int index;
+       char[] stringCharArray = stringConstant.toCharArray();
+       if ((index = stringCache.get(stringCharArray)) < 0) {
+               // The entry doesn't exit yet
+               int stringIndex = literalIndex(stringCharArray);
+               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 to the field binding aFieldBinding.
+ *
+ * @param aFieldBinding FieldBinding
+ * @return <CODE>int</CODE>
+ */
+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);
+               }
+       }
+       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.
+ * Note: uses the method binding #constantPoolDeclaringClass which could be an array type
+ * for the array clone method (see UpdatedMethodDeclaration).
+ * @param aMethodBinding MethodBinding
+ * @return <CODE>int</CODE>
+ */
+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);
+                       }
+               }
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @param aTypeBinding TypeBinding
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(TypeBinding aTypeBinding) {
+       int index;
+       int nameIndex;
+       int indexWellKnownType;
+       if ((indexWellKnownType = indexOfWellKnownTypes(aTypeBinding)) == -1) {
+               if ((index = classCache.get(aTypeBinding)) < 0) {
+                       // The entry doesn't exit yet
+                       nameIndex = literalIndex(aTypeBinding.constantPoolName());
+                       index = classCache.put(aTypeBinding, 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);
+               }
+       } 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);
+               }
+       }
+       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);
+               }
+       }
+       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;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangBooleanConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_BOOLEAN_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 literalIndexForJavaLangBooleanTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_BOOLEAN_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangBoolean();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_BOOLEAN_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangByte() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_BYTE_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangByteConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_BYTE_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangByteTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_BYTE_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangByte();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_BYTE_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangCharacter() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangCharacterConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_CHARACTER_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangCharacterTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_CHARACTER_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangCharacter();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_CHARACTER_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangClass() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_CLASS_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangClassConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_CLASS_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangClassForName() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[FORNAME_CLASS_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangClass();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[FORNAME_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.ForName);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.ForNameSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[FORNAME_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[FORNAME_CLASS_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangClassDesiredAssertionStatus() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[DESIREDASSERTIONSTATUS_CLASS_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangClass();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.DesiredAssertionStatus);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.DesiredAssertionStatusSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[DESIREDASSERTIONSTATUS_CLASS_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangClassGetComponentType() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangClass();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.GetComponentType);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.GetComponentTypeSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCOMPONENTTYPE_CLASS_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[GETCOMPONENTTYPE_CLASS_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangClassNotFoundException() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangClassNotFoundExceptionConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_CLASSNOTFOUNDEXCEPTION_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangDouble() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_DOUBLE_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangDoubleConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_DOUBLE_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangDoubleTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_DOUBLE_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangDouble();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_DOUBLE_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangError() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_ERROR_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangErrorConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_ERROR_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangErrorConstructor() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[JAVALANGERROR_CONSTR_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangError();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[JAVALANGERROR_CONSTR_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+public int literalIndexForJavaLangException() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_EXCEPTION_TYPE]) == 0) {
+               // The entry doesn't exit yet
+               int nameIndex = literalIndex(QualifiedNamesConstants.JavaLangExceptionConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_EXCEPTION_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangFloat() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_FLOAT_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangFloatConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_FLOAT_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangFloatTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_FLOAT_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangFloat();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_FLOAT_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangInteger() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_INTEGER_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangIntegerConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_INTEGER_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangIntegerTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_INTEGER_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangInteger();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_INTEGER_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangLong() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_LONG_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangLongConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_LONG_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangLongTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_LONG_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangLong();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_LONG_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangNoClassDefFoundError() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangNoClassDefFoundErrorConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_NOCLASSDEFFOUNDERROR_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangAssertionError() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_ASSERTIONERROR_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangAssertionErrorConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_ASSERTIONERROR_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @param typeBindingID int
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangAssertionErrorConstructor(int typeBindingID) {
+       int index = 0;
+       int nameAndTypeIndex = 0;
+       int classIndex = 0;
+       switch (typeBindingID) {
+               case T_int :
+               case T_byte :
+               case T_short :
+                       if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_INT_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangAssertionError();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_INT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorIntConstrSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[ASSERTIONERROR_CONSTR_INT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_long :
+                       if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_LONG_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangAssertionError();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_LONG_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorLongConstrSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[ASSERTIONERROR_CONSTR_LONG_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_float :
+                       if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_FLOAT_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangAssertionError();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorFloatConstrSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[ASSERTIONERROR_CONSTR_FLOAT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_double :
+                       if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_DOUBLE_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangAssertionError();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorDoubleConstrSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[ASSERTIONERROR_CONSTR_DOUBLE_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_char :
+                       if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_CHAR_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangAssertionError();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorCharConstrSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[ASSERTIONERROR_CONSTR_CHAR_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_boolean :
+                       if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_BOOLEAN_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangAssertionError();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorBooleanConstrSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[ASSERTIONERROR_CONSTR_BOOLEAN_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               //case T_Object :
+               //case T_String :
+               //case T_null :
+               default : 
+                       if ((index = wellKnownMethods[ASSERTIONERROR_CONSTR_OBJECT_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangAssertionError();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AssertionErrorObjectConstrSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[ASSERTIONERROR_CONSTR_OBJECT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+       }
+       return index;
+}
+
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangAssertionErrorDefaultConstructor() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[ASSERTIONERROR_DEFAULT_CONSTR_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangAssertionError();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.DefaultConstructorSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[ASSERTIONERROR_DEFAULT_CONSTR_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+
+
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangNoClassDefFoundErrorStringConstructor() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[NOCLASSDEFFOUNDERROR_CONSTR_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangNoClassDefFoundError();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[NOCLASSDEFFOUNDERROR_CONSTR_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangObject() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_OBJECT_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangObjectConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_OBJECT_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangReflectConstructor() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangReflectConstructor);
+               index = wellKnownTypes[JAVA_LANG_REFLECT_CONSTRUCTOR_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+public int literalIndexForJavaLangReflectConstructorNewInstance() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[NEWINSTANCE_CONSTRUCTOR_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangReflectConstructor();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[NEWINSTANCE_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.NewInstance);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.NewInstanceSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[NEWINSTANCE_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[NEWINSTANCE_CONSTRUCTOR_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangShort() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_SHORT_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangShortConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_SHORT_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangShortTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_SHORT_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangShort();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_SHORT_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangString() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_STRING_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangStringConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_STRING_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangStringBuffer() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_STRINGBUFFER_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangStringBufferConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_STRINGBUFFER_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangStringBufferAppend(int typeID) {
+       int index = 0;
+       int nameAndTypeIndex = 0;
+       int classIndex = 0;
+       switch (typeID) {
+               case T_int :
+               case T_byte :
+               case T_short :
+                       if ((index = wellKnownMethods[APPEND_INT_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_INT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendIntSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_INT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_long :
+                       if ((index = wellKnownMethods[APPEND_LONG_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_LONG_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendLongSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_LONG_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_float :
+                       if ((index = wellKnownMethods[APPEND_FLOAT_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendFloatSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_FLOAT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_double :
+                       if ((index = wellKnownMethods[APPEND_DOUBLE_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendDoubleSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_DOUBLE_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_char :
+                       if ((index = wellKnownMethods[APPEND_CHAR_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendCharSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_CHAR_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_boolean :
+                       if ((index = wellKnownMethods[APPEND_BOOLEAN_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendBooleanSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_BOOLEAN_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_Object :
+                       if ((index = wellKnownMethods[APPEND_OBJECT_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendObjectSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_OBJECT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_String :
+               case T_null :
+                       if ((index = wellKnownMethods[APPEND_STRING_METHOD]) == 0) {
+                               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_STRING_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Append);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.AppendStringSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[APPEND_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[APPEND_STRING_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangStringBufferConstructor() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[STRINGBUFFER_STRING_CONSTR_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangStringBuffer();
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.StringConstructorSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[CONSTR_STRING_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+               index = wellKnownMethods[STRINGBUFFER_STRING_CONSTR_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangStringBufferDefaultConstructor() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[STRINGBUFFER_DEFAULT_CONSTR_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangStringBuffer();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.Init);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.DefaultConstructorSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[DEFAULT_CONSTR_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[STRINGBUFFER_DEFAULT_CONSTR_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangStringBufferToString() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[STRINGBUFFER_TOSTRING_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangStringBuffer();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[TOSTRING_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.ToString);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.ToStringSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[TOSTRING_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[STRINGBUFFER_TOSTRING_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangStringIntern() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[STRING_INTERN_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangString();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[INTERN_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.Intern);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.InternSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[INTERN_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[STRING_INTERN_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangStringValueOf(int typeID) {
+       int index = 0;
+       int nameAndTypeIndex = 0;
+       int classIndex = literalIndexForJavaLangString();
+       switch (typeID) {
+               case T_int :
+               case T_byte :
+               case T_short :
+                       if ((index = wellKnownMethods[VALUEOF_INT_METHOD]) == 0) {
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_INT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfIntSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_INT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[VALUEOF_INT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_long :
+                       if ((index = wellKnownMethods[VALUEOF_LONG_METHOD]) == 0) {
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_LONG_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfLongSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_LONG_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[VALUEOF_LONG_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_float :
+                       if ((index = wellKnownMethods[VALUEOF_FLOAT_METHOD]) == 0) {
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_FLOAT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfFloatSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_FLOAT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[VALUEOF_FLOAT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_double :
+                       if ((index = wellKnownMethods[VALUEOF_DOUBLE_METHOD]) == 0) {
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfDoubleSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[VALUEOF_DOUBLE_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_char :
+                       if ((index = wellKnownMethods[VALUEOF_CHAR_METHOD]) == 0) {
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_CHAR_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfCharSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_CHAR_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[VALUEOF_CHAR_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_boolean :
+                       if ((index = wellKnownMethods[VALUEOF_BOOLEAN_METHOD]) == 0) {
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfBooleanSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[VALUEOF_BOOLEAN_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+               case T_Object :
+                       if ((index = wellKnownMethods[VALUEOF_OBJECT_METHOD]) == 0) {
+                               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_OBJECT_METHOD_NAME_AND_TYPE]) == 0) {
+                                       int nameIndex = literalIndex(QualifiedNamesConstants.ValueOf);
+                                       int typeIndex = literalIndex(QualifiedNamesConstants.ValueOfObjectSignature);
+                                       nameAndTypeIndex = wellKnownMethodNameAndTypes[VALUEOF_OBJECT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                                       writeU1(NameAndTypeTag);
+                                       writeU2(nameIndex);
+                                       writeU2(typeIndex);
+                               }
+                               index = wellKnownMethods[VALUEOF_OBJECT_METHOD] = currentIndex++;
+                               if (index > 0xFFFF){
+                                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+                               }
+                               // Write the method ref constant into the constant pool
+                               // First add the tag
+                               writeU1(MethodRefTag);
+                               // Then write the class index
+                               writeU2(classIndex);
+                               // The write the nameAndType index
+                               writeU2(nameAndTypeIndex);
+                       }
+                       break;
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangSystem() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_SYSTEM_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangSystemConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_SYSTEM_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangSystemExitInt() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[SYSTEM_EXIT_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangSystem();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[EXIT_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.Exit);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.ExitIntSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[EXIT_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[SYSTEM_EXIT_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangSystemOut() {
+       int index;
+       if ((index = wellKnownFields[OUT_SYSTEM_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangSystem();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[OUT_SYSTEM_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.Out);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaIoPrintStreamSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[OUT_SYSTEM_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[OUT_SYSTEM_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangThrowable() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_THROWABLE_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangThrowableConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_THROWABLE_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the 
+ * method descriptor. It can be either an interface method reference constant
+ * or a method reference constant.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangThrowableGetMessage() {
+       int index;
+       int nameAndTypeIndex;
+       int classIndex;
+       // Looking into the method ref table
+       if ((index = wellKnownMethods[THROWABLE_GETMESSAGE_METHOD]) == 0) {
+               classIndex = literalIndexForJavaLangThrowable();
+               if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETMESSAGE_METHOD_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.GetMessage);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.GetMessageSignature);
+                       nameAndTypeIndex = wellKnownMethodNameAndTypes[GETMESSAGE_METHOD_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownMethods[THROWABLE_GETMESSAGE_METHOD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               // Write the method ref constant into the constant pool
+               // First add the tag
+               writeU1(MethodRefTag);
+               // Then write the class index
+               writeU2(classIndex);
+               // The write the nameAndType index
+               writeU2(nameAndTypeIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool corresponding to the type descriptor.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangVoid() {
+       int index;
+       if ((index = wellKnownTypes[JAVA_LANG_VOID_TYPE]) == 0) {
+               int nameIndex;
+               // The entry doesn't exit yet
+               nameIndex = literalIndex(QualifiedNamesConstants.JavaLangVoidConstantPoolName);
+               index = wellKnownTypes[JAVA_LANG_VOID_TYPE] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(ClassTag);
+               // Then add the 8 bytes representing the long
+               writeU2(nameIndex);
+       }
+       return index;
+}
+/**
+ * This method returns the index into the constantPool 
+ * corresponding to the field binding aFieldBinding.
+ *
+ * @return <CODE>int</CODE>
+ */
+public int literalIndexForJavaLangVoidTYPE() {
+       int index;
+       if ((index = wellKnownFields[TYPE_VOID_FIELD]) == 0) {
+               int nameAndTypeIndex;
+               int classIndex;
+               // The entry doesn't exit yet
+               classIndex = literalIndexForJavaLangVoid();
+               if ((nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE]) == 0) {
+                       int nameIndex = literalIndex(QualifiedNamesConstants.TYPE);
+                       int typeIndex = literalIndex(QualifiedNamesConstants.JavaLangClassSignature);
+                       nameAndTypeIndex = wellKnownFieldNameAndTypes[TYPE_JAVALANGCLASS_NAME_AND_TYPE] = currentIndex++;
+                       writeU1(NameAndTypeTag);
+                       writeU2(nameIndex);
+                       writeU2(typeIndex);
+               }
+               index = wellKnownFields[TYPE_VOID_FIELD] = currentIndex++;
+               if (index > 0xFFFF){
+                       this.classFile.referenceBinding.scope.problemReporter().noMoreAvailableSpaceInConstantPool(this.classFile.referenceBinding.scope.referenceType());
+               }
+               writeU1(FieldRefTag);
+               writeU2(classIndex);
+               writeU2(nameAndTypeIndex);
+       }
+       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;
+}
+/**
+ * This method is used to clean the receiver in case of a clinit header is generated, but the 
+ * clinit has no code.
+ * This implementation assumes that the clinit is the first method to be generated.
+ * @see org.eclipse.jdt.internal.compiler.ast.TypeDeclaration#addClinit()
+ */
+public void resetForClinit(int constantPoolIndex, int constantPoolOffset) {
+       currentIndex = constantPoolIndex;
+       currentOffset = constantPoolOffset;
+       if (UTF8Cache.get(AttributeNamesConstants.CodeName) >= constantPoolIndex) {
+               UTF8Cache.remove(AttributeNamesConstants.CodeName);
+       }
+       if (UTF8Cache.get(QualifiedNamesConstants.ClinitSignature) >= constantPoolIndex) {
+               UTF8Cache.remove(QualifiedNamesConstants.ClinitSignature);
+       }
+       if (UTF8Cache.get(QualifiedNamesConstants.Clinit) >= constantPoolIndex) {
+               UTF8Cache.remove(QualifiedNamesConstants.Clinit);
+       }
+}
+
+/**
+ * Resize the pool contents
+ */
+private final void resizePoolContents(int minimalSize) {
+       int length = poolContent.length;
+       int toAdd = length;
+       if (toAdd < minimalSize)
+               toAdd = minimalSize;
+       System.arraycopy(poolContent, 0, poolContent = new byte[length + toAdd], 0, length);
+}
+/**
+ * Write a unsigned byte into the byte array
+ * 
+ * @param value <CODE>int</CODE> The value to write into the byte array
+ */
+protected final void writeU1(int value) {
+       if (currentOffset + 1 >= poolContent.length) {
+               resizePoolContents(1);
+       }
+       poolContent[currentOffset++] = (byte) value;
+}
+/**
+ * Write a unsigned byte into the byte array
+ * 
+ * @param value <CODE>int</CODE> The value to write into the byte array
+ */
+protected final void writeU2(int value) {
+       if (currentOffset + 2 >= poolContent.length) {
+               resizePoolContents(2);
+       }
+       //first byte
+       poolContent[currentOffset++] = (byte) (value >> 8);
+       poolContent[currentOffset++] = (byte) value;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/DoubleCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/DoubleCache.java
new file mode 100644 (file)
index 0000000..edb7d17
--- /dev/null
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * 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 class DoubleCache {
+       private double keyTable[];
+       private int valueTable[]; 
+       private int elementSize;
+/**
+ * Constructs a new, empty hashtable. A default capacity and
+ * load factor is used. Note that the hashtable will automatically 
+ * grow when it gets full.
+ */
+public DoubleCache() {
+       this(13);
+}
+/**
+ * Constructs a new, empty hashtable with the specified initial
+ * capacity.
+ * @param initialCapacity int
+ *  the initial number of buckets
+ */
+public DoubleCache(int initialCapacity) {
+       elementSize = 0;
+       keyTable = new double[initialCapacity];
+       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] = 0.0;
+               valueTable[i] = 0;
+       }
+       elementSize = 0;
+}
+/** Returns true if the collection contains an element for the key.
+ *
+ * @param key <CODE>double</CODE> the key that we are looking for
+ * @return boolean
+ */
+public boolean containsKey(double key) {
+       if (key == 0.0) {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == 0.0) {
+                               long value1 = Double.doubleToLongBits(key);
+                               long value2 = Double.doubleToLongBits(keyTable[i]);
+                               if (value1 == -9223372036854775808L && value2 == -9223372036854775808L)
+                                       return true;
+                               if (value1 == 0 && value2 == 0)
+                                       return true;
+                       }
+               }
+       } else {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == key) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+/** Gets the object associated with the specified key in the
+ * hashtable.
+ * @param key <CODE>double</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(double key) {
+       if (key == 0.0) {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == 0.0) {
+                               long value1 = Double.doubleToLongBits(key);
+                               long value2 = Double.doubleToLongBits(keyTable[i]);
+                               if (value1 == -9223372036854775808L && value2 == -9223372036854775808L)
+                                       return valueTable[i];
+                               if (value1 == 0 && value2 == 0)
+                                       return valueTable[i];
+                       }
+               }
+       } else {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == key) {
+                               return valueTable[i];
+                       }
+               }
+       }
+       return -1;
+}
+/**
+ * Puts the specified element into the hashtable, using the specified
+ * key.  The element may be retrieved by doing a get() with the same key.
+ * 
+ * @param key <CODE>double</CODE> the specified key in the hashtable
+ * @param value <CODE>int</CODE> the specified element
+ * @return int value
+ */
+public int put(double key, int value) {
+       if (elementSize == keyTable.length) {
+               // resize
+               System.arraycopy(keyTable, 0, (keyTable = new double[elementSize * 2]), 0, elementSize);
+               System.arraycopy(valueTable, 0, (valueTable = new int[elementSize * 2]), 0, elementSize);
+       }
+       keyTable[elementSize] = key;
+       valueTable[elementSize] = value;
+       elementSize++;
+       return value;
+}
+/**
+ * Converts to a rather lengthy String.
+ *
+ * @return String the ascii representation of the receiver
+ */
+public String toString() {
+       int max = elementSize;
+       StringBuffer buf = new StringBuffer();
+       buf.append("{"); //$NON-NLS-1$
+       for (int i = 0; i < max; ++i) {
+               if ((keyTable[i] != 0) || ((keyTable[i] == 0) &&(valueTable[i] != 0))) {
+                       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/java/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java
new file mode 100644 (file)
index 0000000..31b2ee5
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.codegen;
+
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class ExceptionLabel extends Label {
+       
+       public int start = POS_NOT_SET;
+       public int end = POS_NOT_SET;
+       public TypeBinding exceptionType;
+       
+       public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) {
+
+               super(codeStream);
+               this.exceptionType = exceptionType;
+               this.placeStart();      
+       }
+
+       public boolean isStandardLabel(){
+
+               return false;
+       }
+
+       public void place() {
+
+               // register the handler inside the codeStream then normal place
+               codeStream.registerExceptionHandler(this);
+               super.place();
+       }
+
+       public void placeEnd() {
+
+               this.end = codeStream.position;
+       }
+       
+       public void placeStart() {
+
+               this.start = codeStream.position;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/FieldNameAndTypeCache.java
new file mode 100644 (file)
index 0000000..0982a06
--- /dev/null
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * 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/java/org/eclipse/jdt/internal/compiler/codegen/FloatCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/FloatCache.java
new file mode 100644 (file)
index 0000000..3bbe945
--- /dev/null
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * 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 class FloatCache {
+       private float keyTable[];
+       private int valueTable[];
+       private int elementSize;
+/**
+ * Constructs a new, empty hashtable. A default capacity and
+ * load factor is used. Note that the hashtable will automatically 
+ * grow when it gets full.
+ */
+public FloatCache() {
+       this(13);
+}
+/**
+ * Constructs a new, empty hashtable with the specified initial
+ * capacity.
+ * @param initialCapacity int
+ *  the initial number of buckets
+ */
+public FloatCache(int initialCapacity) {
+       elementSize = 0;
+       keyTable = new float[initialCapacity];
+       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] = 0.0f;
+               valueTable[i] = 0;
+       }
+       elementSize = 0;
+}
+/** Returns true if the collection contains an element for the key.
+ *
+ * @param key <CODE>float</CODE> the key that we are looking for
+ * @return boolean
+ */
+public boolean containsKey(float key) {
+       if (key == 0.0f) {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == 0.0f) {
+                               int value1 = Float.floatToIntBits(key);
+                               int value2 = Float.floatToIntBits(keyTable[i]);
+                               if (value1 == -2147483648 && value2 == -2147483648)
+                                       return true;
+                               if (value1 == 0 && value2 == 0)
+                                       return true;
+                       }
+               }
+       } else {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == key) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+/** Gets the object associated with the specified key in the
+ * hashtable.
+ * @param key <CODE>float</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(float key) {
+       if (key == 0.0f) {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == 0.0f) {
+                               int value1 = Float.floatToIntBits(key);
+                               int value2 = Float.floatToIntBits(keyTable[i]);
+                               if (value1 == -2147483648 && value2 == -2147483648)
+                                       return valueTable[i];
+                               if (value1 == 0 && value2 == 0)
+                                       return valueTable[i];
+                       }
+               }
+       } else {
+               for (int i = 0, max = elementSize; i < max; i++) {
+                       if (keyTable[i] == key) {
+                               return valueTable[i];
+                       }
+               }
+       }
+       return -1;
+}
+/**
+ * Puts the specified element into the hashtable, using the specified
+ * key.  The element may be retrieved by doing a get() with the same key.
+ * 
+ * @param key <CODE>float</CODE> the specified key in the hashtable
+ * @param value <CODE>int</CODE> the specified element
+ * @return int value
+ */
+public int put(float key, int value) {
+       if (elementSize == keyTable.length) {
+               // resize
+               System.arraycopy(keyTable, 0, (keyTable = new float[elementSize * 2]), 0, elementSize);
+               System.arraycopy(valueTable, 0, (valueTable = new int[elementSize * 2]), 0, elementSize);
+       }
+       keyTable[elementSize] = key;
+       valueTable[elementSize] = value;
+       elementSize++;
+       return value;
+}
+/**
+ * Converts to a rather lengthy String.
+ *
+ * @return String the ascii representation of the receiver
+ */
+public String toString() {
+       int max = elementSize;
+       StringBuffer buf = new StringBuffer();
+       buf.append("{"); //$NON-NLS-1$
+       for (int i = 0; i < max; ++i) {
+               if ((keyTable[i] != 0) || ((keyTable[i] == 0) && (valueTable[i] != 0))) {
+                       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/java/org/eclipse/jdt/internal/compiler/codegen/IntegerCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/IntegerCache.java
new file mode 100644 (file)
index 0000000..91b36a6
--- /dev/null
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * 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 class IntegerCache {
+       public int keyTable[];
+       public int valueTable[]; 
+       int elementSize;
+       int threshold;
+/**
+ * Constructs a new, empty hashtable. A default capacity and
+ * load factor is used. Note that the hashtable will automatically 
+ * grow when it gets full.
+ */
+public IntegerCache() {
+       this(13);
+}
+/**
+ * Constructs a new, empty hashtable with the specified initial
+ * capacity.
+ * @param initialCapacity int
+ *  the initial number of buckets
+ */
+public IntegerCache(int initialCapacity) {
+       elementSize = 0;
+       threshold = (int) (initialCapacity * 0.66);
+       keyTable = new int[initialCapacity];
+       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] = 0;
+               valueTable[i] = 0;
+       }
+       elementSize = 0;
+}
+/** Returns true if the collection contains an element for the key.
+ *
+ * @param key <CODE>double</CODE> the key that we are looking for
+ * @return boolean
+ */
+public boolean containsKey(int key) {
+       int index = hash(key);
+       while ((keyTable[index] != 0) || ((keyTable[index] == 0) &&(valueTable[index] != 0))) {
+               if (keyTable[index] == key)
+                       return true;
+               index = (index + 1) % keyTable.length;
+       }
+       return false;
+}
+/** Gets the object associated with the specified key in the
+ * hashtable.
+ * @param key <CODE>double</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(int key) {
+       int index = hash(key);
+       while ((keyTable[index] != 0) || ((keyTable[index] == 0) &&(valueTable[index] != 0))) {
+               if (keyTable[index] == key)
+                       return valueTable[index];
+               index = (index + 1) % keyTable.length;
+       }
+       return -1;
+}
+/**
+ * Return a hashcode for the value of the key parameter.
+ * @param key int
+ * @return int the hash code corresponding to the key value
+ */
+public int hash(int key) {
+       return (key & 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.
+ * 
+ * @param key <CODE>int</CODE> the specified key in the hashtable
+ * @param value <CODE>int</CODE> the specified element
+ * @return int value
+ */
+public int put(int key, int value) {
+       int index = hash(key);
+       while ((keyTable[index] != 0) || ((keyTable[index] == 0) && (valueTable[index] != 0))) {
+               if (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() {
+       IntegerCache newHashtable = new IntegerCache(keyTable.length * 2);
+       for (int i = keyTable.length; --i >= 0;) {
+               int key = keyTable[i];
+               int value = valueTable[i];
+               if ((key != 0) || ((key == 0) && (value != 0))) {
+                       newHashtable.put(key, value);
+               }
+       }
+       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] != 0) || ((keyTable[i] == 0) && (valueTable[i] != 0))) {
+                       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/java/org/eclipse/jdt/internal/compiler/codegen/Label.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/Label.java
new file mode 100644 (file)
index 0000000..8c29bce
--- /dev/null
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * 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.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
+
+/**
+ * This type is a port of smalltalks JavaLabel
+ */
+public class Label {
+       public CodeStream codeStream;
+       final static int POS_NOT_SET = -1;
+       public int position = POS_NOT_SET; // position=POS_NOT_SET Then it's pos is not set.
+       public int[] forwardReferences = new int[10]; // Add an overflow check here.
+       public int forwardReferenceCount = 0;
+       private boolean isWide = false;
+       
+public Label() {
+       // for creating labels ahead of code generation
+}
+/**
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ */
+public Label(CodeStream codeStream) {
+       this.codeStream = codeStream;
+}
+/**
+ * Add a forward refrence for the array.
+ */
+void addForwardReference(int iPos) {
+       int length;
+       if (forwardReferenceCount >= (length = forwardReferences.length))
+               System.arraycopy(forwardReferences, 0, (forwardReferences = new int[2*length]), 0, length);
+       forwardReferences[forwardReferenceCount++] = iPos;
+}
+/**
+ * Add a forward refrence for the array.
+ */
+public void appendForwardReferencesFrom(Label otherLabel) {
+       int otherCount = otherLabel.forwardReferenceCount;
+       if (otherCount == 0) return;
+       int length = forwardReferences.length;
+       int neededSpace = otherCount + forwardReferenceCount;
+       if (neededSpace >= length){
+               System.arraycopy(forwardReferences, 0, (forwardReferences = new int[neededSpace]), 0, forwardReferenceCount);
+       }
+       // append other forward references at the end, so they will get updated as well
+       System.arraycopy(otherLabel.forwardReferences, 0, forwardReferences, forwardReferenceCount, otherCount);
+       forwardReferenceCount = neededSpace;
+}
+/*
+* Put down  a reference to the array at the location in the codestream.
+*/
+void branch() {
+       if (position == POS_NOT_SET) {
+               addForwardReference(codeStream.position);
+               // Leave two bytes free to generate the jump afterwards
+               codeStream.position += 2;
+               codeStream.classFileOffset += 2;
+       } else {
+               /*
+                * Position is set. Write it if it is not a wide branch.
+                */
+               int offset = position - codeStream.position + 1;
+               if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
+                       throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE, null);
+               }
+               codeStream.writeSignedShort(offset);
+       }
+}
+/*
+* No support for wide branches yet
+*/
+void branchWide() {
+       if (position == POS_NOT_SET) {
+               addForwardReference(codeStream.position);
+               // Leave 4 bytes free to generate the jump offset afterwards
+               isWide = true;
+               codeStream.position += 4;
+               codeStream.classFileOffset += 4;
+       } else { //Position is set. Write it!
+               codeStream.writeSignedWord(position - codeStream.position + 1);
+       }
+}
+/**
+ * @return boolean
+ */
+public boolean hasForwardReferences() {
+       return forwardReferenceCount != 0;
+}
+/*
+ * Some placed labels might be branching to a goto bytecode which we can optimize better.
+ */
+public void inlineForwardReferencesFromLabelsTargeting(int gotoLocation) {
+       
+/*
+ Code required to optimized unreachable gotos.
+       public boolean isBranchTarget(int location) {
+               Label[] labels = codeStream.labels;
+               for (int i = codeStream.countLabels - 1; i >= 0; i--){
+                       Label label = labels[i];
+                       if ((label.position == location) && label.isStandardLabel()){
+                               return true;
+                       }
+               }
+               return false;
+       }
+ */
+       
+       Label[] labels = codeStream.labels;
+       for (int i = codeStream.countLabels - 1; i >= 0; i--){
+               Label label = labels[i];
+               if ((label.position == gotoLocation) && label.isStandardLabel()){
+                       this.appendForwardReferencesFrom(label);
+                       /*
+                        Code required to optimized unreachable gotos.
+                               label.position = POS_NOT_SET;
+                       */
+               } else {
+                       break; // same target labels should be contiguous
+               }
+       }
+}
+public void initialize(CodeStream stream) {
+    this.codeStream = stream;
+       this.position = POS_NOT_SET;
+       this.forwardReferenceCount = 0; 
+}
+public boolean isStandardLabel(){
+       return true;
+}
+/*
+* Place the label. If we have forward references resolve them.
+*/
+public void place() { // Currently lacking wide support.
+       if (CodeStream.DEBUG) System.out.println("\t\t\t\t<place at: "+codeStream.position+" - "+ this); //$NON-NLS-1$ //$NON-NLS-2$
+
+       if (position == POS_NOT_SET) {
+               position = codeStream.position;
+               codeStream.addLabel(this);
+               int oldPosition = position;
+               boolean isOptimizedBranch = false;
+               // TURNED OFF since fail on 1F4IRD9
+               if (forwardReferenceCount != 0) {
+                       isOptimizedBranch = (forwardReferences[forwardReferenceCount - 1] + 2 == position) && (codeStream.bCodeStream[codeStream.classFileOffset - 3] == Opcodes.OPC_goto);
+                       if (isOptimizedBranch) {
+                               codeStream.position = (position -= 3);
+                               codeStream.classFileOffset -= 3;
+                               forwardReferenceCount--;
+                               // also update the PCs in the related debug attributes
+                               /** OLD CODE
+                                       int index = codeStream.pcToSourceMapSize - 1;
+                                               while ((index >= 0) && (codeStream.pcToSourceMap[index][1] == oldPosition)) {
+                                                       codeStream.pcToSourceMap[index--][1] = position;
+                                               }
+                               */
+                               // Beginning of new code
+                               int index = codeStream.pcToSourceMapSize - 2;
+                               if (codeStream.lastEntryPC == oldPosition) {
+                                       codeStream.lastEntryPC = position;
+                               }
+                               if ((index >= 0) && (codeStream.pcToSourceMap[index] == position)) {
+                                       codeStream.pcToSourceMapSize-=2;
+                               }
+                               // end of new code
+                               if (codeStream.generateLocalVariableTableAttributes) {
+                                       LocalVariableBinding locals[] = codeStream.locals;
+                                       for (int i = 0, max = locals.length; i < max; i++) {
+                                               LocalVariableBinding local = locals[i];
+                                               if ((local != null) && (local.initializationCount > 0)) {
+                                                       if (local.initializationPCs[((local.initializationCount - 1) << 1) + 1] == oldPosition) {
+                                                               // we want to prevent interval of size 0 to have a negative size.
+                                                               // see PR 1GIRQLA: ITPJCORE:ALL - ClassFormatError for local variable attribute
+                                                               local.initializationPCs[((local.initializationCount - 1) << 1) + 1] = position;
+                                                       }
+                                                       if (local.initializationPCs[(local.initializationCount - 1) << 1] == oldPosition) {
+                                                               local.initializationPCs[(local.initializationCount - 1) << 1] = position;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               for (int i = 0; i < forwardReferenceCount; i++) {
+                       int offset = position - forwardReferences[i] + 1;
+                       if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
+                               throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE, null);
+                       }
+                       if (this.codeStream.wideMode) {
+                               if (this.isWide) {
+                                       codeStream.writeSignedWord(forwardReferences[i], offset);
+                               } else {
+                                       codeStream.writeSignedShort(forwardReferences[i], offset);
+                               }
+                       } else {
+                               codeStream.writeSignedShort(forwardReferences[i], offset);
+                       }
+               }
+               // For all labels placed at that position we check if we need to rewrite the jump
+               // offset. It is the case each time a label had a forward reference to the current position.
+               // Like we change the current position, we have to change the jump offset. See 1F4IRD9 for more details.
+               if (isOptimizedBranch) {
+                       for (int i = 0; i < codeStream.countLabels; i++) {
+                               Label label = codeStream.labels[i];
+                               if (oldPosition == label.position) {
+                                       label.position = position;
+                                       if (label instanceof CaseLabel) {
+                                               int offset = position - ((CaseLabel) label).instructionPosition;
+                                               for (int j = 0; j < label.forwardReferenceCount; j++) {
+                                                       int forwardPosition = label.forwardReferences[j];
+                                                       codeStream.writeSignedWord(forwardPosition, offset);
+                                               }
+                                       } else {
+                                               for (int j = 0; j < label.forwardReferenceCount; j++) {
+                                                       int forwardPosition = label.forwardReferences[j];
+                                                       int offset = position - forwardPosition + 1;
+                                                       if (Math.abs(offset) > 0x7FFF && !this.codeStream.wideMode) {
+                                                               throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE, null);
+                                                       }
+                                                       if (this.codeStream.wideMode) {
+                                                               if (this.isWide) {
+                                                                       codeStream.writeSignedWord(forwardPosition, offset);
+                                                               } else {
+                                                                       codeStream.writeSignedShort(forwardPosition, offset);
+                                                               }
+                                                       } else {
+                                                               codeStream.writeSignedShort(forwardPosition, offset);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+/**
+ * Print out the receiver
+ */
+public String toString() {
+       String basic = getClass().getName();
+       basic = basic.substring(basic.lastIndexOf('.')+1);
+       StringBuffer buffer = new StringBuffer(basic); 
+       buffer.append('@').append(Integer.toHexString(hashCode()));
+       buffer.append("(position=").append(position); //$NON-NLS-1$
+       buffer.append(", forwards = ["); //$NON-NLS-1$
+       for (int i = 0; i < forwardReferenceCount - 1; i++)
+               buffer.append(forwardReferences[i] + ", "); //$NON-NLS-1$
+       if (forwardReferenceCount >= 1)
+               buffer.append(forwardReferences[forwardReferenceCount-1]);
+       buffer.append("] )"); //$NON-NLS-1$
+       return buffer.toString();
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/LongCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/LongCache.java
new file mode 100644 (file)
index 0000000..cfb5f08
--- /dev/null
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * 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 class LongCache {
+       public long keyTable[];
+       public int valueTable[]; 
+       int elementSize;
+       int threshold;
+/**
+ * Constructs a new, empty hashtable. A default capacity and
+ * load factor is used. Note that the hashtable will automatically 
+ * grow when it gets full.
+ */
+public LongCache() {
+       this(13);
+}
+/**
+ * Constructs a new, empty hashtable with the specified initial
+ * capacity.
+ * @param initialCapacity int
+ *  the initial number of buckets
+ */
+public LongCache(int initialCapacity) {
+       elementSize = 0;
+       threshold = (int) (initialCapacity * 0.66);
+       keyTable = new long[initialCapacity];
+       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] = 0;
+               valueTable[i] = 0;
+       }
+       elementSize = 0;
+}
+/** Returns true if the collection contains an element for the key.
+ *
+ * @param key <CODE>long</CODE> the key that we are looking for
+ * @return boolean
+ */
+public boolean containsKey(long key) {
+       int index = hash(key);
+       while ((keyTable[index] != 0) || ((keyTable[index] == 0) &&(valueTable[index] != 0))) {
+               if (keyTable[index] == key)
+                       return true;
+               index = (index + 1) % keyTable.length;
+       }
+       return false;
+}
+/** Gets the object associated with the specified key in the
+ * hashtable.
+ * @param key <CODE>long</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(long key) {
+       int index = hash(key);
+       while ((keyTable[index] != 0) || ((keyTable[index] == 0) &&(valueTable[index] != 0))) {
+               if (keyTable[index] == key)
+                       return valueTable[index];
+               index = (index + 1) % keyTable.length;
+       }
+       return -1;
+}
+/**
+ * Return a hashcode for the value of the key parameter.
+ * @param key long
+ * @return int the hash code corresponding to the key value
+ */
+public int hash(long key) {
+       return ((int) key & 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.
+ * 
+ * @param key <CODE>long</CODE> the specified key in the hashtable
+ * @param value <CODE>int</CODE> the specified element
+ * @return int value
+ */
+public int put(long key, int value) {
+       int index = hash(key);
+       while ((keyTable[index] != 0) || ((keyTable[index] == 0) && (valueTable[index] != 0))) {
+               if (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() {
+       LongCache newHashtable = new LongCache(keyTable.length * 2);
+       for (int i = keyTable.length; --i >= 0;) {
+               long key = keyTable[i];
+               int value = valueTable[i];
+               if ((key != 0) || ((key == 0) && (value != 0))) {
+                       newHashtable.put(key, value);
+               }
+       }
+       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] != 0) || ((keyTable[i] == 0) && (valueTable[i] != 0))) {
+                       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/java/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/MethodNameAndTypeCache.java
new file mode 100644 (file)
index 0000000..2ab3da3
--- /dev/null
@@ -0,0 +1,162 @@
+/*******************************************************************************
+ * 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/java/org/eclipse/jdt/internal/compiler/codegen/ObjectCache.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/ObjectCache.java
new file mode 100644 (file)
index 0000000..a1ff0eb
--- /dev/null
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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 class ObjectCache {
+       public Object 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 ObjectCache() {
+       this(13);
+}
+/**
+ * Constructs a new, empty hashtable with the specified initial
+ * capacity.
+ * @param initialCapacity int
+ *  the initial number of buckets
+ */
+public ObjectCache(int initialCapacity) {
+       this.elementSize = 0;
+       this.threshold = (int) (initialCapacity * 0.66f);
+       this.keyTable = new Object[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(Object key) {
+       int index = hashCode(key);
+       while (keyTable[index] != null) {
+               if (keyTable[index] == key)
+                       return true;
+               index = (index + 1) % keyTable.length;
+       }
+       return false;
+}
+/** 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(Object key) {
+       int index = hashCode(key);
+       while (keyTable[index] != null) {
+               if (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(Object key) {
+       return (key.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(Object key, int value) { 
+       int index = hashCode(key);
+       while (keyTable[index] != null) {
+               if (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() {
+       ObjectCache newHashtable = new ObjectCache(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/java/org/eclipse/jdt/internal/compiler/codegen/Opcodes.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/Opcodes.java
new file mode 100644 (file)
index 0000000..8fc2355
--- /dev/null
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * 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 Opcodes {
+
+       public static final byte OPC_nop = 0;
+       public static final byte OPC_aconst_null = 1;
+       public static final byte OPC_iconst_m1 = 2;
+       public static final byte OPC_iconst_0 = 3;
+       public static final byte OPC_iconst_1 = 4;
+       public static final byte OPC_iconst_2 = 5;
+       public static final byte OPC_iconst_3 = 6;
+       public static final byte OPC_iconst_4 = 7;
+       public static final byte OPC_iconst_5 = 8;
+       public static final byte OPC_lconst_0 = 9;
+       public static final byte OPC_lconst_1 = 10;
+       public static final byte OPC_fconst_0 = 11;
+       public static final byte OPC_fconst_1 = 12;
+       public static final byte OPC_fconst_2 = 13;
+       public static final byte OPC_dconst_0 = 14;
+       public static final byte OPC_dconst_1 = 15;
+       public static final byte OPC_bipush = 16;
+       public static final byte OPC_sipush = 17;
+       public static final byte OPC_ldc = 18;
+       public static final byte OPC_ldc_w = 19;
+       public static final byte OPC_ldc2_w = 20;
+       public static final byte OPC_iload = 21;
+       public static final byte OPC_lload = 22;
+       public static final byte OPC_fload = 23;
+       public static final byte OPC_dload = 24;
+       public static final byte OPC_aload = 25;
+       public static final byte OPC_iload_0 = 26;
+       public static final byte OPC_iload_1 = 27;
+       public static final byte OPC_iload_2 = 28;
+       public static final byte OPC_iload_3 = 29;
+       public static final byte OPC_lload_0 = 30;
+       public static final byte OPC_lload_1 = 31;
+       public static final byte OPC_lload_2 = 32;
+       public static final byte OPC_lload_3 = 33;
+       public static final byte OPC_fload_0 = 34;
+       public static final byte OPC_fload_1 = 35;
+       public static final byte OPC_fload_2 = 36;
+       public static final byte OPC_fload_3 = 37;
+       public static final byte OPC_dload_0 = 38;
+       public static final byte OPC_dload_1 = 39;
+       public static final byte OPC_dload_2 = 40;
+       public static final byte OPC_dload_3 = 41;
+       public static final byte OPC_aload_0 = 42;
+       public static final byte OPC_aload_1 = 43;
+       public static final byte OPC_aload_2 = 44;
+       public static final byte OPC_aload_3 = 45;
+       public static final byte OPC_iaload = 46;
+       public static final byte OPC_laload = 47;
+       public static final byte OPC_faload = 48;
+       public static final byte OPC_daload = 49;
+       public static final byte OPC_aaload = 50;
+       public static final byte OPC_baload = 51;
+       public static final byte OPC_caload = 52;
+       public static final byte OPC_saload = 53;
+       public static final byte OPC_istore = 54;
+       public static final byte OPC_lstore = 55;
+       public static final byte OPC_fstore = 56;
+       public static final byte OPC_dstore = 57;
+       public static final byte OPC_astore = 58;
+       public static final byte OPC_istore_0 = 59;
+       public static final byte OPC_istore_1 = 60;
+       public static final byte OPC_istore_2 = 61;
+       public static final byte OPC_istore_3 = 62;
+       public static final byte OPC_lstore_0 = 63;
+       public static final byte OPC_lstore_1 = 64;
+       public static final byte OPC_lstore_2 = 65;
+       public static final byte OPC_lstore_3 = 66;
+       public static final byte OPC_fstore_0 = 67;
+       public static final byte OPC_fstore_1 = 68;
+       public static final byte OPC_fstore_2 = 69;
+       public static final byte OPC_fstore_3 = 70;
+       public static final byte OPC_dstore_0 = 71;
+       public static final byte OPC_dstore_1 = 72;
+       public static final byte OPC_dstore_2 = 73;
+       public static final byte OPC_dstore_3 = 74;
+       public static final byte OPC_astore_0 = 75;
+       public static final byte OPC_astore_1 = 76;
+       public static final byte OPC_astore_2 = 77;
+       public static final byte OPC_astore_3 = 78;
+       public static final byte OPC_iastore = 79;
+       public static final byte OPC_lastore = 80;
+       public static final byte OPC_fastore = 81;
+       public static final byte OPC_dastore = 82;
+       public static final byte OPC_aastore = 83;
+       public static final byte OPC_bastore = 84;
+       public static final byte OPC_castore = 85;
+       public static final byte OPC_sastore = 86;
+       public static final byte OPC_pop = 87;
+       public static final byte OPC_pop2 = 88;
+       public static final byte OPC_dup = 89;
+       public static final byte OPC_dup_x1 = 90;
+       public static final byte OPC_dup_x2 = 91;
+       public static final byte OPC_dup2 = 92;
+       public static final byte OPC_dup2_x1 = 93;
+       public static final byte OPC_dup2_x2 = 94;
+       public static final byte OPC_swap = 95;
+       public static final byte OPC_iadd = 96;
+       public static final byte OPC_ladd = 97;
+       public static final byte OPC_fadd = 98;
+       public static final byte OPC_dadd = 99;
+       public static final byte OPC_isub = 100;
+       public static final byte OPC_lsub = 101;
+       public static final byte OPC_fsub = 102;
+       public static final byte OPC_dsub = 103;
+       public static final byte OPC_imul = 104;
+       public static final byte OPC_lmul = 105;
+       public static final byte OPC_fmul = 106;
+       public static final byte OPC_dmul = 107;
+       public static final byte OPC_idiv = 108;
+       public static final byte OPC_ldiv = 109;
+       public static final byte OPC_fdiv = 110;
+       public static final byte OPC_ddiv = 111;
+       public static final byte OPC_irem = 112;
+       public static final byte OPC_lrem = 113;
+       public static final byte OPC_frem = 114;
+       public static final byte OPC_drem = 115;
+       public static final byte OPC_ineg = 116;
+       public static final byte OPC_lneg = 117;
+       public static final byte OPC_fneg = 118;
+       public static final byte OPC_dneg = 119;
+       public static final byte OPC_ishl = 120;
+       public static final byte OPC_lshl = 121;
+       public static final byte OPC_ishr = 122;
+       public static final byte OPC_lshr = 123;
+       public static final byte OPC_iushr = 124;
+       public static final byte OPC_lushr = 125;
+       public static final byte OPC_iand = 126;
+       public static final byte OPC_land = 127;
+       public static final byte OPC_ior = (byte) 128;
+       public static final byte OPC_lor = (byte) 129;
+       public static final byte OPC_ixor = (byte) 130;
+       public static final byte OPC_lxor = (byte) 131;
+       public static final byte OPC_iinc = (byte) 132;
+       public static final byte OPC_i2l = (byte) 133;
+       public static final byte OPC_i2f = (byte) 134;
+       public static final byte OPC_i2d = (byte) 135;
+       public static final byte OPC_l2i = (byte) 136;
+       public static final byte OPC_l2f = (byte) 137;
+       public static final byte OPC_l2d = (byte) 138;
+       public static final byte OPC_f2i = (byte) 139;
+       public static final byte OPC_f2l = (byte) 140;
+       public static final byte OPC_f2d = (byte) 141;
+       public static final byte OPC_d2i = (byte) 142;
+       public static final byte OPC_d2l = (byte) 143;
+       public static final byte OPC_d2f = (byte) 144;
+       public static final byte OPC_i2b = (byte) 145;
+       public static final byte OPC_i2c = (byte) 146;
+       public static final byte OPC_i2s = (byte) 147;
+       public static final byte OPC_lcmp = (byte) 148;
+       public static final byte OPC_fcmpl = (byte) 149;
+       public static final byte OPC_fcmpg = (byte) 150;
+       public static final byte OPC_dcmpl = (byte) 151;
+       public static final byte OPC_dcmpg = (byte) 152;
+       public static final byte OPC_ifeq = (byte) 153;
+       public static final byte OPC_ifne = (byte) 154;
+       public static final byte OPC_iflt = (byte) 155;
+       public static final byte OPC_ifge = (byte) 156;
+       public static final byte OPC_ifgt = (byte) 157;
+       public static final byte OPC_ifle = (byte) 158;
+       public static final byte OPC_if_icmpeq = (byte) 159;
+       public static final byte OPC_if_icmpne = (byte) 160;
+       public static final byte OPC_if_icmplt = (byte) 161;
+       public static final byte OPC_if_icmpge = (byte) 162;
+       public static final byte OPC_if_icmpgt = (byte) 163;
+       public static final byte OPC_if_icmple = (byte) 164;
+       public static final byte OPC_if_acmpeq = (byte) 165;
+       public static final byte OPC_if_acmpne = (byte) 166;
+       public static final byte OPC_goto = (byte) 167;
+       public static final byte OPC_jsr = (byte) 168;
+       public static final byte OPC_ret = (byte) 169;
+       public static final byte OPC_tableswitch = (byte) 170;
+       public static final byte OPC_lookupswitch = (byte) 171;
+       public static final byte OPC_ireturn = (byte) 172;
+       public static final byte OPC_lreturn = (byte) 173;
+       public static final byte OPC_freturn = (byte) 174;
+       public static final byte OPC_dreturn = (byte) 175;
+       public static final byte OPC_areturn = (byte) 176;
+       public static final byte OPC_return = (byte) 177;
+       public static final byte OPC_getstatic = (byte) 178;
+       public static final byte OPC_putstatic = (byte) 179;
+       public static final byte OPC_getfield = (byte) 180;
+       public static final byte OPC_putfield = (byte) 181;
+       public static final byte OPC_invokevirtual = (byte) 182;
+       public static final byte OPC_invokespecial = (byte) 183;
+       public static final byte OPC_invokestatic = (byte) 184;
+       public static final byte OPC_invokeinterface = (byte) 185;
+       public static final byte OPC_new = (byte) 187;
+       public static final byte OPC_newarray = (byte) 188;
+       public static final byte OPC_anewarray = (byte) 189;
+       public static final byte OPC_arraylength = (byte) 190;
+       public static final byte OPC_athrow = (byte) 191;
+       public static final byte OPC_checkcast = (byte) 192;
+       public static final byte OPC_instanceof = (byte) 193;
+       public static final byte OPC_monitorenter = (byte) 194;
+       public static final byte OPC_monitorexit = (byte) 195;
+       public static final byte OPC_wide = (byte) 196;
+       public static final byte OPC_multianewarray = (byte) 197;
+       public static final byte OPC_ifnull = (byte) 198;
+       public static final byte OPC_ifnonnull = (byte) 199;
+       public static final byte OPC_goto_w = (byte) 200;
+       public static final byte OPC_jsr_w = (byte) 201;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java b/src/java/org/eclipse/jdt/internal/compiler/codegen/QualifiedNamesConstants.java
new file mode 100644 (file)
index 0000000..aff4cb8
--- /dev/null
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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/java/org/eclipse/jdt/internal/compiler/env/IBinaryField.java b/src/java/org/eclipse/jdt/internal/compiler/env/IBinaryField.java
new file mode 100644 (file)
index 0000000..d928f82
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.internal.compiler.impl.Constant;
+
+public interface IBinaryField extends IGenericField {
+/**
+ * 
+ * @return org.eclipse.jdt.internal.compiler.Constant
+ */
+Constant getConstant();
+/**
+ * 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.
+ *
+ * For example:
+ *   - java.lang.String is Ljava/lang/String;
+ *   - an int is I
+ *   - a 2 dimensional array of strings is [[Ljava/lang/String;
+ *   - an array of floats is [F
+ */
+
+char[] getTypeName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java b/src/java/org/eclipse/jdt/internal/compiler/env/IBinaryMethod.java
new file mode 100644 (file)
index 0000000..75435bc
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+// clinit methods (synthetics too?) can be returned from IBinaryType>>getMethods()
+// BUT do not have to be... the compiler will ignore them when building the binding.
+// The synthetic argument of a member type's constructor (ie. the first arg of a non-static
+// member type) is also ignored by the compiler, BUT in this case it must be included
+// in the constructor's signature.
+
+public interface IBinaryMethod extends IGenericMethod {
+
+/**
+ * Answer the resolved names of the exception types in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec
+ * or null if the array is empty.
+ *
+ * For example, java.lang.String is java/lang/String.
+ */
+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.
+ *
+ * For example:
+ *   - int foo(String) is (Ljava/lang/String;)I
+ *   - Object[] foo(int) is (I)[Ljava/lang/Object;
+ */
+char[] getMethodDescriptor();
+
+/**
+ * Answer whether the receiver represents a class initializer method.
+ */
+boolean isClinit();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IBinaryNestedType.java b/src/java/org/eclipse/jdt/internal/compiler/env/IBinaryNestedType.java
new file mode 100644 (file)
index 0000000..8a781dc
--- /dev/null
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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;
+
+public interface IBinaryNestedType {
+/**
+ * Answer the resolved name of the enclosing type in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec.
+ *
+ * For example, java.lang.String is java/lang/String.
+ */
+
+char[] getEnclosingTypeName();
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ */
+
+// We have added AccDeprecated & AccSynthetic.
+
+int getModifiers();
+/**
+ * Answer the resolved name of the member type in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec.
+ *
+ * For example, p1.p2.A.M is p1/p2/A$M.
+ */
+
+char[] getName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IBinaryType.java b/src/java/org/eclipse/jdt/internal/compiler/env/IBinaryType.java
new file mode 100644 (file)
index 0000000..aacda73
--- /dev/null
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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;
+
+public interface IBinaryType extends IGenericType {
+
+       char[][] NoInterface = CharOperation.NO_CHAR_CHAR;
+       IBinaryNestedType[] NoNestedType = new IBinaryNestedType[0];
+       IBinaryField[] NoField = new IBinaryField[0];
+       IBinaryMethod[] NoMethod = new IBinaryMethod[0];
+/**
+ * Answer the resolved name of the enclosing type in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec
+ * or null if the receiver is a top level type.
+ *
+ * For example, java.lang.String is java/lang/String.
+ */
+
+char[] getEnclosingTypeName();
+/**
+ * Answer the receiver's fields or null if the array is empty.
+ */
+
+IBinaryField[] getFields();
+/**
+ * Answer the resolved names of the receiver's interfaces in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec
+ * or null if the array is empty.
+ *
+ * For example, java.lang.String is java/lang/String.
+ */
+
+char[][] getInterfaceNames();
+/**
+ * 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.
+ */
+
+// NOTE: The compiler examines the nested type info & ignores the local types
+// so the local types do not have to be included.
+
+IBinaryNestedType[] getMemberTypes();
+/**
+ * Answer the receiver's methods or null if the array is empty.
+ */
+
+IBinaryMethod[] getMethods();
+/**
+ * Answer the resolved name of the type in the
+ * class file format as specified in section 4.2 of the Java 2 VM spec.
+ *
+ * For example, java.lang.String is java/lang/String.
+ */
+
+char[] getName();
+/**
+ * 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
+ * or null if it does not have one.
+ *
+ * For example, java.lang.String is java/lang/String.
+ */
+
+char[] getSuperclassName();
+
+/**
+ * Answer true if the receiver is an anonymous class.
+ * false otherwise
+ */
+boolean isAnonymous();
+
+/**
+ * Answer true if the receiver is a local class.
+ * false otherwise
+ */
+boolean isLocal();
+
+/**
+ * Answer true if the receiver is a member class.
+ * false otherwise
+ */
+boolean isMember(); 
+
+/**
+ * Answer the source file attribute, or null if none.
+ *
+ * For example, "String.java"
+ */
+
+char[] sourceFileName();
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java b/src/java/org/eclipse/jdt/internal/compiler/env/ICompilationUnit.java
new file mode 100644 (file)
index 0000000..bbcef08
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * This interface denotes a compilation unit, providing its name and content.
+ */
+public interface ICompilationUnit extends IDependent {
+/**
+ * Answer the contents of the compilation unit.
+ *
+ * In normal use, the contents are requested twice.
+ * Once during the initial lite parsing step, then again for the
+ * more detailed parsing step.
+ */
+char[] getContents();
+/**
+ * Answer the name of the top level public type.
+ * For example, {Hashtable}.
+ */
+char[] getMainTypeName();
+/**
+ * Answer the name of the package according to the directory structure
+ * or null if package consistency checks should be ignored.
+ * For example, {java, lang}.
+ */
+char[][] getPackageName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IConstants.java b/src/java/org/eclipse/jdt/internal/compiler/env/IConstants.java
new file mode 100644 (file)
index 0000000..4f3bfa1
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.env;
+
+/**
+ * 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 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;
+
+       /**
+        * Other VM flags.
+        */
+       int AccSuper = 0x0020;
+
+       /**
+        * Extra flags for types and members attributes.
+        */
+       int AccDeprecated = 0x100000;
+       
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IDependent.java b/src/java/org/eclipse/jdt/internal/compiler/env/IDependent.java
new file mode 100644 (file)
index 0000000..bf645ec
--- /dev/null
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * This represents the target file of a type dependency.
+ *
+ * All implementors of this interface are containers for types or types
+ * themselves which must be able to identify their source file name
+ * when file dependencies are collected.
+ */
+public interface IDependent {
+/**
+ * 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.&nbsp;".java")
+ *
+ * e.g.&nbsp;"c:/com/ibm/compiler/java/api/Compiler.java" 
+ */
+
+char[] getFileName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IGenericField.java b/src/java/org/eclipse/jdt/internal/compiler/env/IGenericField.java
new file mode 100644 (file)
index 0000000..35684a0
--- /dev/null
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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;
+
+public interface IGenericField {
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ */
+
+// We have added AccDeprecated & AccSynthetic.
+
+int getModifiers();
+/**
+ * Answer the name of the field.
+ */
+
+char[] getName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IGenericMethod.java b/src/java/org/eclipse/jdt/internal/compiler/env/IGenericMethod.java
new file mode 100644 (file)
index 0000000..c742d2d
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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;
+
+public interface IGenericMethod {
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ */
+// We have added AccDeprecated
+int getModifiers();
+
+/**
+ * Answer the name of the method.
+ *
+ * For a constructor, answer <init> & <clinit> for a clinit method.
+ */
+char[] getSelector();
+
+boolean isConstructor();
+
+/**
+ * Answer the names of the argument
+ * or null if the argument names are not available.
+ */
+
+char[][] getArgumentNames();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/IGenericType.java b/src/java/org/eclipse/jdt/internal/compiler/env/IGenericType.java
new file mode 100644 (file)
index 0000000..cca5c60
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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;
+
+public interface IGenericType extends IDependent {
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ */
+
+// 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
+ * or the unresolved source form of the type.
+ */
+
+boolean isBinaryType();
+boolean isClass();
+boolean isInterface();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java b/src/java/org/eclipse/jdt/internal/compiler/env/INameEnvironment.java
new file mode 100644 (file)
index 0000000..0005601
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * The name environment provides a callback API that the compiler
+ * can use to look up types, compilation units, and packages in the
+ * current environment.  The name environment is passed to the compiler
+ * on creation.
+ */
+public interface INameEnvironment {
+/**
+ * Find a type with the given compound name.
+ * Answer the binary form of the type if it is known to be consistent.
+ * Otherwise, answer the compilation unit which defines the type
+ * or null if the type does not exist.
+ * Types in the default package are specified as {{typeName}}.
+ *
+ * It is unknown whether the package containing the type actually exists.
+ *
+ * NOTE: This method can be used to find a member type using its
+ * internal name A$B, but the source file for A is answered if the binary
+ * file is inconsistent.
+ */
+
+NameEnvironmentAnswer findType(char[][] compoundTypeName);
+/**
+ * Find a type named <typeName> in the package <packageName>.
+ * Answer the binary form of the type if it is known to be consistent.
+ * Otherwise, answer the compilation unit which defines the type
+ * or null if the type does not exist.
+ * The default package is indicated by char[0][].
+ *
+ * It is known that the package containing the type exists.
+ *
+ * NOTE: This method can be used to find a member type using its
+ * internal name A$B, but the source file for A is answered if the binary
+ * file is inconsistent.
+ */
+
+NameEnvironmentAnswer findType(char[] typeName, char[][] packageName);
+/**
+ * Answer whether packageName is the name of a known subpackage inside
+ * the package parentPackageName. A top level package is found relative to null.
+ * The default package is always assumed to exist.
+ *
+ * For example:
+ *      isPackage({{java}, {awt}}, {event});
+ *      isPackage(null, {java});
+ */
+
+boolean isPackage(char[][] parentPackageName, char[] packageName);
+
+/**
+ * This method cleans the environment uo. It is responsible for releasing the memory
+ * and freeing resources. Passed that point, the name environment is no longer usable.
+ * 
+ * A name environment can have a long life cycle, therefore it is the responsibility of
+ * the code which created it to decide when it is a good time to clean it up.
+ */
+void cleanup();
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/ISourceField.java b/src/java/org/eclipse/jdt/internal/compiler/env/ISourceField.java
new file mode 100644 (file)
index 0000000..a344384
--- /dev/null
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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;
+
+public interface ISourceField extends IGenericField {
+/**
+ * Answer the source end position of the field's declaration.
+ */
+int getDeclarationSourceEnd();
+
+/**
+ * Answer the source start position of the field's declaration.
+ */
+int getDeclarationSourceStart();
+
+/**
+ * Answer the initialization source for this constant field.
+ * Answer null if the field is not a constant or if it has no initialization.
+ */
+char[] getInitializationSource();
+
+/**
+ * Answer the source end position of the field's name.
+ */
+int getNameSourceEnd();
+
+/**
+ * Answer the source start position of the field's name.
+ */
+int getNameSourceStart();
+
+/**
+ * Answer the type name of the field.
+ *
+ * The name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+char[] getTypeName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/ISourceImport.java b/src/java/org/eclipse/jdt/internal/compiler/env/ISourceImport.java
new file mode 100644 (file)
index 0000000..5bbd9bc
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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;
+
+public interface ISourceImport {
+
+/**
+ * Answer the source end position of the import declaration.
+ */
+
+int getDeclarationSourceEnd();
+/**
+ * Answer the source start position of the import declaration.
+ */
+
+int getDeclarationSourceStart();
+
+/**
+ * Answer an int whose bits are set according the access constants
+ * defined by the VM spec.
+ * Since Java 1.5, static imports can be defined.
+ */ 
+int getModifiers();
+
+/**
+ * Answer the name of the import.
+ * A name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+char[] getName();      
+
+/**
+ * Answer whether the import is on demand or not
+ * On demand import names have no trailing star
+ */
+boolean onDemand();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java b/src/java/org/eclipse/jdt/internal/compiler/env/ISourceMethod.java
new file mode 100644 (file)
index 0000000..fc08366
--- /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.env;
+
+public interface ISourceMethod extends IGenericMethod {
+
+/**
+ * Answer the unresolved names of the argument types
+ * or null if the array is empty.
+ *
+ * A name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+
+char[][] getArgumentTypeNames();
+/**
+ * Answer the source end position of the method's declaration.
+ */
+
+int getDeclarationSourceEnd();
+/**
+ * Answer the source start position of the method's declaration.
+ */
+
+int getDeclarationSourceStart();
+/**
+ * Answer the unresolved names of the exception types
+ * or null if the array is empty.
+ *
+ * A name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+
+char[][] getExceptionTypeNames();
+/**
+ * Answer the source end position of the method's selector.
+ */
+
+int getNameSourceEnd();
+/**
+ * Answer the source start position of the method's selector.
+ */
+
+int getNameSourceStart();
+/**
+ * Answer the unresolved name of the return type
+ * or null if receiver is a constructor or clinit.
+ *
+ * The name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+
+char[] getReturnTypeName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/ISourceType.java b/src/java/org/eclipse/jdt/internal/compiler/env/ISourceType.java
new file mode 100644 (file)
index 0000000..594d718
--- /dev/null
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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;
+
+public interface ISourceType extends IGenericType {
+
+/**
+ * Answer the source end position of the type's declaration.
+ */
+int getDeclarationSourceEnd();
+
+/**
+ * Answer the source start position of the type's declaration.
+ */
+int getDeclarationSourceStart();
+
+/**
+ * Answer the enclosing type
+ * or null if the receiver is a top level type.
+ */
+ISourceType getEnclosingType();
+
+/**
+ * Answer the receiver's fields or null if the array is empty.
+ *
+ * NOTE: Multiple fields with the same name can exist in the result.
+ */
+ISourceField[] getFields();
+
+/**
+ * Answer the receiver's imports or null if the array is empty.
+ *
+ * An import is a qualified, dot separated name.
+ * For example, java.util.Hashtable or java.lang.*.
+ * A static import used 'static.' as its first fragment, for
+ * example: static.java.util.Hashtable.*
+ */
+ISourceImport[] getImports();
+
+/**
+ * Answer the unresolved names of the receiver's interfaces
+ * or null if the array is empty.
+ *
+ * A name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+char[][] getInterfaceNames();
+
+/**
+ * Answer the receiver's member types
+ * or null if the array is empty.
+ */
+ISourceType[] getMemberTypes();
+
+/**
+ * Answer the receiver's methods or null if the array is empty.
+ *
+ * NOTE: Multiple methods with the same name & parameter types can exist in the result.
+ */
+ISourceMethod[] getMethods();
+
+/**
+ * Answer the simple source name of the receiver.
+ */
+char[] getName();
+
+/**
+ * Answer the source end position of the type's name.
+ */
+int getNameSourceEnd();
+
+/**
+ * Answer the source start position of the type's name.
+ */
+int getNameSourceStart();
+
+/**
+ * Answer the qualified name of the receiver's package separated by periods
+ * or null if its the default package.
+ *
+ * For example, {java.util.Hashtable}.
+ */
+char[] getPackageName();
+
+/**
+ * Answer the unresolved name of the receiver's superclass
+ * or null if it does not have one.
+ *
+ * The name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+char[] getSuperclassName();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java b/src/java/org/eclipse/jdt/internal/compiler/env/NameEnvironmentAnswer.java
new file mode 100644 (file)
index 0000000..b7ab4e6
--- /dev/null
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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;
+
+public class NameEnvironmentAnswer {
+       
+       // only one of the three can be set
+       IBinaryType binaryType;
+       ICompilationUnit compilationUnit;
+       ISourceType[] sourceTypes;
+       
+       public NameEnvironmentAnswer(IBinaryType binaryType) {
+               this.binaryType = binaryType;
+       }
+
+       public NameEnvironmentAnswer(ICompilationUnit compilationUnit) {
+               this.compilationUnit = compilationUnit;
+       }
+
+       public NameEnvironmentAnswer(ISourceType[] sourceTypes) {
+               this.sourceTypes = sourceTypes;
+       }
+
+       /**
+        * Answer the resolved binary form for the type or null if the
+        * receiver represents a compilation unit or source type.
+        */
+       public IBinaryType getBinaryType() {
+               return this.binaryType;
+       }
+
+       /**
+        * Answer the compilation unit or null if the
+        * receiver represents a binary or source type.
+        */
+       public ICompilationUnit getCompilationUnit() {
+               return this.compilationUnit;
+       }
+
+       /**
+        * Answer the unresolved source forms for the type or null if the
+        * receiver represents a compilation unit or binary type.
+        * 
+        * Multiple source forms can be answered in case the originating compilation unit did contain
+        * several type at once. Then the first type is guaranteed to be the requested type.
+        */
+       public ISourceType[] getSourceTypes() {
+               return this.sourceTypes;
+       }
+
+       /**
+        * Answer whether the receiver contains the resolved binary form of the type.
+        */
+       public boolean isBinaryType() {
+               return this.binaryType != null;
+       }
+
+       /**
+        * Answer whether the receiver contains the compilation unit which defines the type.
+        */
+       public boolean isCompilationUnit() {
+               return this.compilationUnit != null;
+       }
+
+       /**
+        * Answer whether the receiver contains the unresolved source form of the type.
+        */
+       public boolean isSourceType() {
+               return this.sourceTypes != null;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java b/src/java/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java
new file mode 100644 (file)
index 0000000..115979e
--- /dev/null
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * 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.flow;
+
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+
+/**
+ * Record conditional initialization status during definite assignment analysis
+ *
+ */
+public class ConditionalFlowInfo extends FlowInfo {
+       
+       public FlowInfo initsWhenTrue;
+       public FlowInfo initsWhenFalse;
+       
+       ConditionalFlowInfo(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){
+               
+               this.initsWhenTrue = initsWhenTrue;
+               this.initsWhenFalse = initsWhenFalse; 
+       }
+       
+       public FlowInfo addInitializationsFrom(FlowInfo otherInits) {
+               
+               this.initsWhenTrue.addInitializationsFrom(otherInits);
+               this.initsWhenFalse.addInitializationsFrom(otherInits);
+               return this;
+       }
+       
+       public FlowInfo addPotentialInitializationsFrom(FlowInfo otherInits) {
+               
+               this.initsWhenTrue.addPotentialInitializationsFrom(otherInits);
+               this.initsWhenFalse.addPotentialInitializationsFrom(otherInits);
+               return this;
+       }
+       
+       public FlowInfo asNegatedCondition() {
+               
+               FlowInfo extra = initsWhenTrue;
+               initsWhenTrue = initsWhenFalse;
+               initsWhenFalse = extra;
+               return this;
+       }
+
+       public FlowInfo copy() {
+               
+               return new ConditionalFlowInfo(initsWhenTrue.copy(), initsWhenFalse.copy());
+       }
+       
+       public FlowInfo initsWhenFalse() {
+               
+               return initsWhenFalse;
+       }
+       
+       public FlowInfo initsWhenTrue() {
+               
+               return initsWhenTrue;
+       }
+       
+       /**
+        * Check status of definite assignment for a field.
+        */
+       public boolean isDefinitelyAssigned(FieldBinding field) {
+               
+               return initsWhenTrue.isDefinitelyAssigned(field) 
+                               && initsWhenFalse.isDefinitelyAssigned(field);
+       }
+       
+       /**
+        * Check status of definite assignment for a local variable.
+        */
+       public boolean isDefinitelyAssigned(LocalVariableBinding local) {
+               
+               return initsWhenTrue.isDefinitelyAssigned(local) 
+                               && initsWhenFalse.isDefinitelyAssigned(local);
+       }
+       
+       public int reachMode(){
+               return unconditionalInits().reachMode();
+       }
+       
+       public boolean isReachable(){
+               
+               return unconditionalInits().isReachable();      
+               //should maybe directly be: false
+       }
+       
+       /**
+        * Check status of potential assignment for a field.
+        */
+       public boolean isPotentiallyAssigned(FieldBinding field) {
+               
+               return initsWhenTrue.isPotentiallyAssigned(field) 
+                               || initsWhenFalse.isPotentiallyAssigned(field);
+       }
+       
+       /**
+        * Check status of potential assignment for a local variable.
+        */
+       public boolean isPotentiallyAssigned(LocalVariableBinding local) {
+               
+               return initsWhenTrue.isPotentiallyAssigned(local) 
+                               || initsWhenFalse.isPotentiallyAssigned(local);
+       }
+       
+       /**
+        * Record a field got definitely assigned.
+        */
+       public void markAsDefinitelyAssigned(FieldBinding field) {
+               
+               initsWhenTrue.markAsDefinitelyAssigned(field);
+               initsWhenFalse.markAsDefinitelyAssigned(field); 
+       }
+       
+       /**
+        * Record a field got definitely assigned.
+        */
+       public void markAsDefinitelyAssigned(LocalVariableBinding local) {
+               
+               initsWhenTrue.markAsDefinitelyAssigned(local);
+               initsWhenFalse.markAsDefinitelyAssigned(local); 
+       }
+       
+       /**
+        * Clear the initialization info for a field
+        */
+       public void markAsDefinitelyNotAssigned(FieldBinding field) {
+               
+               initsWhenTrue.markAsDefinitelyNotAssigned(field);
+               initsWhenFalse.markAsDefinitelyNotAssigned(field);      
+       }
+       
+       /**
+        * Clear the initialization info for a local variable
+        */
+       public void markAsDefinitelyNotAssigned(LocalVariableBinding local) {
+               
+               initsWhenTrue.markAsDefinitelyNotAssigned(local);
+               initsWhenFalse.markAsDefinitelyNotAssigned(local);      
+       }
+       
+       public FlowInfo setReachMode(int reachMode) {
+               
+               initsWhenTrue.setReachMode(reachMode);
+               initsWhenFalse.setReachMode(reachMode);
+               return this;
+       }
+       
+       /**
+        * Converts conditional receiver into inconditional one, updated in the following way: <ul>
+        * <li> intersection of definitely assigned variables, 
+        * <li> union of potentially assigned variables.
+        * </ul>
+        */
+       public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
+               
+               return unconditionalInits().mergedWith(otherInits);
+       }
+       
+       public String toString() {
+               
+               return "FlowInfo<true: " + initsWhenTrue.toString() + ", false: " + initsWhenFalse.toString() + ">"; //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
+       }
+       
+       public UnconditionalFlowInfo unconditionalInits() {
+               
+               return initsWhenTrue.unconditionalInits().copy()
+                               .mergedWith(initsWhenFalse.unconditionalInits());
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
new file mode 100644 (file)
index 0000000..4862742
--- /dev/null
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * 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.flow;
+
+import java.util.ArrayList;
+
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.TryStatement;
+import org.eclipse.jdt.internal.compiler.codegen.ObjectCache;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class ExceptionHandlingFlowContext extends FlowContext {
+       
+       public ReferenceBinding[] handledExceptions;
+       
+       public final static int BitCacheSize = 32; // 32 bits per int
+       int[] isReached;
+       int[] isNeeded;
+       UnconditionalFlowInfo[] initsOnExceptions;
+       ObjectCache indexes = new ObjectCache();
+       boolean isMethodContext;
+
+       public UnconditionalFlowInfo initsOnReturn;
+
+       // for dealing with anonymous constructor thrown exceptions
+       public ArrayList extendedExceptions;
+       
+       public ExceptionHandlingFlowContext(
+               FlowContext parent,
+               ASTNode associatedNode,
+               ReferenceBinding[] handledExceptions,
+               BlockScope scope,
+               UnconditionalFlowInfo flowInfo) {
+
+               super(parent, associatedNode);
+               isMethodContext = scope == scope.methodScope();
+               this.handledExceptions = handledExceptions;
+               int count = handledExceptions.length, cacheSize = (count / BitCacheSize) + 1;
+               this.isReached = new int[cacheSize]; // none is reached by default
+               this.isNeeded = new int[cacheSize]; // none is needed by default
+               this.initsOnExceptions = new UnconditionalFlowInfo[count];
+               for (int i = 0; i < count; i++) {
+                       this.indexes.put(handledExceptions[i], i); // key type  -> value index
+                       boolean isUnchecked =
+                               (scope.compareUncheckedException(handledExceptions[i]) != NotRelated);
+                       int cacheIndex = i / BitCacheSize, bitMask = 1 << (i % BitCacheSize);
+                       if (isUnchecked) {
+                               isReached[cacheIndex] |= bitMask;
+                               this.initsOnExceptions[i] = flowInfo.copy().unconditionalInits();
+                       } else {
+                               this.initsOnExceptions[i] = FlowInfo.DEAD_END;
+                       }
+               }
+               System.arraycopy(this.isReached, 0, this.isNeeded, 0, cacheSize);
+               this.initsOnReturn = FlowInfo.DEAD_END; 
+       }
+
+       public void complainIfUnusedExceptionHandlers(AbstractMethodDeclaration method) {
+               MethodScope scope = method.scope;
+               // can optionally skip overriding methods
+               if ((method.binding.modifiers & (CompilerModifiers.AccOverriding | CompilerModifiers.AccImplementing)) != 0
+                       && !scope.environment().options.reportUnusedDeclaredThrownExceptionWhenOverriding) {
+                   return;
+               }
+                   
+               // report errors for unreachable exception handlers
+               for (int i = 0, count = handledExceptions.length; i < count; i++) {
+                       int index = indexes.get(handledExceptions[i]);
+                       int cacheIndex = index / BitCacheSize;
+                       int bitMask = 1 << (index % BitCacheSize);
+                       if ((isReached[cacheIndex] & bitMask) == 0) {
+                               scope.problemReporter().unusedDeclaredThrownException(
+                                       handledExceptions[index],
+                                       method,
+                                       method.thrownExceptions[index]);
+                       }
+               }
+       }
+       
+       public void complainIfUnusedExceptionHandlers(
+               BlockScope scope,
+               TryStatement tryStatement) {
+               // report errors for unreachable exception handlers
+               for (int i = 0, count = handledExceptions.length; i < count; i++) {
+                       int index = indexes.get(handledExceptions[i]);
+                       int cacheIndex = index / BitCacheSize;
+                       int bitMask = 1 << (index % BitCacheSize);
+                       if ((isReached[cacheIndex] & bitMask) == 0) {
+                               scope.problemReporter().unreachableCatchBlock(
+                                       handledExceptions[index],
+                                       tryStatement.catchArguments[index].type);
+                       } else {
+                               if ((isNeeded[cacheIndex] & bitMask) == 0) {
+                                       scope.problemReporter().hiddenCatchBlock(
+                                               handledExceptions[index],
+                                               tryStatement.catchArguments[index].type);
+                               }
+                       }
+               }
+       }
+
+       public String individualToString() {
+               
+               StringBuffer buffer = new StringBuffer("Exception flow context"); //$NON-NLS-1$
+               int length = handledExceptions.length;
+               for (int i = 0; i < length; i++) {
+                       int cacheIndex = i / BitCacheSize;
+                       int bitMask = 1 << (i % BitCacheSize);
+                       buffer.append('[').append(handledExceptions[i].readableName());
+                       if ((isReached[cacheIndex] & bitMask) != 0) {
+                               if ((isNeeded[cacheIndex] & bitMask) == 0) {
+                                       buffer.append("-masked"); //$NON-NLS-1$
+                               } else {
+                                       buffer.append("-reached"); //$NON-NLS-1$
+                               }
+                       } else {
+                               buffer.append("-not reached"); //$NON-NLS-1$
+                       }
+                       buffer.append('-').append(initsOnExceptions[i].toString()).append(']');
+               }
+               buffer.append("[initsOnReturn -").append(initsOnReturn.toString()).append(']'); //$NON-NLS-1$
+               return buffer.toString();
+       }
+
+       public UnconditionalFlowInfo initsOnException(ReferenceBinding exceptionType) {
+               
+               int index;
+               if ((index = indexes.get(exceptionType)) < 0) {
+                       return FlowInfo.DEAD_END;
+               }
+               return initsOnExceptions[index];
+       }
+
+       public UnconditionalFlowInfo initsOnReturn(){
+               return this.initsOnReturn;
+       }
+       
+       public void recordHandlingException(
+               ReferenceBinding exceptionType,
+               UnconditionalFlowInfo flowInfo,
+               TypeBinding raisedException,
+               ASTNode invocationSite,
+               boolean wasAlreadyDefinitelyCaught) {
+                       
+               int index = indexes.get(exceptionType);
+               // if already flagged as being reached (unchecked exception handler)
+               int cacheIndex = index / BitCacheSize;
+               int bitMask = 1 << (index % BitCacheSize);
+               if (!wasAlreadyDefinitelyCaught) {
+                       this.isNeeded[cacheIndex] |= bitMask;
+               }
+               this.isReached[cacheIndex] |= bitMask;
+               
+               initsOnExceptions[index] =
+                       initsOnExceptions[index] == FlowInfo.DEAD_END
+                               ? flowInfo.copy().unconditionalInits()
+                               : initsOnExceptions[index].mergedWith(flowInfo.copy().unconditionalInits());
+       }
+       
+       public void recordReturnFrom(FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return; 
+               if (initsOnReturn == FlowInfo.DEAD_END) {
+                       initsOnReturn = flowInfo.copy().unconditionalInits();
+               } else {
+                       initsOnReturn = initsOnReturn.mergedWith(flowInfo.copy().unconditionalInits());
+               }
+       }
+       
+       /*
+        * Compute a merged list of unhandled exception types (keeping only the most generic ones).
+        * This is necessary to add synthetic thrown exceptions for anonymous type constructors (JLS 8.6).
+        */
+       public void mergeUnhandledException(TypeBinding newException){
+               
+               if (this.extendedExceptions == null){
+                       this.extendedExceptions = new ArrayList(5);
+                       for (int i = 0; i < this.handledExceptions.length; i++){
+                               this.extendedExceptions.add(this.handledExceptions[i]);
+                       }
+               }
+               
+               boolean isRedundant = false;
+               
+               for(int i = this.extendedExceptions.size()-1; i >= 0; i--){
+                       switch(Scope.compareTypes(newException, (TypeBinding)this.extendedExceptions.get(i))){
+                               case MoreGeneric :
+                                       this.extendedExceptions.remove(i);
+                                       break;
+                               case EqualOrMoreSpecific :
+                                       isRedundant = true;
+                                       break;
+                               case NotRelated :
+                                       break;
+                       }
+               }
+               if (!isRedundant){
+                       this.extendedExceptions.add(newException);
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/FinallyFlowContext.java
new file mode 100644 (file)
index 0000000..d17ab89
--- /dev/null
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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.flow;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Reference;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class FinallyFlowContext extends FlowContext {
+       
+       Reference finalAssignments[];
+       VariableBinding finalVariables[];
+       int assignCount;
+       
+       public FinallyFlowContext(FlowContext parent, ASTNode associatedNode) {
+               super(parent, associatedNode);
+       }
+
+       /**
+        * Given some contextual initialization info (derived from a try block or a catch block), this 
+        * code will check that the subroutine context does not also initialize a final variable potentially set
+        * redundantly.
+        */
+       public void complainOnRedundantFinalAssignments(
+               FlowInfo flowInfo,
+               BlockScope scope) {
+               for (int i = 0; i < assignCount; i++) {
+                       VariableBinding variable = finalVariables[i];
+                       if (variable == null) continue;
+                       
+                       boolean complained = false; // remember if have complained on this final assignment
+                       if (variable instanceof FieldBinding) {
+                               // final field
+                               if (flowInfo.isPotentiallyAssigned((FieldBinding)variable)) {
+                                       complained = true;
+                                       scope.problemReporter().duplicateInitializationOfBlankFinalField((FieldBinding)variable, finalAssignments[i]);
+                               }
+                       } else {
+                               // final local variable
+                               if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
+                                       complained = true;
+                                       scope.problemReporter().duplicateInitializationOfFinalLocal(
+                                               (LocalVariableBinding) variable,
+                                               finalAssignments[i]);
+                               }
+                       }
+                       // any reference reported at this level is removed from the parent context 
+                       // where it could also be reported again
+                       if (complained) {
+                               FlowContext currentContext = parent;
+                               while (currentContext != null) {
+                                       //if (currentContext.isSubRoutine()) {
+                                       currentContext.removeFinalAssignmentIfAny(finalAssignments[i]);
+                                       //}
+                                       currentContext = currentContext.parent;
+                               }
+                       }
+               }
+       }
+
+       public String individualToString() {
+               
+               StringBuffer buffer = new StringBuffer("Finally flow context"); //$NON-NLS-1$
+               buffer.append("[finalAssignments count -").append(assignCount).append(']'); //$NON-NLS-1$
+               return buffer.toString();
+       }
+       
+       public boolean isSubRoutine() {
+               return true;
+       }
+
+       boolean recordFinalAssignment(
+               VariableBinding binding,
+               Reference finalAssignment) {
+               if (assignCount == 0) {
+                       finalAssignments = new Reference[5];
+                       finalVariables = new VariableBinding[5];
+               } else {
+                       if (assignCount == finalAssignments.length)
+                               System.arraycopy(
+                                       finalAssignments,
+                                       0,
+                                       (finalAssignments = new Reference[assignCount * 2]),
+                                       0,
+                                       assignCount);
+                       System.arraycopy(
+                               finalVariables,
+                               0,
+                               (finalVariables = new VariableBinding[assignCount * 2]),
+                               0,
+                               assignCount);
+               }
+               finalAssignments[assignCount] = finalAssignment;
+               finalVariables[assignCount++] = binding;
+               return true;
+       }
+
+       void removeFinalAssignmentIfAny(Reference reference) {
+               for (int i = 0; i < assignCount; i++) {
+                       if (finalAssignments[i] == reference) {
+                               finalAssignments[i] = null;
+                               finalVariables[i] = null;
+                               return;
+                       }
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/FlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/FlowContext.java
new file mode 100644 (file)
index 0000000..340781f
--- /dev/null
@@ -0,0 +1,493 @@
+/*******************************************************************************
+ * 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.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.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.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class FlowContext implements TypeConstants {
+       
+       public ASTNode associatedNode;
+       public FlowContext parent;
+
+       public final static FlowContext NotContinuableContext = new FlowContext(null, null);
+               
+       public FlowContext(FlowContext parent, ASTNode associatedNode) {
+
+               this.parent = parent;
+               this.associatedNode = associatedNode;
+       }
+       
+       public Label breakLabel() {
+
+               return null;
+       }
+       
+       public void checkExceptionHandlers(
+               TypeBinding[] raisedExceptions,
+               ASTNode location,
+               FlowInfo flowInfo,
+               BlockScope scope) {
+
+               // check that all the argument exception types are handled
+               // JDK Compatible implementation - when an exception type is thrown, 
+               // all related catch blocks are marked as reachable... instead of those only
+               // until the point where it is safely handled (Smarter - see comment at the end)
+               int remainingCount; // counting the number of remaining unhandled exceptions
+               int raisedCount; // total number of exceptions raised
+               if ((raisedExceptions == null)
+                       || ((raisedCount = raisedExceptions.length) == 0))
+                       return;
+               remainingCount = raisedCount;
+
+               // duplicate the array of raised exceptions since it will be updated
+               // (null replaces any handled exception)
+               System.arraycopy(
+                       raisedExceptions,
+                       0,
+                       (raisedExceptions = new TypeBinding[raisedCount]),
+                       0,
+                       raisedCount);
+               FlowContext traversedContext = this;
+
+               while (traversedContext != null) {
+                       SubRoutineStatement sub;
+                       if (((sub = traversedContext.subRoutine()) != null) && sub.isSubRoutineEscaping()) {
+                               // traversing a non-returning subroutine means that all unhandled 
+                               // exceptions will actually never get sent...
+                               return;
+                       }
+                       // filter exceptions that are locally caught from the innermost enclosing 
+                       // try statement to the outermost ones.
+                       if (traversedContext instanceof ExceptionHandlingFlowContext) {
+                               ExceptionHandlingFlowContext exceptionContext =
+                                       (ExceptionHandlingFlowContext) traversedContext;
+                               ReferenceBinding[] caughtExceptions;
+                               if ((caughtExceptions = exceptionContext.handledExceptions) != NoExceptions) {
+                                       int caughtCount = caughtExceptions.length;
+                                       boolean[] locallyCaught = new boolean[raisedCount]; // at most
+
+                                       for (int caughtIndex = 0; caughtIndex < caughtCount; caughtIndex++) {
+                                               ReferenceBinding caughtException = caughtExceptions[caughtIndex];
+                                               for (int raisedIndex = 0; raisedIndex < raisedCount; raisedIndex++) {
+                                                       TypeBinding raisedException;
+                                                       if ((raisedException = raisedExceptions[raisedIndex]) != null) {
+                                                           int state = caughtException == null 
+                                                               ? EqualOrMoreSpecific /* any exception */
+                                                               : Scope.compareTypes(raisedException, caughtException);
+                                                               switch (state) {
+                                                                       case EqualOrMoreSpecific :
+                                                                               exceptionContext.recordHandlingException(
+                                                                                       caughtException,
+                                                                                       flowInfo.unconditionalInits(),
+                                                                                       raisedException,
+                                                                                       location,
+                                                                                       locallyCaught[raisedIndex]);
+                                                                               // was already definitely caught ?
+                                                                               if (!locallyCaught[raisedIndex]) {
+                                                                                       locallyCaught[raisedIndex] = true;
+                                                                                       // remember that this exception has been definitely caught
+                                                                                       remainingCount--;
+                                                                               }
+                                                                               break;
+                                                                       case MoreGeneric :
+                                                                               exceptionContext.recordHandlingException(
+                                                                                       caughtException,
+                                                                                       flowInfo.unconditionalInits(),
+                                                                                       raisedException,
+                                                                                       location,
+                                                                                       false);
+                                                                               // was not caught already per construction
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       // remove locally caught exceptions from the remaining ones
+                                       for (int i = 0; i < raisedCount; i++) {
+                                               if (locallyCaught[i]) {
+                                                       raisedExceptions[i] = null; // removed from the remaining ones.
+                                               }
+                                       }
+                               }
+                               // method treatment for unchecked exceptions
+                               if (exceptionContext.isMethodContext) {
+                                       for (int i = 0; i < raisedCount; i++) {
+                                               TypeBinding raisedException;
+                                               if ((raisedException = raisedExceptions[i]) != null) {
+                                                       if (raisedException.isCompatibleWith(scope.getJavaLangRuntimeException())
+                                                               || raisedException.isCompatibleWith(scope.getJavaLangError())) {
+                                                               remainingCount--;
+                                                               raisedExceptions[i] = null;
+                                                       }
+                                               }
+                                       }
+                                       // anonymous constructors are allowed to throw any exceptions (their thrown exceptions
+                                       // clause will be fixed up later as per JLS 8.6).
+                                       if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration){
+                                               AbstractMethodDeclaration method = (AbstractMethodDeclaration)exceptionContext.associatedNode;
+                                               if (method.isConstructor() && method.binding.declaringClass.isAnonymousType()){
+                                                               
+                                                       for (int i = 0; i < raisedCount; i++) {
+                                                               TypeBinding raisedException;
+                                                               if ((raisedException = raisedExceptions[i]) != null) {
+                                                                       exceptionContext.mergeUnhandledException(raisedException);
+                                                               }
+                                                       }
+                                                       return; // no need to complain, will fix up constructor exceptions                                              
+                                               }
+                                       }
+                                       break; // not handled anywhere, thus jump to error handling
+                               }
+                       }
+                       if (remainingCount == 0)
+                               return;
+                               
+                       traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+                       if (traversedContext.associatedNode instanceof TryStatement){
+                               flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits);
+                       }
+                       traversedContext = traversedContext.parent;
+               }
+               // if reaches this point, then there are some remaining unhandled exception types.      
+               nextReport: for (int i = 0; i < raisedCount; i++) {
+                       TypeBinding exception;
+                       if ((exception = raisedExceptions[i]) != null) {
+                               // only one complaint if same exception declared to be thrown more than once
+                               for (int j = 0; j < i; j++) {
+                                       if (raisedExceptions[j] == exception) continue nextReport; // already reported 
+                               }
+                               scope.problemReporter().unhandledException(exception, location);
+                       }
+               }
+       }
+
+       public void checkExceptionHandlers(
+               TypeBinding raisedException,
+               ASTNode location,
+               FlowInfo flowInfo,
+               BlockScope scope) {
+
+               // LIGHT-VERSION OF THE EQUIVALENT WITH AN ARRAY OF EXCEPTIONS
+               // check that all the argument exception types are handled
+               // JDK Compatible implementation - when an exception type is thrown, 
+               // all related catch blocks are marked as reachable... instead of those only
+               // until the point where it is safely handled (Smarter - see comment at the end)
+               FlowContext traversedContext = this;
+               while (traversedContext != null) {
+                       SubRoutineStatement sub;
+                       if (((sub = traversedContext.subRoutine()) != null) && sub.isSubRoutineEscaping()) {
+                               // traversing a non-returning subroutine means that all unhandled 
+                               // exceptions will actually never get sent...
+                               return;
+                       }
+                       
+                       // filter exceptions that are locally caught from the innermost enclosing 
+                       // try statement to the outermost ones.
+                       if (traversedContext instanceof ExceptionHandlingFlowContext) {
+                               ExceptionHandlingFlowContext exceptionContext =
+                                       (ExceptionHandlingFlowContext) traversedContext;
+                               ReferenceBinding[] caughtExceptions;
+                               if ((caughtExceptions = exceptionContext.handledExceptions) != NoExceptions) {
+                                       boolean definitelyCaught = false;
+                                       for (int caughtIndex = 0, caughtCount = caughtExceptions.length;
+                                               caughtIndex < caughtCount;
+                                               caughtIndex++) {
+                                               ReferenceBinding caughtException = caughtExceptions[caughtIndex];
+                                           int state = caughtException == null 
+                                               ? EqualOrMoreSpecific /* any exception */
+                                               : Scope.compareTypes(raisedException, caughtException);                                         
+                                               switch (state) {
+                                                       case EqualOrMoreSpecific :
+                                                               exceptionContext.recordHandlingException(
+                                                                       caughtException,
+                                                                       flowInfo.unconditionalInits(),
+                                                                       raisedException,
+                                                                       location,
+                                                                       definitelyCaught);
+                                                               // was it already definitely caught ?
+                                                               definitelyCaught = true;
+                                                               break;
+                                                       case MoreGeneric :
+                                                               exceptionContext.recordHandlingException(
+                                                                       caughtException,
+                                                                       flowInfo.unconditionalInits(),
+                                                                       raisedException,
+                                                                       location,
+                                                                       false);
+                                                               // was not caught already per construction
+                                               }
+                                       }
+                                       if (definitelyCaught)
+                                               return;
+                               }
+                               // method treatment for unchecked exceptions
+                               if (exceptionContext.isMethodContext) {
+                                       if (raisedException.isCompatibleWith(scope.getJavaLangRuntimeException())
+                                               || raisedException.isCompatibleWith(scope.getJavaLangError()))
+                                               return;
+                                               
+                                       // anonymous constructors are allowed to throw any exceptions (their thrown exceptions
+                                       // clause will be fixed up later as per JLS 8.6).
+                                       if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration){
+                                               AbstractMethodDeclaration method = (AbstractMethodDeclaration)exceptionContext.associatedNode;
+                                               if (method.isConstructor() && method.binding.declaringClass.isAnonymousType()){
+                                                                       
+                                                       exceptionContext.mergeUnhandledException(raisedException);
+                                                       return; // no need to complain, will fix up constructor exceptions                                              
+                                               }
+                                       }
+                                       break; // not handled anywhere, thus jump to error handling
+                               }
+                       }
+
+                       traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+                       if (traversedContext.associatedNode instanceof TryStatement){
+                               flowInfo = flowInfo.copy().addInitializationsFrom(((TryStatement) traversedContext.associatedNode).subRoutineInits);
+                       }
+                       traversedContext = traversedContext.parent;
+               }
+               // if reaches this point, then there are some remaining unhandled exception types.
+               scope.problemReporter().unhandledException(raisedException, location);
+       }
+
+       public Label continueLabel() {
+
+               return null;
+       }
+
+       /*
+        * lookup through break labels
+        */
+       public FlowContext getTargetContextForBreakLabel(char[] labelName) {
+
+               FlowContext current = this, lastNonReturningSubRoutine = null;
+               while (current != null) {
+                       if (current.isNonReturningContext()) {
+                               lastNonReturningSubRoutine = current;
+                       }
+                       char[] currentLabelName;
+                       if (((currentLabelName = current.labelName()) != null)
+                               && CharOperation.equals(currentLabelName, labelName)) {
+                               if (lastNonReturningSubRoutine == null)
+                                       return current;
+                               return lastNonReturningSubRoutine;
+                       }
+                       current = current.parent;
+               }
+               // not found
+               return null;
+       }
+
+       /*
+        * lookup through continue labels
+        */
+       public FlowContext getTargetContextForContinueLabel(char[] labelName) {
+
+               FlowContext current = this;
+               FlowContext lastContinuable = null;
+               FlowContext lastNonReturningSubRoutine = null;
+
+               while (current != null) {
+                       if (current.isNonReturningContext()) {
+                               lastNonReturningSubRoutine = current;
+                       } else {
+                               if (current.isContinuable()) {
+                                       lastContinuable = current;
+                               }
+                       }
+                       
+                       char[] currentLabelName;
+                       if ((currentLabelName = current.labelName()) != null && CharOperation.equals(currentLabelName, labelName)) {
+
+                               // matching label found                                 
+                               if ((lastContinuable != null)
+                                               && (current.associatedNode.concreteStatement()  == lastContinuable.associatedNode)) {
+                                   
+                                       if (lastNonReturningSubRoutine == null) return lastContinuable;
+                                       return lastNonReturningSubRoutine;
+                               } 
+                               // label is found, but not a continuable location
+                               return NotContinuableContext;
+                       }
+                       current = current.parent;
+               }
+               // not found
+               return null;
+       }
+
+       /*
+        * lookup a default break through breakable locations
+        */
+       public FlowContext getTargetContextForDefaultBreak() {
+
+               FlowContext current = this, lastNonReturningSubRoutine = null;
+               while (current != null) {
+                       if (current.isNonReturningContext()) {
+                               lastNonReturningSubRoutine = current;
+                       }
+                       if (current.isBreakable() && current.labelName() == null) {
+                               if (lastNonReturningSubRoutine == null) return current;
+                               return lastNonReturningSubRoutine;
+                       }
+                       current = current.parent;
+               }
+               // not found
+               return null;
+       }
+
+       /*
+        * lookup a default continue amongst continuable locations
+        */
+       public FlowContext getTargetContextForDefaultContinue() {
+
+               FlowContext current = this, lastNonReturningSubRoutine = null;
+               while (current != null) {
+                       if (current.isNonReturningContext()) {
+                               lastNonReturningSubRoutine = current;
+                       }
+                       if (current.isContinuable()) {
+                               if (lastNonReturningSubRoutine == null)
+                                       return current;
+                               return lastNonReturningSubRoutine;
+                       }
+                       current = current.parent;
+               }
+               // not found
+               return null;
+       }
+
+       public String individualToString() {
+
+               return "Flow context"; //$NON-NLS-1$
+       }
+
+       public FlowInfo initsOnBreak() {
+
+               return FlowInfo.DEAD_END;
+       }
+
+       public UnconditionalFlowInfo initsOnReturn() {
+
+               return FlowInfo.DEAD_END;
+       }
+
+       public boolean isBreakable() {
+
+               return false;
+       }
+
+       public boolean isContinuable() {
+
+               return false;
+       }
+
+       public boolean isNonReturningContext() {
+
+               return false;
+       }
+
+       public boolean isSubRoutine() {
+
+               return false;
+       }
+
+       public char[] labelName() {
+
+               return null;
+       }
+
+       public void recordBreakFrom(FlowInfo flowInfo) {
+               // default implementation: do nothing
+       }
+
+       public void recordContinueFrom(FlowInfo flowInfo) {
+               // default implementation: do nothing
+       }
+
+       boolean recordFinalAssignment(
+               VariableBinding variable,
+               Reference finalReference) {
+
+               return true; // keep going
+       }
+
+       public void recordReturnFrom(FlowInfo flowInfo) {
+               // default implementation: do nothing
+       }
+
+       public void recordSettingFinal(
+               VariableBinding variable,
+               Reference finalReference,
+               FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+
+               // for initialization inside looping statement that effectively loops
+               FlowContext context = this;
+               while (context != null) {
+                       if (!context.recordFinalAssignment(variable, finalReference)) {
+                               break; // no need to keep going
+                       }
+                       context = context.parent;
+               }
+       }
+
+       void removeFinalAssignmentIfAny(Reference reference) {
+               // default implementation: do nothing
+       }
+
+       public SubRoutineStatement subRoutine() {
+
+               return null;
+       }
+
+       public String toString() {
+
+               StringBuffer buffer = new StringBuffer();
+               FlowContext current = this;
+               int parentsCount = 0;
+               while ((current = current.parent) != null) {
+                       parentsCount++;
+               }
+               FlowContext[] parents = new FlowContext[parentsCount + 1];
+               current = this;
+               int index = parentsCount;
+               while (index >= 0) {
+                       parents[index--] = current;
+                       current = current.parent;
+               }
+               for (int i = 0; i < parentsCount; i++) {
+                       for (int j = 0; j < i; j++)
+                               buffer.append('\t');
+                       buffer.append(parents[i].individualToString()).append('\n');
+               }
+               buffer.append('*');
+               for (int j = 0; j < parentsCount + 1; j++)
+                       buffer.append('\t');
+               buffer.append(individualToString()).append('\n');
+               return buffer.toString();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/src/java/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
new file mode 100644 (file)
index 0000000..1736a5c
--- /dev/null
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * 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.flow;
+
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+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 static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
+       static {
+               DEAD_END = new UnconditionalFlowInfo();
+               DEAD_END.reachMode = UNREACHABLE;
+       }
+       abstract public FlowInfo addInitializationsFrom(FlowInfo otherInits);
+
+       abstract public FlowInfo addPotentialInitializationsFrom(FlowInfo otherInits);
+
+       public FlowInfo asNegatedCondition() {
+
+               return this;
+       }
+
+       public static FlowInfo conditional(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){
+
+               // if (initsWhenTrue.equals(initsWhenFalse)) return initsWhenTrue; -- could optimize if #equals is defined
+               return new ConditionalFlowInfo(initsWhenTrue, initsWhenFalse);
+       }
+
+       abstract public FlowInfo copy();
+
+       public static UnconditionalFlowInfo initial(int maxFieldCount) {
+               UnconditionalFlowInfo info = new UnconditionalFlowInfo();
+               info.maxFieldCount = maxFieldCount;
+               return info;
+       }
+
+       abstract public FlowInfo initsWhenFalse();
+
+       abstract public FlowInfo initsWhenTrue();
+
+       /**
+        * Check status of definite assignment for a field.
+        */
+        abstract public boolean isDefinitelyAssigned(FieldBinding field);   
+
+       /**
+        * Check status of definite assignment for a local.
+        */
+       public abstract boolean isDefinitelyAssigned(LocalVariableBinding local);
+
+       //abstract public int reachMode(); 
+
+       /**
+        * Check status of potential assignment for a field.
+        */
+        abstract public boolean isPotentiallyAssigned(FieldBinding field);   
+
+       /**
+        * Check status of potential assignment for a local variable.
+        */
+
+        abstract public boolean isPotentiallyAssigned(LocalVariableBinding field);   
+
+       abstract public boolean isReachable();
+       
+       /**
+        * Record a field got definitely assigned.
+        */
+       abstract public void markAsDefinitelyAssigned(FieldBinding field);
+
+       /**
+        * Record a local got definitely assigned.
+        */
+       abstract public void markAsDefinitelyAssigned(LocalVariableBinding local);
+
+       /**
+        * Clear the initialization info for a field
+        */
+       abstract public void markAsDefinitelyNotAssigned(FieldBinding field);
+
+       /**
+        * Clear the initialization info for a local variable
+        */
+       abstract public void markAsDefinitelyNotAssigned(LocalVariableBinding local);
+
+       /**
+        * Merge branches using optimized boolean conditions
+        */
+       public static FlowInfo mergedOptimizedBranches(FlowInfo initsWhenTrue, boolean isOptimizedTrue, FlowInfo initsWhenFalse, boolean isOptimizedFalse, boolean allowFakeDeadBranch) {
+               FlowInfo mergedInfo;
+               if (isOptimizedTrue){
+                       if (initsWhenTrue == FlowInfo.DEAD_END && allowFakeDeadBranch) {
+                               mergedInfo = initsWhenFalse.setReachMode(FlowInfo.UNREACHABLE);
+                       } else {
+                               mergedInfo = initsWhenTrue.addPotentialInitializationsFrom(initsWhenFalse);
+                       }
+
+               } else if (isOptimizedFalse) {
+                       if (initsWhenFalse == FlowInfo.DEAD_END && allowFakeDeadBranch) {
+                               mergedInfo = initsWhenTrue.setReachMode(FlowInfo.UNREACHABLE);
+                       } else {
+                               mergedInfo = initsWhenFalse.addPotentialInitializationsFrom(initsWhenTrue);
+                       }
+
+               } else {
+                       mergedInfo = initsWhenTrue.unconditionalInits().mergedWith(initsWhenFalse.unconditionalInits());
+               }
+               return mergedInfo;
+       }
+       
+       abstract public int reachMode();
+
+       abstract public FlowInfo setReachMode(int reachMode);
+
+       /**
+        * Returns the receiver updated in the following way: <ul>
+        * <li> intersection of definitely assigned variables, 
+        * <li> union of potentially assigned variables.
+        * </ul>
+        */
+       abstract public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits);
+
+       public String toString(){
+
+               if (this == DEAD_END){
+                       return "FlowInfo.DEAD_END"; //$NON-NLS-1$
+               }
+               return super.toString();
+       }
+
+       abstract public UnconditionalFlowInfo unconditionalInits();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/InitializationFlowContext.java
new file mode 100644 (file)
index 0000000..e609ae1
--- /dev/null
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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.flow;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class InitializationFlowContext extends ExceptionHandlingFlowContext {
+
+       public int exceptionCount;
+       public TypeBinding[] thrownExceptions = new TypeBinding[5];
+       public ASTNode[] exceptionThrowers = new ASTNode[5];
+       public FlowInfo[] exceptionThrowerFlowInfos = new FlowInfo[5];
+       
+       public InitializationFlowContext(
+               FlowContext parent,
+               ASTNode associatedNode,
+               BlockScope scope) {
+               super(
+                       parent,
+                       associatedNode,
+                       NoExceptions, // no exception allowed by default
+                       scope, 
+                       FlowInfo.DEAD_END);
+       }
+
+       public void checkInitializerExceptions(
+               BlockScope currentScope,
+               FlowContext initializerContext,
+               FlowInfo flowInfo) {
+               for (int i = 0; i < exceptionCount; i++) {
+                       initializerContext.checkExceptionHandlers(
+                               thrownExceptions[i],
+                               exceptionThrowers[i],
+                               exceptionThrowerFlowInfos[i],
+                               currentScope);
+               }
+       }
+
+       public String individualToString() {
+               
+               StringBuffer buffer = new StringBuffer("Initialization flow context"); //$NON-NLS-1$
+               for (int i = 0; i < exceptionCount; i++) {
+                       buffer.append('[').append(thrownExceptions[i].readableName());
+                       buffer.append('-').append(exceptionThrowerFlowInfos[i].toString()).append(']');
+               }
+               return buffer.toString();
+       }
+       
+       public void recordHandlingException(
+               ReferenceBinding exceptionType,
+               UnconditionalFlowInfo flowInfo,
+               TypeBinding raisedException,
+               ASTNode invocationSite,
+               boolean wasMasked) {
+                       
+               // even if unreachable code, need to perform unhandled exception diagnosis
+               int size = thrownExceptions.length;
+               if (exceptionCount == size) {
+                       System.arraycopy(
+                               thrownExceptions,
+                               0,
+                               (thrownExceptions = new TypeBinding[size * 2]),
+                               0,
+                               size);
+                       System.arraycopy(
+                               exceptionThrowers,
+                               0,
+                               (exceptionThrowers = new ASTNode[size * 2]),
+                               0,
+                               size);
+                       System.arraycopy(
+                               exceptionThrowerFlowInfos,
+                               0,
+                               (exceptionThrowerFlowInfos = new FlowInfo[size * 2]),
+                               0,
+                               size);
+               }
+               thrownExceptions[exceptionCount] = raisedException;
+               exceptionThrowers[exceptionCount] = invocationSite;
+               exceptionThrowerFlowInfos[exceptionCount++] = flowInfo.copy();
+       }       
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/InsideSubRoutineFlowContext.java
new file mode 100644 (file)
index 0000000..221666b
--- /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.flow;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class InsideSubRoutineFlowContext extends FlowContext {
+
+       public UnconditionalFlowInfo initsOnReturn;
+       
+       public InsideSubRoutineFlowContext(
+               FlowContext parent,
+               ASTNode associatedNode) {
+               super(parent, associatedNode);
+               this.initsOnReturn = FlowInfo.DEAD_END;                         
+       }
+
+       public String individualToString() {
+               
+               StringBuffer buffer = new StringBuffer("Inside SubRoutine flow context"); //$NON-NLS-1$
+               buffer.append("[initsOnReturn -").append(initsOnReturn.toString()).append(']'); //$NON-NLS-1$
+               return buffer.toString();
+       }
+               
+       public UnconditionalFlowInfo initsOnReturn(){
+               return this.initsOnReturn;
+       }
+               
+       public boolean isNonReturningContext() {
+               return subRoutine().isSubRoutineEscaping();
+       }
+       
+       public SubRoutineStatement subRoutine() {
+               return (SubRoutineStatement)associatedNode;
+       }
+       
+       public void recordReturnFrom(FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return; 
+               if (initsOnReturn == FlowInfo.DEAD_END) {
+                       initsOnReturn = flowInfo.copy().unconditionalInits();
+               } else {
+                       initsOnReturn = initsOnReturn.mergedWith(flowInfo.copy().unconditionalInits());
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/LabelFlowContext.java
new file mode 100644 (file)
index 0000000..0d83e74
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.flow;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.codegen.Label;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class LabelFlowContext extends SwitchFlowContext {
+       
+       public char[] labelName;
+       
+       public LabelFlowContext(
+               FlowContext parent,
+               ASTNode associatedNode,
+               char[] labelName,
+               Label breakLabel,
+               BlockScope scope) {
+                       
+               super(parent, associatedNode, breakLabel);
+               this.labelName = labelName;
+               checkLabelValidity(scope);
+       }
+
+       void checkLabelValidity(BlockScope scope) {
+               
+               // check if label was already defined above
+               FlowContext current = parent;
+               while (current != null) {
+                       char[] currentLabelName;
+                       if (((currentLabelName = current.labelName()) != null)
+                               && CharOperation.equals(currentLabelName, labelName)) {
+                               scope.problemReporter().alreadyDefinedLabel(labelName, associatedNode);
+                       }
+                       current = current.parent;
+               }
+       }
+
+       public String individualToString() {
+
+               return "Label flow context [label:" + String.valueOf(labelName) + "]"; //$NON-NLS-2$ //$NON-NLS-1$
+       }
+
+       public char[] labelName() {
+
+               return labelName;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
new file mode 100644 (file)
index 0000000..450bdff
--- /dev/null
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * 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.flow;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Reference;
+import org.eclipse.jdt.internal.compiler.codegen.Label;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class LoopingFlowContext extends SwitchFlowContext {
+       
+       public Label continueLabel;
+       public UnconditionalFlowInfo initsOnContinue = FlowInfo.DEAD_END;
+       Reference finalAssignments[];
+       VariableBinding finalVariables[];
+       int assignCount = 0;
+       Scope associatedScope;
+       
+       public LoopingFlowContext(
+               FlowContext parent,
+               ASTNode associatedNode,
+               Label breakLabel,
+               Label continueLabel,
+               Scope associatedScope) {
+               super(parent, associatedNode, breakLabel);
+               this.continueLabel = continueLabel;
+               this.associatedScope = associatedScope;
+       }
+       
+       public void complainOnFinalAssignmentsInLoop(
+               BlockScope scope,
+               FlowInfo flowInfo) {
+               for (int i = 0; i < assignCount; i++) {
+                       VariableBinding variable = finalVariables[i];
+                       if (variable == null) continue;
+                       boolean complained = false; // remember if have complained on this final assignment
+                       if (variable instanceof FieldBinding) {
+                               if (flowInfo.isPotentiallyAssigned((FieldBinding) variable)) {
+                                       complained = true;
+                                       scope.problemReporter().duplicateInitializationOfBlankFinalField(
+                                               (FieldBinding) variable,
+                                               finalAssignments[i]);
+                               }
+                       } else {
+                               if (flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
+                                       complained = true;
+                                       scope.problemReporter().duplicateInitializationOfFinalLocal(
+                                               (LocalVariableBinding) variable,
+                                               finalAssignments[i]);
+                               }
+                       }
+                       // any reference reported at this level is removed from the parent context where it 
+                       // could also be reported again
+                       if (complained) {
+                               FlowContext context = parent;
+                               while (context != null) {
+                                       context.removeFinalAssignmentIfAny(finalAssignments[i]);
+                                       context = context.parent;
+                               }
+                       }
+               }
+       }
+
+       public Label continueLabel() {
+               return continueLabel;
+       }
+
+       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$
+               return buffer.toString();
+       }
+
+       public boolean isContinuable() {
+               return true;
+       }
+
+       public boolean isContinuedTo() {
+               return initsOnContinue != FlowInfo.DEAD_END;
+       }
+
+       public void recordContinueFrom(FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return;
+               if (initsOnContinue == FlowInfo.DEAD_END) {
+                       initsOnContinue = flowInfo.copy().unconditionalInits();
+               } else {
+                       initsOnContinue = initsOnContinue.mergedWith(flowInfo.copy().unconditionalInits());
+               }
+       }
+
+       boolean recordFinalAssignment(
+               VariableBinding binding,
+               Reference finalAssignment) {
+
+               // do not consider variables which are defined inside this loop
+               if (binding instanceof LocalVariableBinding) {
+                       Scope scope = ((LocalVariableBinding) binding).declaringScope;
+                       while ((scope = scope.parent) != null) {
+                               if (scope == associatedScope)
+                                       return false;
+                       }
+               }
+               if (assignCount == 0) {
+                       finalAssignments = new Reference[5];
+                       finalVariables = new VariableBinding[5];
+               } else {
+                       if (assignCount == finalAssignments.length)
+                               System.arraycopy(
+                                       finalAssignments,
+                                       0,
+                                       (finalAssignments = new Reference[assignCount * 2]),
+                                       0,
+                                       assignCount);
+                       System.arraycopy(
+                               finalVariables,
+                               0,
+                               (finalVariables = new VariableBinding[assignCount * 2]),
+                               0,
+                               assignCount);
+               }
+               finalAssignments[assignCount] = finalAssignment;
+               finalVariables[assignCount++] = binding;
+               return true;
+       }
+
+       void removeFinalAssignmentIfAny(Reference reference) {
+               for (int i = 0; i < assignCount; i++) {
+                       if (finalAssignments[i] == reference) {
+                               finalAssignments[i] = null;
+                               finalVariables[i] = null;
+                               return;
+                       }
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java b/src/java/org/eclipse/jdt/internal/compiler/flow/SwitchFlowContext.java
new file mode 100644 (file)
index 0000000..5cd28eb
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.flow;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.codegen.Label;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ *     try statements, exception handlers, etc...
+ */
+public class SwitchFlowContext extends FlowContext {
+       public Label breakLabel;
+       public UnconditionalFlowInfo initsOnBreak = FlowInfo.DEAD_END;
+       
+       public SwitchFlowContext(
+               FlowContext parent,
+               ASTNode associatedNode,
+               Label breakLabel) {
+               super(parent, associatedNode);
+               this.breakLabel = breakLabel;
+       }
+
+       public Label breakLabel() {
+               return breakLabel;
+       }
+
+       public String individualToString() {
+               StringBuffer buffer = new StringBuffer("Switch flow context"); //$NON-NLS-1$
+               buffer.append("[initsOnBreak -").append(initsOnBreak.toString()).append(']'); //$NON-NLS-1$
+               return buffer.toString();
+       }
+
+       public boolean isBreakable() {
+               return true;
+       }
+
+       public void recordBreakFrom(FlowInfo flowInfo) {
+
+               if (initsOnBreak == FlowInfo.DEAD_END) {
+                       initsOnBreak = flowInfo.copy().unconditionalInits();
+               } else {
+                       initsOnBreak = initsOnBreak.mergedWith(flowInfo.copy().unconditionalInits());
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/src/java/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
new file mode 100644 (file)
index 0000000..4ae4c52
--- /dev/null
@@ -0,0 +1,559 @@
+/*******************************************************************************
+ * 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.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;
+
+/**
+ * Record initialization status during definite assignment analysis
+ *
+ * No caching of pre-allocated instances.
+ */
+public class UnconditionalFlowInfo extends FlowInfo {
+
+       
+       public long definiteInits;
+       public long potentialInits;
+       public long extraDefiniteInits[];
+       public long extraPotentialInits[];
+       
+       public int reachMode; // by default
+
+       public int maxFieldCount;
+       
+       // Constants
+       public static final int BitCacheSize = 64; // 64 bits in a long.
+
+       UnconditionalFlowInfo() {
+               this.reachMode = REACHABLE;
+       }
+
+       // unions of both sets of initialization - used for try/finally
+       public FlowInfo addInitializationsFrom(FlowInfo inits) {
+
+               if (this == DEAD_END)
+                       return this;
+
+               UnconditionalFlowInfo otherInits = inits.unconditionalInits();  
+               if (otherInits == DEAD_END)
+                       return this;
+                       
+               // union of definitely assigned variables, 
+               definiteInits |= otherInits.definiteInits;
+               // union of potentially set ones
+               potentialInits |= otherInits.potentialInits;
+       
+               // treating extra storage
+               if (extraDefiniteInits != null) {
+                       if (otherInits.extraDefiniteInits != null) {
+                               // both sides have extra storage
+                               int i = 0, length, otherLength;
+                               if ((length = 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);
+                                       while (i < length) {
+                                               extraDefiniteInits[i] |= otherInits.extraDefiniteInits[i];
+                                               extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+                                       }
+                                       while (i < otherLength) {
+                                               extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
+                                       }
+                               } else {
+                                       // current storage is longer
+                                       while (i < otherLength) {
+                                               extraDefiniteInits[i] |= otherInits.extraDefiniteInits[i];
+                                               extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+                                       }
+                                       while (i < length)
+                                               extraDefiniteInits[i++] = 0;
+                               }
+                       } else {
+                               // no extra storage on otherInits
+                       }
+               } else
+                       if (otherInits.extraDefiniteInits != null) {
+                               // no storage here, but other has extra storage.
+                               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);
+                       }
+               return this;
+       }
+
+       // unions of both sets of initialization - used for try/finally
+       public FlowInfo addPotentialInitializationsFrom(FlowInfo inits) {
+       
+               if (this == DEAD_END){
+                       return this;
+               }
+
+               UnconditionalFlowInfo otherInits = inits.unconditionalInits();
+               if (otherInits == DEAD_END){
+                       return this;
+               }
+               // union of potentially set ones
+               potentialInits |= otherInits.potentialInits;
+       
+               // treating extra storage
+               if (extraDefiniteInits != null) {
+                       if (otherInits.extraDefiniteInits != null) {
+                               // both sides have extra storage
+                               int i = 0, length, otherLength;
+                               if ((length = 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);
+                                       while (i < length) {
+                                               extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+                                       }
+                                       while (i < otherLength) {
+                                               extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
+                                       }
+                               } else {
+                                       // current storage is longer
+                                       while (i < otherLength) {
+                                               extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+                                       }
+                               }
+                       }
+               } else
+                       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);
+                       }
+               return this;
+       }
+
+       /**
+        * Answers a copy of the current instance
+        */
+       public FlowInfo copy() {
+               
+               // do not clone the DeadEnd
+               if (this == DEAD_END)
+                       return this;
+       
+               // look for an unused preallocated object
+               UnconditionalFlowInfo copy = new UnconditionalFlowInfo();
+       
+               // copy slots
+               copy.definiteInits = this.definiteInits;
+               copy.potentialInits = this.potentialInits;
+               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.extraPotentialInits, 0, (copy.extraPotentialInits = new long[length]), 0, length);
+               }
+               return copy;
+       }
+       
+       public UnconditionalFlowInfo discardFieldInitializations(){
+               
+               int limit = this.maxFieldCount;
+               
+               if (limit < BitCacheSize) {
+                       long mask = (1L << limit)-1;
+                       this.definiteInits &= ~mask;
+                       this.potentialInits &= ~mask;
+                       return this;
+               } 
+
+               this.definiteInits = 0;
+               this.potentialInits = 0;
+
+               // use extra vector
+               if (extraDefiniteInits == null) {
+                       return this; // if vector not yet allocated, then not initialized
+               }
+               int vectorIndex, length = this.extraDefiniteInits.length;
+               if ((vectorIndex = (limit / BitCacheSize) - 1) >= length) {
+                       return this; // not enough room yet
+               }
+               for (int i = 0; i < vectorIndex; i++) {
+                       this.extraDefiniteInits[i] = 0L;
+                       this.extraPotentialInits[i] = 0L;
+               }
+               long mask = (1L << (limit % BitCacheSize))-1;
+               this.extraDefiniteInits[vectorIndex] &= ~mask;
+               this.extraPotentialInits[vectorIndex] &= ~mask;
+               return this;
+       }
+
+       public UnconditionalFlowInfo discardNonFieldInitializations(){
+               
+               int limit = this.maxFieldCount;
+               
+               if (limit < BitCacheSize) {
+                       long mask = (1L << limit)-1;
+                       this.definiteInits &= mask;
+                       this.potentialInits &= mask;
+                       return this;
+               } 
+               // use extra vector
+               if (extraDefiniteInits == null) {
+                       return this; // if vector not yet allocated, then not initialized
+               }
+               int vectorIndex, length = this.extraDefiniteInits.length;
+               if ((vectorIndex = (limit / BitCacheSize) - 1) >= length) {
+                       return this; // not enough room yet
+               }
+               long mask = (1L << (limit % BitCacheSize))-1;
+               this.extraDefiniteInits[vectorIndex] &= mask;
+               this.extraPotentialInits[vectorIndex] &= mask;
+               for (int i = vectorIndex+1; i < length; i++) {
+                       this.extraDefiniteInits[i] = 0L;
+                       this.extraPotentialInits[i] = 0L;
+               }
+               return this;
+       }
+       
+       public FlowInfo initsWhenFalse() {
+               
+               return this;
+       }
+       
+       public FlowInfo initsWhenTrue() {
+               
+               return this;
+       }
+       
+       /**
+        * Check status of definite 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 isDefinitelyAssigned(int position) {
+               
+               // Dependant of CodeStream.isDefinitelyAssigned(..)
+               // id is zero-based
+               if (position < BitCacheSize) {
+                       return (definiteInits & (1L << position)) != 0; // use bits
+               }
+               // use extra vector
+               if (extraDefiniteInits == null)
+                       return false; // if vector not yet allocated, then not initialized
+               int vectorIndex;
+               if ((vectorIndex = (position / BitCacheSize) - 1) >= extraDefiniteInits.length)
+                       return false; // if not enough room in vector, then not initialized 
+               return ((extraDefiniteInits[vectorIndex]) & (1L << (position % BitCacheSize))) != 0;
+       }
+       
+       /**
+        * Check status of definite assignment for a field.
+        */
+       final public boolean isDefinitelyAssigned(FieldBinding field) {
+               
+               // Dependant of CodeStream.isDefinitelyAssigned(..)
+               // We do not want to complain in unreachable code
+               if ((this.reachMode & UNREACHABLE) != 0)  
+                       return true;
+               return isDefinitelyAssigned(field.id); 
+       }
+       
+       /**
+        * Check status of definite assignment for a local.
+        */
+       final public boolean isDefinitelyAssigned(LocalVariableBinding local) {
+               
+               // Dependant of CodeStream.isDefinitelyAssigned(..)
+               // We do not want to complain in unreachable code
+               if ((this.reachMode & UNREACHABLE) != 0)
+                       return true;
+               if (local.isArgument) {
+                       return true;
+               }
+               // final constants are inlined, and thus considered as always initialized
+               if (local.constant != Constant.NotAConstant) {
+                       return true;
+               }
+               return isDefinitelyAssigned(local.id + maxFieldCount);
+       }
+       
+       public boolean isReachable() {
+               
+               return this.reachMode == REACHABLE;
+       }
+       
+       /**
+        * Check status of potential assignment at a given position.
+        * It deals with the dual representation of the InitializationInfo3:
+        * bits for the first 64 entries, then an array of booleans.
+        */
+       final private boolean isPotentiallyAssigned(int position) {
+               
+               // id is zero-based
+               if (position < BitCacheSize) {
+                       // use bits
+                       return (potentialInits & (1L << position)) != 0;
+               }
+               // use extra vector
+               if (extraPotentialInits == null)
+                       return false; // if vector not yet allocated, then not initialized
+               int vectorIndex;
+               if ((vectorIndex = (position / BitCacheSize) - 1) >= extraPotentialInits.length)
+                       return false; // if not enough room in vector, then not initialized 
+               return ((extraPotentialInits[vectorIndex]) & (1L << (position % BitCacheSize))) != 0;
+       }
+       
+       /**
+        * Check status of definite assignment for a field.
+        */
+       final public boolean isPotentiallyAssigned(FieldBinding field) {
+               
+               return isPotentiallyAssigned(field.id); 
+       }
+       
+       /**
+        * Check status of potential assignment for a local.
+        */
+       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) {
+                       return true;
+               }
+               return isPotentiallyAssigned(local.id + maxFieldCount);
+       }
+       
+       /**
+        * Record a definite 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 markAsDefinitelyAssigned(int position) {
+               
+               if (this != DEAD_END) {
+       
+                       // position is zero-based
+                       if (position < BitCacheSize) {
+                               // use bits
+                               long mask;
+                               definiteInits |= (mask = 1L << position);
+                               potentialInits |= mask;
+                       } else {
+                               // use extra vector
+                               int vectorIndex = (position / BitCacheSize) - 1;
+                               if (extraDefiniteInits == null) {
+                                       int length;
+                                       extraDefiniteInits = new long[length = vectorIndex + 1];
+                                       extraPotentialInits = 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);
+                                       }
+                               }
+                               long mask;
+                               extraDefiniteInits[vectorIndex] |= (mask = 1L << (position % BitCacheSize));
+                               extraPotentialInits[vectorIndex] |= mask;
+                       }
+               }
+       }
+       
+       /**
+        * Record a field got definitely assigned.
+        */
+       public void markAsDefinitelyAssigned(FieldBinding field) {
+               if (this != DEAD_END)
+                       markAsDefinitelyAssigned(field.id);
+       }
+       
+       /**
+        * Record a local got definitely assigned.
+        */
+       public void markAsDefinitelyAssigned(LocalVariableBinding local) {
+               if (this != DEAD_END)
+                       markAsDefinitelyAssigned(local.id + maxFieldCount);
+       }
+       
+       /**
+        * Clear initialization information 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 markAsDefinitelyNotAssigned(int position) {
+               if (this != DEAD_END) {
+       
+                       // position is zero-based
+                       if (position < BitCacheSize) {
+                               // use bits
+                               long mask;
+                               definiteInits &= ~(mask = 1L << position);
+                               potentialInits &= ~mask;
+                       } else {
+                               // use extra vector
+                               int vectorIndex = (position / BitCacheSize) - 1;
+                               if (extraDefiniteInits == null) {
+                                       return; // nothing to do, it was not yet set 
+                               }
+                               // might need to grow the arrays
+                               if (vectorIndex >= extraDefiniteInits.length) {
+                                       return; // nothing to do, it was not yet set 
+                               }
+                               long mask;
+                               extraDefiniteInits[vectorIndex] &= ~(mask = 1L << (position % BitCacheSize));
+                               extraPotentialInits[vectorIndex] &= ~mask;
+                       }
+               }
+       }
+       
+       /**
+        * Clear the initialization info for a field
+        */
+       public void markAsDefinitelyNotAssigned(FieldBinding field) {
+               
+               if (this != DEAD_END)
+                       markAsDefinitelyNotAssigned(field.id);
+       }
+       
+       /**
+        * Clear the initialization info for a local variable
+        */
+       
+       public void markAsDefinitelyNotAssigned(LocalVariableBinding local) {
+               
+               if (this != DEAD_END)
+                       markAsDefinitelyNotAssigned(local.id + maxFieldCount);
+       }
+               
+       /**
+        * Returns the receiver updated in the following way: <ul>
+        * <li> intersection of definitely assigned variables, 
+        * <li> union of potentially assigned variables.
+        * </ul>
+        */
+       public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
+       
+               if (this == DEAD_END) return otherInits;
+               if (otherInits == DEAD_END) return this;
+       
+               if ((this.reachMode & UNREACHABLE) != (otherInits.reachMode & UNREACHABLE)){
+                       if ((this.reachMode & UNREACHABLE) != 0){
+                               return otherInits;
+                       } 
+                       return this;
+               }
+               
+               // if one branch is not fake reachable, then the merged one is reachable
+               this.reachMode &= otherInits.reachMode;
+       
+               // intersection of definitely assigned variables, 
+               this.definiteInits &= otherInits.definiteInits;
+               // union of potentially set ones
+               this.potentialInits |= otherInits.potentialInits;
+       
+               // treating extra storage
+               if (this.extraDefiniteInits != null) {
+                       if (otherInits.extraDefiniteInits != null) {
+                               // both sides have extra storage
+                               int i = 0, length, otherLength;
+                               if ((length = this.extraDefiniteInits.length) < (otherLength = otherInits.extraDefiniteInits.length)) {
+                                       // 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);
+                                       while (i < length) {
+                                               this.extraDefiniteInits[i] &= otherInits.extraDefiniteInits[i];
+                                               this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+                                       }
+                                       while (i < otherLength) {
+                                               this.extraPotentialInits[i] = otherInits.extraPotentialInits[i++];
+                                       }
+                               } else {
+                                       // current storage is longer
+                                       while (i < otherLength) {
+                                               this.extraDefiniteInits[i] &= otherInits.extraDefiniteInits[i];
+                                               this.extraPotentialInits[i] |= otherInits.extraPotentialInits[i++];
+                                       }
+                                       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;
+                       }
+               } else
+                       if (otherInits.extraDefiniteInits != null) {
+                               // no storage here, but other has extra storage.
+                               int otherLength;
+                               this.extraDefiniteInits = new long[otherLength = otherInits.extraDefiniteInits.length];
+                               System.arraycopy(otherInits.extraPotentialInits, 0, (this.extraPotentialInits = new long[otherLength]), 0, otherLength);
+                       }
+               return this;
+       }
+       
+       /*
+        * Answer the total number of fields in enclosing types of a given type
+        */
+       static int numberOfEnclosingFields(ReferenceBinding type){
+               
+               int count = 0;
+               type = type.enclosingType();
+               while(type != null) {
+                       count += type.fieldCount();
+                       type = type.enclosingType();
+               }
+               return count;
+       }
+       
+       public int reachMode(){
+               return this.reachMode;
+       }
+       
+       public FlowInfo setReachMode(int reachMode) {
+               
+               if (this == DEAD_END) return this; // cannot modify DEAD_END
+       
+               // reset optional inits when becoming unreachable
+               if ((this.reachMode & UNREACHABLE) == 0 && (reachMode & UNREACHABLE) != 0) {
+                       this.potentialInits = 0;
+                       if (this.extraPotentialInits != null){
+                               for (int i = 0, length = this.extraPotentialInits.length; i < length; i++){
+                                       this.extraPotentialInits[i] = 0;
+                               }
+                       }
+               }                               
+               this.reachMode = reachMode;
+       
+               return this;
+       }
+
+       public String toString(){
+               
+               if (this == DEAD_END){
+                       return "FlowInfo.DEAD_END"; //$NON-NLS-1$
+               }
+               return "FlowInfo<def: "+ this.definiteInits //$NON-NLS-1$
+                       +", pot: " + this.potentialInits  //$NON-NLS-1$
+                       + ", reachable:" + ((this.reachMode & UNREACHABLE) == 0) //$NON-NLS-1$
+                       +">"; //$NON-NLS-1$
+       }
+       
+       public UnconditionalFlowInfo unconditionalInits() {
+               
+               // also see conditional inits, where it requests them to merge
+               return this;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/BooleanConstant.java
new file mode 100644 (file)
index 0000000..e85214f
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.impl;
+
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class BooleanConstant extends Constant {
+
+       boolean value;
+       
+       public BooleanConstant(boolean value) {
+               this.value = value;
+       }
+
+       public boolean booleanValue() {
+               return value;
+       }
+
+       public String stringValue() {
+               //spec 15.17.11
+               String s = Util.toBoolean(value).toString();
+               if (s == null) return "null"; //$NON-NLS-1$
+               return s;
+       }
+
+       public String toString(){
+               return "(boolean)" + value ;  //$NON-NLS-1$
+       }
+
+       public int typeID() {
+               return T_boolean;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/ByteConstant.java
new file mode 100644 (file)
index 0000000..9a5e56a
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.impl;
+
+public class ByteConstant extends Constant {
+       byte value;
+public ByteConstant(byte value) {
+       this.value = value;
+}
+public byte byteValue() {
+       return this.value;
+}
+public char charValue() {
+       return (char) value;
+}
+public double doubleValue() {
+       return value; // implicit cast to return type
+}
+public float floatValue() {
+       return value; // implicit cast to return type
+}
+public int intValue() {
+       return value; // implicit cast to return type
+}
+public long longValue() {
+       return value; // implicit cast to return type
+}
+public short shortValue() {
+       return value; // implicit cast to return type
+}
+public String stringValue() {
+       //spec 15.17.11
+       
+       String s = new Integer(value).toString() ;
+       if (s == null) return "null"; //$NON-NLS-1$
+       return s;
+}
+public String toString(){
+
+       return "(byte)" + value ; } //$NON-NLS-1$
+public int typeID() {
+       return T_byte;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/CharConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/CharConstant.java
new file mode 100644 (file)
index 0000000..d70f8a3
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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.impl;
+
+public class CharConstant extends Constant {
+
+       char value;
+
+       public CharConstant(char value) {
+               this.value = value;
+       }
+       public byte byteValue() {
+               return (byte) value;
+       }
+       public char charValue() {
+               return this.value;
+       }
+       public double doubleValue() {
+               return value; // implicit cast to return type
+       }
+       public float floatValue() {
+               return value; // implicit cast to return type
+       }
+       public int intValue() {
+               return value; // implicit cast to return type
+       }
+       public long longValue() {
+               return value; // implicit cast to return type
+       }
+       public short shortValue() {
+               return (short) value;
+       }
+       public String stringValue() {
+               //spec 15.17.11
+               
+               String s = new Character(value).toString() ;
+               if (s == null) return "null"; //$NON-NLS-1$
+               return s;
+       }
+       public String toString(){
+       
+               return "(char)" + value; //$NON-NLS-1$
+       }
+       public int typeID() {
+               return T_char;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/src/java/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
new file mode 100644 (file)
index 0000000..0d729a4
--- /dev/null
@@ -0,0 +1,695 @@
+/*******************************************************************************
+ * 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.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.Compiler;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+public class CompilerOptions implements ProblemReasons, ProblemSeverities, ClassFileConstants {
+       
+       /**
+        * Option IDs
+        */
+       public static final String OPTION_LocalVariableAttribute = "org.eclipse.jdt.core.compiler.debug.localVariable"; //$NON-NLS-1$
+       public static final String OPTION_LineNumberAttribute = "org.eclipse.jdt.core.compiler.debug.lineNumber"; //$NON-NLS-1$
+       public static final String OPTION_SourceFileAttribute = "org.eclipse.jdt.core.compiler.debug.sourceFile"; //$NON-NLS-1$
+       public static final String OPTION_PreserveUnusedLocal = "org.eclipse.jdt.core.compiler.codegen.unusedLocal"; //$NON-NLS-1$
+       public static final String OPTION_DocCommentSupport= "org.eclipse.jdt.core.compiler.doc.comment.support"; //$NON-NLS-1$
+       public static final String OPTION_ReportMethodWithConstructorName = "org.eclipse.jdt.core.compiler.problem.methodWithConstructorName"; //$NON-NLS-1$
+       public static final String OPTION_ReportOverridingPackageDefaultMethod = "org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod"; //$NON-NLS-1$
+       public static final String OPTION_ReportDeprecation = "org.eclipse.jdt.core.compiler.problem.deprecation"; //$NON-NLS-1$
+       public static final String OPTION_ReportDeprecationInDeprecatedCode = "org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode"; //$NON-NLS-1$
+       public static final String OPTION_ReportDeprecationWhenOverridingDeprecatedMethod = "org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod"; //$NON-NLS-1$
+       public static final String OPTION_ReportHiddenCatchBlock = "org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnusedLocal = "org.eclipse.jdt.core.compiler.problem.unusedLocal"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnusedParameter = "org.eclipse.jdt.core.compiler.problem.unusedParameter"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnusedParameterWhenImplementingAbstract = "org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnusedParameterWhenOverridingConcrete = "org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnusedImport = "org.eclipse.jdt.core.compiler.problem.unusedImport"; //$NON-NLS-1$
+       public static final String OPTION_ReportSyntheticAccessEmulation = "org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation"; //$NON-NLS-1$
+       public static final String OPTION_ReportNoEffectAssignment = "org.eclipse.jdt.core.compiler.problem.noEffectAssignment"; //$NON-NLS-1$
+       public static final String OPTION_ReportLocalVariableHiding = "org.eclipse.jdt.core.compiler.problem.localVariableHiding"; //$NON-NLS-1$
+       public static final String OPTION_ReportSpecialParameterHidingField = "org.eclipse.jdt.core.compiler.problem.specialParameterHidingField"; //$NON-NLS-1$
+       public static final String OPTION_ReportFieldHiding = "org.eclipse.jdt.core.compiler.problem.fieldHiding"; //$NON-NLS-1$
+       public static final String OPTION_ReportPossibleAccidentalBooleanAssignment = "org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment"; //$NON-NLS-1$
+       public static final String OPTION_ReportNonExternalizedStringLiteral = "org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral"; //$NON-NLS-1$
+       public static final String OPTION_ReportIncompatibleNonInheritedInterfaceMethod = "org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnusedPrivateMember = "org.eclipse.jdt.core.compiler.problem.unusedPrivateMember"; //$NON-NLS-1$
+       public static final String OPTION_ReportNoImplicitStringConversion = "org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion"; //$NON-NLS-1$
+       public static final String OPTION_ReportAssertIdentifier = "org.eclipse.jdt.core.compiler.problem.assertIdentifier"; //$NON-NLS-1$
+       public static final String OPTION_ReportNonStaticAccessToStatic = "org.eclipse.jdt.core.compiler.problem.staticAccessReceiver"; //$NON-NLS-1$
+       public static final String OPTION_ReportIndirectStaticAccess = "org.eclipse.jdt.core.compiler.problem.indirectStaticAccess"; //$NON-NLS-1$
+       public static final String OPTION_ReportEmptyStatement = "org.eclipse.jdt.core.compiler.problem.emptyStatement"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnnecessaryTypeCheck = "org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnnecessaryElse = "org.eclipse.jdt.core.compiler.problem.unnecessaryElse"; //$NON-NLS-1$
+       public static final String OPTION_ReportUndocumentedEmptyBlock = "org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock"; //$NON-NLS-1$
+       public static final String OPTION_ReportInvalidJavadoc = "org.eclipse.jdt.core.compiler.problem.invalidJavadoc"; //$NON-NLS-1$
+       public static final String OPTION_ReportInvalidJavadocTags = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTags"; //$NON-NLS-1$
+       public static final String OPTION_ReportInvalidJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingJavadocTags = "org.eclipse.jdt.core.compiler.problem.missingJavadocTags"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingJavadocTagsVisibility = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingJavadocTagsOverriding = "org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingJavadocComments = "org.eclipse.jdt.core.compiler.problem.missingJavadocComments"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingJavadocCommentsVisibility = "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingJavadocCommentsOverriding = "org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding"; //$NON-NLS-1$
+       public static final String OPTION_ReportFinallyBlockNotCompletingNormally = "org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally"; //$NON-NLS-1$
+       public static final String OPTION_ReportUnusedDeclaredThrownException = "org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException"; //$NON-NLS-1$
+       public static final String OPTION_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_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$
+       public static final String OPTION_Encoding = "org.eclipse.jdt.core.encoding"; //$NON-NLS-1$
+       public static final String OPTION_MaxProblemPerUnit = "org.eclipse.jdt.core.compiler.maxProblemPerUnit"; //$NON-NLS-1$
+       public static final String OPTION_TaskTags = "org.eclipse.jdt.core.compiler.taskTags"; //$NON-NLS-1$
+       public static final String OPTION_TaskPriorities = "org.eclipse.jdt.core.compiler.taskPriorities"; //$NON-NLS-1$
+       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$
+       
+       // Backward compatibility
+       public static final String OPTION_ReportInvalidAnnotation = "org.eclipse.jdt.core.compiler.problem.invalidAnnotation"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingAnnotation = "org.eclipse.jdt.core.compiler.problem.missingAnnotation"; //$NON-NLS-1$
+       public static final String OPTION_ReportMissingJavadoc = "org.eclipse.jdt.core.compiler.problem.missingJavadoc"; //$NON-NLS-1$
+
+       /* should surface ??? */
+       public static final String OPTION_PrivateConstructorAccess = "org.eclipse.jdt.core.compiler.codegen.constructorAccessEmulation"; //$NON-NLS-1$
+
+       /**
+        * Possible values for configurable options
+        */
+       public static final String GENERATE = "generate";//$NON-NLS-1$
+       public static final String DO_NOT_GENERATE = "do not generate"; //$NON-NLS-1$
+       public static final String PRESERVE = "preserve"; //$NON-NLS-1$
+       public static final String OPTIMIZE_OUT = "optimize out"; //$NON-NLS-1$
+       public static final String VERSION_1_1 = "1.1"; //$NON-NLS-1$
+       public static final String VERSION_1_2 = "1.2"; //$NON-NLS-1$
+       public static final String VERSION_1_3 = "1.3"; //$NON-NLS-1$
+       public static final String VERSION_1_4 = "1.4"; //$NON-NLS-1$
+       public static final String VERSION_1_5 = "1.5"; //$NON-NLS-1$
+       public static final String ERROR = "error"; //$NON-NLS-1$
+       public static final String WARNING = "warning"; //$NON-NLS-1$
+       public static final String IGNORE = "ignore"; //$NON-NLS-1$
+       public static final String ENABLED = "enabled"; //$NON-NLS-1$
+       public static final String DISABLED = "disabled"; //$NON-NLS-1$
+       public static final String PUBLIC = "public";   //$NON-NLS-1$
+       public static final String PROTECTED = "protected";     //$NON-NLS-1$
+       public static final String DEFAULT = "default"; //$NON-NLS-1$
+       public static final String PRIVATE = "private"; //$NON-NLS-1$
+       
+       /**
+        * Bit mask for configurable problems (error/warning threshold)
+        */
+       public static final long MethodWithConstructorName = ASTNode.Bit1;
+       public static final long OverriddenPackageDefaultMethod = ASTNode.Bit2;
+       public static final long UsingDeprecatedAPI = ASTNode.Bit3;
+       public static final long MaskedCatchBlock = ASTNode.Bit4;
+       public static final long UnusedLocalVariable = ASTNode.Bit5;
+       public static final long UnusedArgument = ASTNode.Bit6;
+       public static final long NoImplicitStringConversion = ASTNode.Bit7;
+       public static final long AccessEmulation = ASTNode.Bit8;
+       public static final long NonExternalizedString = ASTNode.Bit9;
+       public static final long AssertUsedAsAnIdentifier = ASTNode.Bit10;
+       public static final long UnusedImport = ASTNode.Bit11;
+       public static final long NonStaticAccessToStatic = ASTNode.Bit12;
+       public static final long Task = ASTNode.Bit13;
+       public static final long NoEffectAssignment = ASTNode.Bit14;
+       public static final long IncompatibleNonInheritedInterfaceMethod = ASTNode.Bit15;
+       public static final long UnusedPrivateMember = ASTNode.Bit16;
+       public static final long LocalVariableHiding = ASTNode.Bit17;
+       public static final long FieldHiding = ASTNode.Bit18;
+       public static final long AccidentalBooleanAssign = ASTNode.Bit19;
+       public static final long EmptyStatement = ASTNode.Bit20;
+       public static final long MissingJavadocComments  = ASTNode.Bit21;
+       public static final long MissingJavadocTags = ASTNode.Bit22;
+       public static final long UnqualifiedFieldAccess = ASTNode.Bit23;
+       public static final long UnusedDeclaredThrownException = ASTNode.Bit24;
+       public static final long FinallyBlockNotCompleting = ASTNode.Bit25;
+       public static final long InvalidJavadoc = ASTNode.Bit26;
+       public static final long UnnecessaryTypeCheck = ASTNode.Bit27;
+       public static final long UndocumentedEmptyBlock = ASTNode.Bit28;
+       public static final long IndirectStaticAccess = ASTNode.Bit29;
+       public static final long UnnecessaryElse  = ASTNode.Bit30;
+
+       // Default severity level for handlers
+       public long errorThreshold = 0;
+               
+       public long warningThreshold = 
+               MethodWithConstructorName 
+               | UsingDeprecatedAPI 
+               | MaskedCatchBlock 
+               | OverriddenPackageDefaultMethod
+               | UnusedImport
+               | NonStaticAccessToStatic
+               | NoEffectAssignment
+               | IncompatibleNonInheritedInterfaceMethod
+               | NoImplicitStringConversion
+               | FinallyBlockNotCompleting
+               | AssertUsedAsAnIdentifier;
+
+       // Debug attributes
+       public static final int Source = 1; // SourceFileAttribute
+       public static final int Lines = 2; // LineNumberAttribute
+       public static final int Vars = 4; // LocalVariableTableAttribute
+
+       // By default only lines and source attributes are generated.
+       public int produceDebugAttributes = Lines | Source;
+
+       public long complianceLevel = JDK1_4; // by default be compliant with 1.4
+       public long sourceLevel = JDK1_3; //1.3 source behavior by default
+       public long targetJDK = JDK1_2; // default generates for JVM1.2
+
+       // toggle private access emulation for 1.2 (constr. accessor has extra arg on constructor) or 1.3 (make private constructor default access when access needed)
+       public boolean isPrivateConstructorAccessChangingVisibility = false; // by default, follows 1.2
+       
+       // source encoding format
+       public String defaultEncoding = null; // will use the platform default encoding
+       
+       // print what unit is being processed
+       public boolean verbose = Compiler.DEBUG;
+
+       // indicates if reference info is desired
+       public boolean produceReferenceInfo = false;
+
+       // indicates if unused/optimizable local variables need to be preserved (debugging purpose)
+       public boolean preserveAllLocalVariables = false;
+
+       // indicates whether literal expressions are inlined at parse-time or not
+       public boolean parseLiteralExpressionsAsConstants = true;
+
+       // max problems per compilation unit
+       public int maxProblemsPerUnit = 100; // no more than 100 problems per default
+       
+       // tags used to recognize tasks in comments
+       public char[][] taskTags = null;
+       public char[][] taskPriorites = null;
+       public boolean isTaskCaseSensitive = true;
+
+       // deprecation report
+       public boolean reportDeprecationInsideDeprecatedCode = false;
+       public boolean reportDeprecationWhenOverridingDeprecatedMethod = false;
+       
+       // unused parameters report
+       public boolean reportUnusedParameterWhenImplementingAbstract = false;
+       public boolean reportUnusedParameterWhenOverridingConcrete = false;
+
+       // unused declaration of thrown exception
+       public boolean reportUnusedDeclaredThrownExceptionWhenOverriding = false;
+       
+       // constructor/setter parameter hiding
+       public boolean reportSpecialParameterHidingField = false;
+
+       // check javadoc comments
+       public int reportInvalidJavadocTagsVisibility = AccPrivate; 
+       public boolean reportInvalidJavadocTags = true; 
+
+       // check missing javadoc tags
+       public int reportMissingJavadocTagsVisibility = AccPrivate; 
+       public boolean reportMissingJavadocTagsOverriding = true;
+
+       // check missing javadoc comments
+       public int reportMissingJavadocCommentsVisibility = AccPublic; 
+       public boolean reportMissingJavadocCommentsOverriding = true; 
+       
+       // JSR bytecode inlining
+       public boolean inlineJsrBytecode = false;
+       
+       // javadoc comment support
+       public boolean docCommentSupport = false;
+       
+       
+       /** 
+        * Initializing the compiler options with defaults
+        */
+       public CompilerOptions(){
+               // use default options
+       }
+
+       /** 
+        * Initializing the compiler options with external settings
+        * @param settings
+        */
+       public CompilerOptions(Map settings){
+
+               if (settings == null) return;
+               set(settings);          
+       }
+
+       public Map getMap() {
+               Map optionsMap = new HashMap(30);
+               optionsMap.put(OPTION_LocalVariableAttribute, (this.produceDebugAttributes & Vars) != 0 ? GENERATE : DO_NOT_GENERATE); 
+               optionsMap.put(OPTION_LineNumberAttribute, (this.produceDebugAttributes & Lines) != 0 ? GENERATE : DO_NOT_GENERATE);
+               optionsMap.put(OPTION_SourceFileAttribute, (this.produceDebugAttributes & Source) != 0 ? GENERATE : DO_NOT_GENERATE);
+               optionsMap.put(OPTION_PreserveUnusedLocal, this.preserveAllLocalVariables ? PRESERVE : OPTIMIZE_OUT);
+               optionsMap.put(OPTION_DocCommentSupport, this.docCommentSupport ? ENABLED : DISABLED); 
+               optionsMap.put(OPTION_ReportMethodWithConstructorName, getSeverityString(MethodWithConstructorName)); 
+               optionsMap.put(OPTION_ReportOverridingPackageDefaultMethod, getSeverityString(OverriddenPackageDefaultMethod)); 
+               optionsMap.put(OPTION_ReportDeprecation, getSeverityString(UsingDeprecatedAPI)); 
+               optionsMap.put(OPTION_ReportDeprecationInDeprecatedCode, this.reportDeprecationInsideDeprecatedCode ? ENABLED : DISABLED); 
+               optionsMap.put(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod, this.reportDeprecationWhenOverridingDeprecatedMethod ? ENABLED : DISABLED); 
+               optionsMap.put(OPTION_ReportHiddenCatchBlock, getSeverityString(MaskedCatchBlock)); 
+               optionsMap.put(OPTION_ReportUnusedLocal, getSeverityString(UnusedLocalVariable)); 
+               optionsMap.put(OPTION_ReportUnusedParameter, getSeverityString(UnusedArgument)); 
+               optionsMap.put(OPTION_ReportUnusedImport, getSeverityString(UnusedImport)); 
+               optionsMap.put(OPTION_ReportSyntheticAccessEmulation, getSeverityString(AccessEmulation)); 
+               optionsMap.put(OPTION_ReportNoEffectAssignment, getSeverityString(NoEffectAssignment)); 
+               optionsMap.put(OPTION_ReportNonExternalizedStringLiteral, getSeverityString(NonExternalizedString)); 
+               optionsMap.put(OPTION_ReportNoImplicitStringConversion, getSeverityString(NoImplicitStringConversion)); 
+               optionsMap.put(OPTION_ReportNonStaticAccessToStatic, getSeverityString(NonStaticAccessToStatic)); 
+               optionsMap.put(OPTION_ReportIndirectStaticAccess, getSeverityString(IndirectStaticAccess)); 
+               optionsMap.put(OPTION_ReportIncompatibleNonInheritedInterfaceMethod, getSeverityString(IncompatibleNonInheritedInterfaceMethod)); 
+               optionsMap.put(OPTION_ReportUnusedPrivateMember, getSeverityString(UnusedPrivateMember)); 
+               optionsMap.put(OPTION_ReportLocalVariableHiding, getSeverityString(LocalVariableHiding)); 
+               optionsMap.put(OPTION_ReportFieldHiding, getSeverityString(FieldHiding)); 
+               optionsMap.put(OPTION_ReportPossibleAccidentalBooleanAssignment, getSeverityString(AccidentalBooleanAssign)); 
+               optionsMap.put(OPTION_ReportEmptyStatement, getSeverityString(EmptyStatement)); 
+               optionsMap.put(OPTION_ReportAssertIdentifier, getSeverityString(AssertUsedAsAnIdentifier)); 
+               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_ReportMissingJavadocTags, getSeverityString(MissingJavadocTags));
+               optionsMap.put(OPTION_ReportMissingJavadocTagsVisibility, getVisibilityString(this.reportMissingJavadocTagsVisibility));
+               optionsMap.put(OPTION_ReportMissingJavadocTagsOverriding, this.reportMissingJavadocTagsOverriding ? ENABLED : DISABLED);
+               optionsMap.put(OPTION_ReportMissingJavadocComments, getSeverityString(MissingJavadocComments));
+               optionsMap.put(OPTION_ReportMissingJavadocCommentsVisibility, getVisibilityString(this.reportMissingJavadocCommentsVisibility));
+               optionsMap.put(OPTION_ReportMissingJavadocCommentsOverriding, this.reportMissingJavadocCommentsOverriding ? ENABLED : DISABLED);
+               optionsMap.put(OPTION_ReportFinallyBlockNotCompletingNormally, getSeverityString(FinallyBlockNotCompleting));
+               optionsMap.put(OPTION_ReportUnusedDeclaredThrownException, getSeverityString(UnusedDeclaredThrownException));
+               optionsMap.put(OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding, this.reportUnusedDeclaredThrownExceptionWhenOverriding ? ENABLED : DISABLED); 
+               optionsMap.put(OPTION_ReportUnqualifiedFieldAccess, getSeverityString(UnqualifiedFieldAccess));
+               optionsMap.put(OPTION_Compliance, versionFromJdkLevel(this.complianceLevel)); 
+               optionsMap.put(OPTION_Source, versionFromJdkLevel(this.sourceLevel)); 
+               optionsMap.put(OPTION_TargetPlatform, versionFromJdkLevel(this.targetJDK)); 
+               if (this.defaultEncoding != null) {
+                       optionsMap.put(OPTION_Encoding, this.defaultEncoding); 
+               }
+               optionsMap.put(OPTION_TaskTags, this.taskTags == null ? "" : new String(CharOperation.concatWith(this.taskTags,','))); //$NON-NLS-1$
+               optionsMap.put(OPTION_TaskPriorities, this.taskPriorites == null ? "" : new String(CharOperation.concatWith(this.taskPriorites,','))); //$NON-NLS-1$
+               optionsMap.put(OPTION_TaskCaseSensitive, this.isTaskCaseSensitive ? ENABLED : DISABLED);
+               optionsMap.put(OPTION_ReportUnusedParameterWhenImplementingAbstract, this.reportUnusedParameterWhenImplementingAbstract ? ENABLED : DISABLED); 
+               optionsMap.put(OPTION_ReportUnusedParameterWhenOverridingConcrete, this.reportUnusedParameterWhenOverridingConcrete ? ENABLED : DISABLED); 
+               optionsMap.put(OPTION_ReportSpecialParameterHidingField, this.reportSpecialParameterHidingField ? ENABLED : DISABLED); 
+               optionsMap.put(OPTION_MaxProblemPerUnit, String.valueOf(this.maxProblemsPerUnit));
+               optionsMap.put(OPTION_InlineJsr, this.inlineJsrBytecode ? ENABLED : DISABLED); 
+               return optionsMap;              
+       }
+       
+       public int getSeverity(long irritant) {
+               if((this.warningThreshold & irritant) != 0)
+                       return Warning;
+               if((this.errorThreshold & irritant) != 0)
+                       return Error;
+               return Ignore;
+       }
+
+       public String getSeverityString(long irritant) {
+               if((this.warningThreshold & irritant) != 0)
+                       return WARNING;
+               if((this.errorThreshold & irritant) != 0)
+                       return ERROR;
+               return IGNORE;
+       }
+       
+       public String getVisibilityString(int level) {
+               switch (level) {
+                       case AccPublic:
+                               return PUBLIC;
+                       case AccProtected:
+                               return PROTECTED;
+                       case AccPrivate:
+                               return PRIVATE;
+                       default:
+                               return DEFAULT;
+               }
+       }
+       
+       public void set(Map optionsMap) {
+
+               Object optionValue;
+               if ((optionValue = optionsMap.get(OPTION_LocalVariableAttribute)) != null) {
+                       if (GENERATE.equals(optionValue)) {
+                               this.produceDebugAttributes |= Vars;
+                       } else if (DO_NOT_GENERATE.equals(optionValue)) {
+                               this.produceDebugAttributes &= ~Vars;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_LineNumberAttribute)) != null) {
+                       if (GENERATE.equals(optionValue)) {
+                               this.produceDebugAttributes |= Lines;
+                       } else if (DO_NOT_GENERATE.equals(optionValue)) {
+                               this.produceDebugAttributes &= ~Lines;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_SourceFileAttribute)) != null) {
+                       if (GENERATE.equals(optionValue)) {
+                               this.produceDebugAttributes |= Source;
+                       } else if (DO_NOT_GENERATE.equals(optionValue)) {
+                               this.produceDebugAttributes &= ~Source;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_PreserveUnusedLocal)) != null) {
+                       if (PRESERVE.equals(optionValue)) {
+                               this.preserveAllLocalVariables = true;
+                       } else if (OPTIMIZE_OUT.equals(optionValue)) {
+                               this.preserveAllLocalVariables = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportDeprecationInDeprecatedCode)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportDeprecationInsideDeprecatedCode = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportDeprecationInsideDeprecatedCode = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportDeprecationWhenOverridingDeprecatedMethod)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportDeprecationWhenOverridingDeprecatedMethod = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportDeprecationWhenOverridingDeprecatedMethod = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportUnusedDeclaredThrownExceptionWhenOverriding = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportUnusedDeclaredThrownExceptionWhenOverriding = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_Compliance)) != null) {
+                       long level = versionToJdkLevel(optionValue);
+                       if (level != 0) this.complianceLevel = level;
+               }
+               if ((optionValue = optionsMap.get(OPTION_Source)) != null) {
+                       long level = versionToJdkLevel(optionValue);
+                       if (level != 0) this.sourceLevel = level;
+               }
+               if ((optionValue = optionsMap.get(OPTION_TargetPlatform)) != null) {
+                       long level = versionToJdkLevel(optionValue);
+                       if (level != 0) this.targetJDK = level;
+               }
+               if ((optionValue = optionsMap.get(OPTION_Encoding)) != null) {
+                       if (optionValue instanceof String) {
+                               this.defaultEncoding = null;
+                               String stringValue = (String) optionValue;
+                               if (stringValue.length() > 0){
+                                       try { 
+                                               new InputStreamReader(new ByteArrayInputStream(new byte[0]), stringValue);
+                                               this.defaultEncoding = stringValue;
+                                       } catch(UnsupportedEncodingException e){
+                                               // ignore unsupported encoding
+                                       }
+                               }
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_PrivateConstructorAccess)) != null) {
+                       long level = versionToJdkLevel(optionValue);
+                       if (level >= JDK1_3) this.isPrivateConstructorAccessChangingVisibility = true;
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameterWhenImplementingAbstract)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportUnusedParameterWhenImplementingAbstract = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportUnusedParameterWhenImplementingAbstract = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameterWhenOverridingConcrete)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportUnusedParameterWhenOverridingConcrete = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportUnusedParameterWhenOverridingConcrete = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportSpecialParameterHidingField)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportSpecialParameterHidingField = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportSpecialParameterHidingField = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_MaxProblemPerUnit)) != null) {
+                       if (optionValue instanceof String) {
+                               String stringValue = (String) optionValue;
+                               try {
+                                       int val = Integer.parseInt(stringValue);
+                                       if (val >= 0) this.maxProblemsPerUnit = val;
+                               } catch(NumberFormatException e){
+                                       // ignore ill-formatted limit
+                               }                               
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_TaskTags)) != null) {
+                       if (optionValue instanceof String) {
+                               String stringValue = (String) optionValue;
+                               if (stringValue.length() == 0) {
+                                       this.taskTags = null;
+                               } else {
+                                       this.taskTags = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+                               }
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_TaskPriorities)) != null) {
+                       if (optionValue instanceof String) {
+                               String stringValue = (String) optionValue;
+                               if (stringValue.length() == 0) {
+                                       this.taskPriorites = null;
+                               } else {
+                                       this.taskPriorites = CharOperation.splitAndTrimOn(',', stringValue.toCharArray());
+                               }
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_TaskCaseSensitive)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.isTaskCaseSensitive = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.isTaskCaseSensitive = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_InlineJsr)) != null) {
+                       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);
+               if ((optionValue = optionsMap.get(OPTION_ReportOverridingPackageDefaultMethod)) != null) updateSeverity(OverriddenPackageDefaultMethod, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportDeprecation)) != null) updateSeverity(UsingDeprecatedAPI, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportHiddenCatchBlock)) != null) updateSeverity(MaskedCatchBlock, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedLocal)) != null) updateSeverity(UnusedLocalVariable, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedParameter)) != null) updateSeverity(UnusedArgument, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedImport)) != null) updateSeverity(UnusedImport, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedPrivateMember)) != null) updateSeverity(UnusedPrivateMember, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnusedDeclaredThrownException)) != null) updateSeverity(UnusedDeclaredThrownException, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportNoImplicitStringConversion)) != null) updateSeverity(NoImplicitStringConversion, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportSyntheticAccessEmulation)) != null) updateSeverity(AccessEmulation, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportLocalVariableHiding)) != null) updateSeverity(LocalVariableHiding, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportFieldHiding)) != null) updateSeverity(FieldHiding, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportPossibleAccidentalBooleanAssignment)) != null) updateSeverity(AccidentalBooleanAssign, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_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_ReportNonStaticAccessToStatic)) != null) updateSeverity(NonStaticAccessToStatic, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportIndirectStaticAccess)) != null) updateSeverity(IndirectStaticAccess, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportIncompatibleNonInheritedInterfaceMethod)) != null) updateSeverity(IncompatibleNonInheritedInterfaceMethod, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUndocumentedEmptyBlock)) != null) updateSeverity(UndocumentedEmptyBlock, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryTypeCheck)) != null) updateSeverity(UnnecessaryTypeCheck, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportFinallyBlockNotCompletingNormally)) != null) updateSeverity(FinallyBlockNotCompleting, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnqualifiedFieldAccess)) != null) updateSeverity(UnqualifiedFieldAccess, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportNoEffectAssignment)) != null) updateSeverity(NoEffectAssignment, optionValue);
+               if ((optionValue = optionsMap.get(OPTION_ReportUnnecessaryElse)) != null) updateSeverity(UnnecessaryElse, optionValue);
+
+               // Javadoc options
+               if ((optionValue = optionsMap.get(OPTION_DocCommentSupport)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.docCommentSupport = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.docCommentSupport = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadoc)) != null) {
+                       updateSeverity(InvalidJavadoc, optionValue);
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTagsVisibility)) != null) {
+                       if (PUBLIC.equals(optionValue)) {
+                               this.reportInvalidJavadocTagsVisibility = AccPublic;
+                       } else if (PROTECTED.equals(optionValue)) {
+                               this.reportInvalidJavadocTagsVisibility = AccProtected;
+                       } else if (DEFAULT.equals(optionValue)) {
+                               this.reportInvalidJavadocTagsVisibility = AccDefault;
+                       } else if (PRIVATE.equals(optionValue)) {
+                               this.reportInvalidJavadocTagsVisibility = AccPrivate;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportInvalidJavadocTags)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportInvalidJavadocTags= true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportInvalidJavadocTags = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTags)) != null) {
+                       updateSeverity(MissingJavadocTags, optionValue);
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagsVisibility)) != null) {
+                       if (PUBLIC.equals(optionValue)) {
+                               this.reportMissingJavadocTagsVisibility = AccPublic;
+                       } else if (PROTECTED.equals(optionValue)) {
+                               this.reportMissingJavadocTagsVisibility = AccProtected;
+                       } else if (DEFAULT.equals(optionValue)) {
+                               this.reportMissingJavadocTagsVisibility = AccDefault;
+                       } else if (PRIVATE.equals(optionValue)) {
+                               this.reportMissingJavadocTagsVisibility = AccPrivate;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocTagsOverriding)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportMissingJavadocTagsOverriding = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportMissingJavadocTagsOverriding = false;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocComments)) != null) {
+                       updateSeverity(MissingJavadocComments, optionValue);
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocCommentsVisibility)) != null) {
+                       if (PUBLIC.equals(optionValue)) {
+                               this.reportMissingJavadocCommentsVisibility = AccPublic;
+                       } else if (PROTECTED.equals(optionValue)) {
+                               this.reportMissingJavadocCommentsVisibility = AccProtected;
+                       } else if (DEFAULT.equals(optionValue)) {
+                               this.reportMissingJavadocCommentsVisibility = AccDefault;
+                       } else if (PRIVATE.equals(optionValue)) {
+                               this.reportMissingJavadocCommentsVisibility = AccPrivate;
+                       }
+               }
+               if ((optionValue = optionsMap.get(OPTION_ReportMissingJavadocCommentsOverriding)) != null) {
+                       if (ENABLED.equals(optionValue)) {
+                               this.reportMissingJavadocCommentsOverriding = true;
+                       } else if (DISABLED.equals(optionValue)) {
+                               this.reportMissingJavadocCommentsOverriding = false;
+                       }
+               }
+       }
+
+       public String toString() {
+       
+               StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$
+               buf.append("\n\t- local variables debug attributes: ").append((this.produceDebugAttributes & Vars) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- line number debug attributes: ").append((this.produceDebugAttributes & Lines) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- source debug attributes: ").append((this.produceDebugAttributes & Source) != 0 ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- preserve all local variables: ").append(this.preserveAllLocalVariables ? "ON" : " OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- method with constructor name: ").append(getSeverityString(MethodWithConstructorName)); //$NON-NLS-1$
+               buf.append("\n\t- overridden package default method: ").append(getSeverityString(OverriddenPackageDefaultMethod)); //$NON-NLS-1$
+               buf.append("\n\t- deprecation: ").append(getSeverityString(UsingDeprecatedAPI)); //$NON-NLS-1$
+               buf.append("\n\t- masked catch block: ").append(getSeverityString(MaskedCatchBlock)); //$NON-NLS-1$
+               buf.append("\n\t- unused local variable: ").append(getSeverityString(UnusedLocalVariable)); //$NON-NLS-1$
+               buf.append("\n\t- unused parameter: ").append(getSeverityString(UnusedArgument)); //$NON-NLS-1$
+               buf.append("\n\t- unused import: ").append(getSeverityString(UnusedImport)); //$NON-NLS-1$
+               buf.append("\n\t- synthetic access emulation: ").append(getSeverityString(AccessEmulation)); //$NON-NLS-1$
+               buf.append("\n\t- assignment with no effect: ").append(getSeverityString(NoEffectAssignment)); //$NON-NLS-1$
+               buf.append("\n\t- non externalized string: ").append(getSeverityString(NonExternalizedString)); //$NON-NLS-1$
+               buf.append("\n\t- static access receiver: ").append(getSeverityString(NonStaticAccessToStatic)); //$NON-NLS-1$
+               buf.append("\n\t- indirect static access: ").append(getSeverityString(IndirectStaticAccess)); //$NON-NLS-1$
+               buf.append("\n\t- incompatible non inherited interface method: ").append(getSeverityString(IncompatibleNonInheritedInterfaceMethod)); //$NON-NLS-1$
+               buf.append("\n\t- unused private member: ").append(getSeverityString(UnusedPrivateMember)); //$NON-NLS-1$
+               buf.append("\n\t- local variable hiding another variable: ").append(getSeverityString(LocalVariableHiding)); //$NON-NLS-1$
+               buf.append("\n\t- field hiding another variable: ").append(getSeverityString(FieldHiding)); //$NON-NLS-1$
+               buf.append("\n\t- possible accidental boolean assignment: ").append(getSeverityString(AccidentalBooleanAssign)); //$NON-NLS-1$
+               buf.append("\n\t- superfluous semicolon: ").append(getSeverityString(EmptyStatement)); //$NON-NLS-1$
+               buf.append("\n\t- uncommented empty block: ").append(getSeverityString(UndocumentedEmptyBlock)); //$NON-NLS-1$
+               buf.append("\n\t- unnecessary type check: ").append(getSeverityString(UnnecessaryTypeCheck)); //$NON-NLS-1$
+               buf.append("\n\t- 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+ 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$
+               buf.append("\n\t\t+ report missing javadoc tags in overriding methods: ").append(this.reportMissingJavadocTagsOverriding ? ENABLED : DISABLED); //$NON-NLS-1$
+               buf.append("\n\t\t+ missing javadoc comments: ").append(getSeverityString(MissingJavadocComments)); //$NON-NLS-1$
+               buf.append("\n\t\t+ visibility level to report missing javadoc comments: ").append(getVisibilityString(this.reportMissingJavadocCommentsVisibility)); //$NON-NLS-1$
+               buf.append("\n\t\t+ report missing javadoc comments in overriding methods: ").append(this.reportMissingJavadocCommentsOverriding ? ENABLED : DISABLED); //$NON-NLS-1$
+               buf.append("\n\t- finally block not completing normally: ").append(getSeverityString(FinallyBlockNotCompleting)); //$NON-NLS-1$
+               buf.append("\n\t- unused declared thrown exception: ").append(getSeverityString(UnusedDeclaredThrownException)); //$NON-NLS-1$
+               buf.append("\n\t- unused declared thrown exception when overriding: ").append(this.reportUnusedDeclaredThrownExceptionWhenOverriding ? ENABLED : DISABLED); //$NON-NLS-1$
+               buf.append("\n\t- unnecessary else: ").append(getSeverityString(UnnecessaryElse)); //$NON-NLS-1$
+               buf.append("\n\t- JDK compliance level: "+ versionFromJdkLevel(this.complianceLevel)); //$NON-NLS-1$
+               buf.append("\n\t- JDK source level: "+ versionFromJdkLevel(this.sourceLevel)); //$NON-NLS-1$
+               buf.append("\n\t- JDK target level: "+ versionFromJdkLevel(this.targetJDK)); //$NON-NLS-1$
+               buf.append("\n\t- private constructor access: ").append(this.isPrivateConstructorAccessChangingVisibility ? "extra argument" : "make default access"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- verbose : ").append(this.verbose ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- produce reference info : ").append(this.produceReferenceInfo ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- parse literal expressions as constants : ").append(this.parseLiteralExpressionsAsConstants ? "ON" : "OFF"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+               buf.append("\n\t- encoding : ").append(this.defaultEncoding == null ? "<default>" : this.defaultEncoding); //$NON-NLS-1$ //$NON-NLS-2$
+               buf.append("\n\t- task tags: ").append(this.taskTags == null ? "" : new String(CharOperation.concatWith(this.taskTags,',')));  //$NON-NLS-1$ //$NON-NLS-2$
+               buf.append("\n\t- task priorities : ").append(this.taskPriorites == null ? "" : new String(CharOperation.concatWith(this.taskPriorites,','))); //$NON-NLS-1$ //$NON-NLS-2$
+               buf.append("\n\t- report deprecation inside deprecated code : ").append(this.reportDeprecationInsideDeprecatedCode ? ENABLED : DISABLED); //$NON-NLS-1$
+               buf.append("\n\t- report deprecation when overriding deprecated method : ").append(this.reportDeprecationWhenOverridingDeprecatedMethod ? ENABLED : DISABLED); //$NON-NLS-1$
+               buf.append("\n\t- report unused parameter when implementing abstract method : ").append(this.reportUnusedParameterWhenImplementingAbstract ? ENABLED : DISABLED); //$NON-NLS-1$
+               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$
+               return buf.toString();
+       }
+
+       void updateSeverity(long irritant, Object severityString) {
+               if (ERROR.equals(severityString)) {
+                       this.errorThreshold |= irritant;
+                       this.warningThreshold &= ~irritant;
+               } else if (WARNING.equals(severityString)) {
+                       this.errorThreshold &= ~irritant;
+                       this.warningThreshold |= irritant;
+               } else if (IGNORE.equals(severityString)) {
+                       this.errorThreshold &= ~irritant;
+                       this.warningThreshold &= ~irritant;
+               }
+       }                               
+       public static long versionToJdkLevel(Object versionID) {
+               if (VERSION_1_1.equals(versionID)) {
+                       return JDK1_1;
+               } else if (VERSION_1_2.equals(versionID)) {
+                       return JDK1_2;
+               } else if (VERSION_1_3.equals(versionID)) {
+                       return JDK1_3;
+               } else if (VERSION_1_4.equals(versionID)) {
+                       return JDK1_4;
+               } else if (VERSION_1_5.equals(versionID)) {
+                       return JDK1_5;
+               }
+               return 0; // unknown
+       }
+
+       public static String versionFromJdkLevel(long jdkLevel) {
+               if (jdkLevel == JDK1_1) {
+                       return VERSION_1_1;
+               } else if (jdkLevel == JDK1_2) {
+                       return VERSION_1_2;
+               } else if (jdkLevel == JDK1_3) {
+                       return VERSION_1_3;
+               } else if (jdkLevel == JDK1_4) {
+                       return VERSION_1_4;
+               } else if (jdkLevel == JDK1_5) {
+                       return VERSION_1_5;
+               }
+               return ""; // unknown version //$NON-NLS-1$
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/Constant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/Constant.java
new file mode 100644 (file)
index 0000000..f82b409
--- /dev/null
@@ -0,0 +1,1611 @@
+/*******************************************************************************
+ * 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.impl;
+
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public abstract class Constant implements TypeIds, OperatorIds {
+       
+       public static final Constant NotAConstant = new DoubleConstant(Double.NaN);
+
+       public static final IntConstant Zero = new IntConstant(0);
+       public static final IntConstant Two = new IntConstant(2);
+       public static final IntConstant One = new IntConstant(1);
+       
+       public boolean booleanValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotCastedInto",typeName(),"boolean")); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+
+       public byte byteValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotCastedInto",typeName(),"byte")); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+
+       public final Constant castTo(int conversionToTargetType){
+               //the cast is an int of the form
+               // (castId<<4)+typeId (in order to follow the
+               //user written style (cast)expression ....
+       
+               if (this == NotAConstant) return NotAConstant;
+               switch(conversionToTargetType){
+                       case T_undefined :                                              return this;
+       //            TARGET TYPE  <- FROM TYPE
+       //          case (T_undefined<<4)+T_undefined    : return NotAConstant;  
+       //          case (T_undefined<<4)+T_byte                 : return NotAConstant;   
+       //          case (T_undefined<<4)+T_long                 : return NotAConstant;   
+       //          case (T_undefined<<4)+T_short                : return NotAConstant;   
+       //          case (T_undefined<<4)+T_void                 : return NotAConstant;   
+       //          case (T_undefined<<4)+T_String       : return NotAConstant;   
+       //          case (T_undefined<<4)+T_Object       : return NotAConstant;   
+       //          case (T_undefined<<4)+T_double       : return NotAConstant;   
+       //          case (T_undefined<<4)+T_float                : return NotAConstant;   
+       //          case (T_undefined<<4)+T_boolean      : return NotAConstant;   
+       //          case (T_undefined<<4)+T_char                 : return NotAConstant;   
+       //          case (T_undefined<<4)+T_int                  : return NotAConstant;   
+               
+       //          case (T_byte<<4)+T_undefined         : return NotAConstant;   
+                   case (T_byte<<4)+T_byte              : return this;  
+                   case (T_byte<<4)+T_long              : return Constant.fromValue((byte)this.longValue()); 
+                   case (T_byte<<4)+T_short             : return Constant.fromValue((byte)this.shortValue());    
+       //          case (T_byte<<4)+T_void              : return NotAConstant;   
+       //          case (T_byte<<4)+T_String            : return NotAConstant;   
+       //          case (T_byte<<4)+T_Object            : return NotAConstant;   
+                   case (T_byte<<4)+T_double            : return Constant.fromValue((byte)this.doubleValue());    
+                   case (T_byte<<4)+T_float             : return Constant.fromValue((byte)this.floatValue());    
+       //          case (T_byte<<4)+T_boolean           : return NotAConstant;   
+                   case (T_byte<<4)+T_char              : return Constant.fromValue((byte)this.charValue());    
+                   case (T_byte<<4)+T_int               : return Constant.fromValue((byte)this.intValue());    
+       
+       //          case (T_long<<4)+T_undefined         : return NotAConstant;   
+                   case (T_long<<4)+T_byte              : return Constant.fromValue((long)this.byteValue()); 
+                   case (T_long<<4)+T_long              : return this; 
+                   case (T_long<<4)+T_short             : return Constant.fromValue((long)this.shortValue()); 
+       //          case (T_long<<4)+T_void              : return NotAConstant;   
+       //          case (T_long<<4)+T_String            : return NotAConstant;   
+       //          case (T_long<<4)+T_Object            : return NotAConstant;   
+                   case (T_long<<4)+T_double            : return Constant.fromValue((long)this.doubleValue());   
+                   case (T_long<<4)+T_float             : return Constant.fromValue((long)this.floatValue());  
+       //          case (T_long<<4)+T_boolean           : return NotAConstant;   
+                   case (T_long<<4)+T_char              : return Constant.fromValue((long)this.charValue()); 
+                   case (T_long<<4)+T_int               : return Constant.fromValue((long)this.intValue()); 
+       
+       //          case (T_short<<4)+T_undefined        : return NotAConstant;   
+                   case (T_short<<4)+T_byte             : return Constant.fromValue((short)this.byteValue());
+                   case (T_short<<4)+T_long             : return Constant.fromValue((short)this.longValue()); 
+                   case (T_short<<4)+T_short            : return this;  
+       //          case (T_short<<4)+T_void             : return NotAConstant;   
+       //          case (T_short<<4)+T_String           : return NotAConstant;   
+       //          case (T_short<<4)+T_Object           : return NotAConstant;   
+                   case (T_short<<4)+T_double           : return Constant.fromValue((short)this.doubleValue());   
+                   case (T_short<<4)+T_float            : return Constant.fromValue((short)this.floatValue());   
+       //          case (T_short<<4)+T_boolean          : return NotAConstant;   
+                   case (T_short<<4)+T_char             : return Constant.fromValue((short)this.charValue());  
+                   case (T_short<<4)+T_int              : return Constant.fromValue((short)this.intValue());  
+       
+       //          case (T_void<<4)+T_undefined         : return NotAConstant;   
+       //          case (T_void<<4)+T_byte              : return NotAConstant;   
+       //          case (T_void<<4)+T_long              : return NotAConstant;   
+       //          case (T_void<<4)+T_short             : return NotAConstant;   
+       //          case (T_void<<4)+T_void              : return NotAConstant;   
+       //          case (T_void<<4)+T_String            : return NotAConstant;   
+       //          case (T_void<<4)+T_Object            : return NotAConstant;   
+       //          case (T_void<<4)+T_double            : return NotAConstant;   
+       //          case (T_void<<4)+T_float             : return NotAConstant;   
+       //          case (T_void<<4)+T_boolean           : return NotAConstant;   
+       //          case (T_void<<4)+T_char              : return NotAConstant;   
+       //          case (T_void<<4)+T_int               : return NotAConstant;   
+       
+       //          case (T_String<<4)+T_undefined   : return NotAConstant;   
+       //          case (T_String<<4)+T_byte            : return NotAConstant;   
+       //          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_String<<4)+T_Object          : return NotAConstant;   
+       //          case (T_String<<4)+T_double          : return NotAConstant;   
+       //          case (T_String<<4)+T_float           : return NotAConstant;   
+       //          case (T_String<<4)+T_boolean         : return NotAConstant;   
+       //          case (T_String<<4)+T_char            : return NotAConstant;   
+       //          case (T_String<<4)+T_int             : return NotAConstant;   
+       
+       //          case (T_Object<<4)+T_undefined      : return NotAConstant;   
+       //          case (T_Object<<4)+T_byte                   : return NotAConstant;   
+       //          case (T_Object<<4)+T_long                   : return NotAConstant;   
+       //          case (T_Object<<4)+T_short                  : return NotAConstant;   
+       //          case (T_Object<<4)+T_void                   : return NotAConstant;   
+       //          case (T_Object<<4)+T_String                 : return NotAConstant;   
+       //          case (T_Object<<4)+T_Object                 : return NotAConstant;   
+       //          case (T_Object<<4)+T_double                 : return NotAConstant;   
+       //          case (T_Object<<4)+T_float                  : return NotAConstant;   
+       //          case (T_Object<<4)+T_boolean                : return NotAConstant;   
+       //          case (T_Object<<4)+T_char                   : return NotAConstant;   
+       //          case (T_Object<<4)+T_int                    : return NotAConstant;   
+       
+       //          case (T_double<<4)+T_undefined      : return NotAConstant;   
+                   case (T_double<<4)+T_byte                   : return Constant.fromValue((double)this.byteValue());   
+                   case (T_double<<4)+T_long                   : return Constant.fromValue((double)this.longValue());   
+                   case (T_double<<4)+T_short                  : return Constant.fromValue((double)this.shortValue());   
+       //          case (T_double<<4)+T_void                   : return NotAConstant;   
+       //          case (T_double<<4)+T_String                 : return NotAConstant;   
+       //          case (T_double<<4)+T_Object                 : return NotAConstant;   
+                   case (T_double<<4)+T_double                 : return this;   
+                   case (T_double<<4)+T_float                  : return Constant.fromValue((double)this.floatValue());   
+       //          case (T_double<<4)+T_boolean                : return NotAConstant;   
+                   case (T_double<<4)+T_char                   : return Constant.fromValue((double)this.charValue());   
+                   case (T_double<<4)+T_int                    : return Constant.fromValue((double)this.intValue());  
+       
+       //          case (T_float<<4)+T_undefined        : return NotAConstant;   
+                   case (T_float<<4)+T_byte             : return Constant.fromValue((float)this.byteValue());   
+                   case (T_float<<4)+T_long             : return Constant.fromValue((float)this.longValue());   
+                   case (T_float<<4)+T_short            : return Constant.fromValue((float)this.shortValue());   
+       //          case (T_float<<4)+T_void             : return NotAConstant;   
+       //          case (T_float<<4)+T_String           : return NotAConstant;   
+       //          case (T_float<<4)+T_Object           : return NotAConstant;   
+                   case (T_float<<4)+T_double           : return Constant.fromValue((float)this.doubleValue());   
+                   case (T_float<<4)+T_float            : return this;   
+       //          case (T_float<<4)+T_boolean          : return NotAConstant;   
+                   case (T_float<<4)+T_char             : return Constant.fromValue((float)this.charValue());   
+                   case (T_float<<4)+T_int              : return Constant.fromValue((float)this.intValue());   
+       
+       //          case (T_boolean<<4)+T_undefined              : return NotAConstant;   
+       //          case (T_boolean<<4)+T_byte                           : return NotAConstant;   
+       //          case (T_boolean<<4)+T_long                           : return NotAConstant;   
+       //          case (T_boolean<<4)+T_short                          : return NotAConstant;   
+       //          case (T_boolean<<4)+T_void                           : return NotAConstant;   
+       //          case (T_boolean<<4)+T_String                         : return NotAConstant;   
+       //          case (T_boolean<<4)+T_Object                         : return NotAConstant;   
+       //          case (T_boolean<<4)+T_double                         : return NotAConstant;   
+       //          case (T_boolean<<4)+T_float                          : return NotAConstant;   
+                   case (T_boolean<<4)+T_boolean                        : return this;  
+       //          case (T_boolean<<4)+T_char                           : return NotAConstant;   
+       //          case (T_boolean<<4)+T_int                            : return NotAConstant;   
+               
+       //          case (T_char<<4)+T_undefined         : return NotAConstant;   
+                   case (T_char<<4)+T_byte              : return Constant.fromValue((char)this.byteValue());  
+                   case (T_char<<4)+T_long              : return Constant.fromValue((char)this.longValue());  
+                   case (T_char<<4)+T_short             : return Constant.fromValue((char)this.shortValue());  
+       //          case (T_char<<4)+T_void              : return NotAConstant;   
+       //          case (T_char<<4)+T_String            : return NotAConstant;   
+       //          case (T_char<<4)+T_Object            : return NotAConstant;   
+                   case (T_char<<4)+T_double            : return Constant.fromValue((char)this.doubleValue());   
+                   case (T_char<<4)+T_float             : return Constant.fromValue((char)this.floatValue());   
+       //          case (T_char<<4)+T_boolean           : return NotAConstant;   
+                   case (T_char<<4)+T_char              : return this;  
+                   case (T_char<<4)+T_int               : return Constant.fromValue((char)this.intValue());  
+               
+       //          case (T_int<<4)+T_undefined          : return NotAConstant;   
+                   case (T_int<<4)+T_byte               : return Constant.fromValue((int)this.byteValue());  
+                   case (T_int<<4)+T_long               : return Constant.fromValue((int)this.longValue());  
+                   case (T_int<<4)+T_short              : return Constant.fromValue((int)this.shortValue());  
+       //          case (T_int<<4)+T_void               : return NotAConstant;   
+       //          case (T_int<<4)+T_String             : return NotAConstant;   
+       //          case (T_int<<4)+T_Object             : return NotAConstant;   
+                   case (T_int<<4)+T_double             : return Constant.fromValue((int)this.doubleValue());   
+                   case (T_int<<4)+T_float              : return Constant.fromValue((int)this.floatValue());   
+       //          case (T_int<<4)+T_boolean            : return NotAConstant;   
+                   case (T_int<<4)+T_char               : return Constant.fromValue((int)this.charValue());  
+                   case (T_int<<4)+T_int                        : return this;  
+       
+               }
+       
+               return NotAConstant;
+       }
+       
+       public char charValue() {
+               
+               throw new ShouldNotImplement(Util.bind("constant.cannotCastedInto",typeName(),"char")); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+       
+       public static final Constant computeConstantOperation(Constant cst, int id, int operator) {
+
+               switch (operator) {
+                       case NOT        :       
+                                                       return Constant.fromValue(!cst.booleanValue());
+                       case PLUS       :       return cst; 
+                       case MINUS      :       //the two special -9223372036854775808L and -2147483648 are inlined at parseTime
+                                                       switch (id){
+                                                               case T_float  : float f;
+                                                                                               if ( (f= cst.floatValue()) == 0.0f)
+                                                                                               { //positive and negative 0....
+                                                                                                       if (Float.floatToIntBits(f) == 0)
+                                                                                                               return Constant.fromValue(-0.0f);
+                                                                                                       else
+                                                                                                               return Constant.fromValue(0.0f);}
+                                                                                               break; //default case
+                                                               case T_double : double d;
+                                                                                               if ( (d= cst.doubleValue()) == 0.0d)
+                                                                                               { //positive and negative 0....
+                                                                                                       if (Double.doubleToLongBits(d) == 0)
+                                                                                                               return Constant.fromValue(-0.0d);
+                                                                                                       else
+                                                                                                               return Constant.fromValue(0.0d);}
+                                                                                               break; //default case
+                                                       }
+                                                       return computeConstantOperationMINUS(Zero,T_int,operator,cst,id);
+                       case TWIDDLE:   
+                               switch (id){
+                                       case T_char :   return Constant.fromValue(~ cst.charValue());
+                                       case T_byte:    return Constant.fromValue(~ cst.byteValue());
+                                       case T_short:   return Constant.fromValue(~ cst.shortValue());
+                                       case T_int:             return Constant.fromValue(~ cst.intValue());
+                                       case T_long:    return Constant.fromValue(~ cst.longValue());
+                                       default : return NotAConstant;
+                               } 
+                       default : return NotAConstant;
+               }
+       } 
+
+       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);
+       
+                       default : return NotAConstant;
+               }
+       }
+       
+       public static final Constant computeConstantOperationAND(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_boolean :                return Constant.fromValue(left.booleanValue() & right.booleanValue());
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() & right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() & right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() & right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() & right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() & right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() & right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() & right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() & right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() & right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() & right.byteValue());
+                                       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());
+                               }
+                       }
+               
+               return NotAConstant;
+       } 
+               
+       public static final Constant computeConstantOperationAND_AND(Constant left, int leftId, int operator, 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) {
+               // division by zero must be handled outside this method (error reporting)
+       
+               switch (leftId){
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() / right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() / right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() / right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() / right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() / right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() / right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() / right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() / right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() / right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() / right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() / right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() / right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() / right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() / right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() / right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() / right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() / right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() / right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() / right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() / right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() / right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() / right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() / right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() / right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() / right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() / right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() / right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() / right.byteValue());
+                                       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());
+                               }
+       
+                       }
+               
+               return NotAConstant;
+       } 
+               
+       public static final Constant computeConstantOperationEQUAL_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_boolean :
+                               if (rightId == T_boolean) {
+                                       return Constant.fromValue(left.booleanValue() == right.booleanValue());
+                               }
+                       break;
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() == right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() == right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() == right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() == right.byteValue());
+                                       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());}
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() == right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() == right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() == right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() == right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() == right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() == right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() == right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() == right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() == right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() == right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() == right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() == right.byteValue());
+                                       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());
+                               }
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() == right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() == right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() == right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() == right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() == right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() == right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() == right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() == right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() == right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() == right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() == right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() == right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_String :
+                               if (rightId == T_String) {
+                                       //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) { 
+                                       return Constant.fromValue(false);
+                               } else {
+                                       if (rightId == T_null) { 
+                                               return Constant.fromValue(true);
+                                       }
+                               }
+                       }
+               
+               return Constant.fromValue(false);
+       }
+               
+       public static final Constant computeConstantOperationGREATER(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char : 
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() > right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() > right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() > right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() > right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() > right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() > right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() > right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() > right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() > right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() > right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() > right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() > right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() > right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() > right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() > right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() > right.byteValue());
+                                       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());
+                               }
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() > right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() > right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() > right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() > right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() > right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() > right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() > right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() > right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() > right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() > right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() > right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() > right.byteValue());
+                                       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());
+                               }
+                               
+                       }
+               
+               return NotAConstant;
+       }
+
+       public static final Constant computeConstantOperationGREATER_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char : 
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() >= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() >= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() >= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() >= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() >= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() >= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() >= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() >= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() >= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() >= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() >= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() >= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() >= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() >= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() >= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() >= right.byteValue());
+                                       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());
+                               }
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() >= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() >= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() >= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() >= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() >= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() >= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() >= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() >= right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() >= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() >= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() >= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() >= right.byteValue());
+                                       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());
+                               }
+                               
+                       }
+               
+               return NotAConstant;
+       }  
+               
+       public static final Constant computeConstantOperationLEFT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() << right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() << right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() << right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() << right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() << right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() << right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() << right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() << right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() << right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() << right.byteValue());
+                                       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());
+                               }
+       
+                       }
+       
+               return NotAConstant;
+       } 
+               
+       public static final Constant computeConstantOperationLESS(Constant left, int leftId, int operator, Constant right, int rightId) { 
+               
+               switch (leftId){
+                       case T_char : 
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() < right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() < right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() < right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() < right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() < right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() < right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() < right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() < right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() < right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() < right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() < right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() < right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() < right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() < right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() < right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() < right.byteValue());
+                                       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());
+                               }
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() < right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() < right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() < right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() < right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() < right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() < right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() < right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() < right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() < right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() < right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() < right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() < right.byteValue());
+                                       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());
+                               }
+                               
+                       }
+               
+               return NotAConstant;
+       }
+               
+       public static final Constant computeConstantOperationLESS_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char : 
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() <= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() <= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() <= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() <= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() <= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() <= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() <= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() <= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() <= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() <= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() <= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() <= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() <= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() <= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() <= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() <= right.byteValue());
+                                       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());
+                               }
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() <= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() <= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() <= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() <= right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() <= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() <= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() <= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() <= right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() <= right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() <= right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() <= right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() <= right.byteValue());
+                                       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());
+                               }
+                       }
+               
+               return NotAConstant;
+       }  
+       
+       public static final Constant computeConstantOperationMINUS(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char : 
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() - right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() - right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() - right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() - right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() - right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() - right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() - right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() - right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() - right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() - right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() - right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() - right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() - right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() - right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() - right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() - right.byteValue());
+                                       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());
+                               }
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() - right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() - right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() - right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() - right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() - right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() - right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() - right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() - right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() - right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() - right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() - right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() - right.byteValue());
+                                       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());
+                               }
+                               
+                       }
+               
+               return NotAConstant;
+       }
+       
+       public static final Constant computeConstantOperationMULTIPLY(Constant left, int leftId, int operator, Constant right, int rightId) {
+       
+               switch (leftId){
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() * right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() * right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() * right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() * right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() * right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() * right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() * right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() * right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() * right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() * right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() * right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() * right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() * right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() * right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() * right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() * right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() * right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() * right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() * right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() * right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() * right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() * right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() * right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() * right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() * right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() * right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() * right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() * right.byteValue());
+                                       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());
+                               }
+                       }
+       
+               return NotAConstant;
+       }
+       
+       public static final Constant computeConstantOperationOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_boolean :                return Constant.fromValue(left.booleanValue() | right.booleanValue());
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() | right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() | right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() | right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() | right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() | right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() | right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() | right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() | right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() | right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() | right.byteValue());
+                                       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());
+                               }
+       
+                       }       
+       
+               return NotAConstant;
+       }
+       
+       public static final Constant computeConstantOperationOR_OR(Constant left, int leftId, int operator, 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) {
+               
+               switch (leftId){
+                       case T_Object :
+                               if (rightId == T_String) {
+                                       return Constant.fromValue(left.stringValue() + right.stringValue());
+                               }
+                       case T_boolean :
+                               if (rightId == T_String) {
+                                       return Constant.fromValue(left.stringValue() + right.stringValue());
+                               }
+                       break;
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() + right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() + right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() + right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() + right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() + right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() + right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() + right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() + right.byteValue());
+                                       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()); 
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() + right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() + right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() + right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() + right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() + right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() + right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() + right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() + right.byteValue());
+                                       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()); 
+                               }
+       
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() + right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() + right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() + right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() + right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() + right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() + right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() + right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() + right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() + right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() + right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() + right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() + right.byteValue());
+                                       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()); 
+                               }
+                       break;
+                       case T_String :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_float:   return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_double:  return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_byte:    return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_short:   return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_int:             return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_long:    return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_String:  return Constant.fromValue(left.stringValue() + right.stringValue()); 
+                                       case T_boolean: return Constant.fromValue(left.stringValue() + right.stringValue());
+                               }
+                       break;  
+                       case T_null :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_float:   return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_double:  return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_byte:    return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_short:   return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_int:             return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_long:    return Constant.fromValue(left.stringValue() + right.stringValue());
+                                       case T_String:  return Constant.fromValue(left.stringValue() + right.stringValue()); 
+                               }
+                               
+                       }
+               
+               return NotAConstant;
+       }
+               
+       public static final Constant computeConstantOperationREMAINDER(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char : 
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() % right.charValue());
+                                       case T_float:   return Constant.fromValue(left.charValue() % right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.charValue() % right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() % right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_float :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.floatValue() % right.charValue());
+                                       case T_float:   return Constant.fromValue(left.floatValue() % right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.floatValue() % right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.floatValue() % right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_double :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.doubleValue() % right.charValue());
+                                       case T_float:   return Constant.fromValue(left.doubleValue() % right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.doubleValue() % right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.doubleValue() % right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() % right.charValue());
+                                       case T_float:   return Constant.fromValue(left.byteValue() % right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.byteValue() % right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() % right.byteValue());
+                                       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());
+                               }
+                       break;                  
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() % right.charValue());
+                                       case T_float:   return Constant.fromValue(left.shortValue() % right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.shortValue() % right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() % right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() % right.charValue());
+                                       case T_float:   return Constant.fromValue(left.intValue() % right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.intValue() % right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() % right.byteValue());
+                                       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());
+                               }
+                       break;          
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() % right.charValue());
+                                       case T_float:   return Constant.fromValue(left.longValue() % right.floatValue());
+                                       case T_double:  return Constant.fromValue(left.longValue() % right.doubleValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() % right.byteValue());
+                                       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());
+                               }
+                               
+                       }
+               
+               return NotAConstant;
+       } 
+       
+       public static final Constant computeConstantOperationRIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() >> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() >> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() >> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() >> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() >> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() >> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() >> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() >> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() >> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() >> right.byteValue());
+                                       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());
+                               }
+       
+                       }
+               
+               return NotAConstant;
+       }
+
+       public static final Constant computeConstantOperationUNSIGNED_RIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() >>> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() >>> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() >>> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() >>> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() >>> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() >>> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() >>> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() >>> right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() >>> right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() >>> right.byteValue());
+                                       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());
+                               }
+       
+                       }
+       
+               return NotAConstant;
+       }
+       
+       public static final Constant computeConstantOperationXOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+               
+               switch (leftId){
+                       case T_boolean :                return Constant.fromValue(left.booleanValue() ^ right.booleanValue());
+                       case T_char :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.charValue() ^ right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.charValue() ^ right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_byte :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.byteValue() ^ right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.byteValue() ^ right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_short :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.shortValue() ^ right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.shortValue() ^ right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_int :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.intValue() ^ right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.intValue() ^ right.byteValue());
+                                       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());
+                               }
+                       break;
+                       case T_long :
+                               switch (rightId){
+                                       case T_char :   return Constant.fromValue(left.longValue() ^ right.charValue());
+                                       case T_byte:    return Constant.fromValue(left.longValue() ^ right.byteValue());
+                                       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());
+                               }
+                       }
+       
+               return NotAConstant;
+       }
+
+       public double doubleValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotCastedInto",typeName(),"double")); //$NON-NLS-2$ //$NON-NLS-1$
+       }
+
+       public float floatValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotCastedInto",typeName(),"float")); //$NON-NLS-2$ //$NON-NLS-1$
+       }
+
+       public static Constant fromValue(byte value) {
+
+               return new ByteConstant(value);
+       }
+
+       public static Constant fromValue(char value) {
+
+               return new CharConstant(value);
+       }
+
+       public static Constant fromValue(double value) {
+
+               return new DoubleConstant(value);
+       }
+
+       public static Constant fromValue(float value) {
+
+               return new FloatConstant(value);
+       }
+
+       public static Constant fromValue(int value) {
+
+               return new IntConstant(value);
+       }
+
+       public static Constant fromValue(long value) {
+
+               return new LongConstant(value);
+       }
+
+       public static Constant fromValue(String value) {
+               
+               return new StringConstant(value);
+       }
+
+       public static Constant fromValue(short value) {
+
+               return new ShortConstant(value);
+       }
+
+       public static Constant fromValue(boolean value) {
+
+               return new BooleanConstant(value);
+       }
+
+       public int intValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotCastedInto",typeName(),"int")); //$NON-NLS-2$ //$NON-NLS-1$
+       }
+
+       public long longValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotCastedInto",typeName(),"long")); //$NON-NLS-2$ //$NON-NLS-1$
+       }
+
+       public short shortValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotConvertedTo",typeName(),"short")); //$NON-NLS-2$ //$NON-NLS-1$
+       }
+
+       public String stringValue() {
+
+               throw new ShouldNotImplement(Util.bind("constant.cannotConvertedTo",typeName(),"String")); //$NON-NLS-1$ //$NON-NLS-2$
+       }
+
+       public String toString(){
+       
+               if (this == NotAConstant) return "(Constant) NotAConstant"; //$NON-NLS-1$
+               return super.toString(); }
+
+       public abstract int typeID();
+
+       public String typeName() {
+               switch (typeID()) {
+                       case T_int : return "int"; //$NON-NLS-1$
+                       case T_byte : return "byte"; //$NON-NLS-1$
+                       case T_short : return "short"; //$NON-NLS-1$
+                       case T_char : return "char"; //$NON-NLS-1$
+                       case T_float : return "float"; //$NON-NLS-1$
+                       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_null : return "null";     //$NON-NLS-1$
+                       default: return "unknown"; //$NON-NLS-1$
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/DoubleConstant.java
new file mode 100644 (file)
index 0000000..ca72801
--- /dev/null
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.impl;
+
+public class DoubleConstant extends Constant {
+       
+       double value;
+       
+       public DoubleConstant(double value) {
+               this.value = value;
+       }
+       
+       public byte byteValue() {
+               return (byte) value;
+       }
+       
+       public char charValue() {
+               return (char) value;
+       }
+       
+       public double doubleValue() {
+               return this.value;
+       }
+       
+       public float floatValue() {
+               return (float) value;
+       }
+       
+       public int intValue() {
+               return (int) value;
+       }
+       
+       public long longValue() {
+               return (long) value;
+       }
+       
+       public short shortValue() {
+               return (short) value;
+       }
+       
+       public String stringValue() {
+               String s = Double.toString(value);
+               if (s == null) return "null"; //$NON-NLS-1$
+               return s;
+       }
+       
+       public String toString() {
+               if (this == NotAConstant)
+                       return "(Constant) NotAConstant"; //$NON-NLS-1$
+               return "(double)" + value;  //$NON-NLS-1$
+       }
+
+       public int typeID() {
+               return T_double;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/FloatConstant.java
new file mode 100644 (file)
index 0000000..6caec4d
--- /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.impl;
+
+public class FloatConstant extends Constant {
+       
+       float value;
+       
+       public FloatConstant(float value) {
+               this.value = value;
+       }
+       
+       public byte byteValue() {
+               return (byte) value;
+       }
+       
+       public char charValue() {
+               return (char) value;
+       }
+       
+       public double doubleValue() {
+               return value; // implicit cast to return type
+       }
+       
+       public float floatValue() {
+               return this.value;
+       }
+       
+       public int intValue() {
+               return (int) value;
+       }
+       
+       public long longValue() {
+               return (long) value;
+       }
+       
+       public short shortValue() {
+               return (short) value;
+       }
+       
+       public String stringValue() {
+               String s = Float.toString(value);
+               if (s == null) return "null"; //$NON-NLS-1$
+               return s;
+       }
+
+       public String toString() {
+               return "(float)" + value; //$NON-NLS-1$
+       } 
+
+       public int typeID() {
+               return T_float;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java b/src/java/org/eclipse/jdt/internal/compiler/impl/ITypeRequestor.java
new file mode 100644 (file)
index 0000000..52398d0
--- /dev/null
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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.impl;
+
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+import org.eclipse.jdt.internal.compiler.env.ISourceType;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+
+public interface ITypeRequestor {
+       
+       /**
+        * Accept the resolved binary form for the requested type.
+        */
+       void accept(IBinaryType binaryType, PackageBinding packageBinding);
+
+       /**
+        * Accept the requested type's compilation unit.
+        */
+       void accept(ICompilationUnit unit);
+
+       /**
+        * Accept the unresolved source forms for the requested type.
+        * Note that the multiple source forms can be answered, in case the target compilation unit
+        * contains multiple types. The first one is then guaranteed to be the one corresponding to the
+        * requested type.
+        */
+       void accept(ISourceType[] sourceType, PackageBinding packageBinding);
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/IntConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/IntConstant.java
new file mode 100644 (file)
index 0000000..8d54e90
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.impl;
+
+public class IntConstant extends Constant {
+       
+       int value;
+       
+       public IntConstant(int value) {
+               this.value = value;
+       }
+       
+       public byte byteValue() {
+               return (byte) value;
+       }
+       
+       public char charValue() {
+               return (char) value;
+       }
+       
+       public double doubleValue() {
+               return value; // implicit cast to return type
+       }
+       
+       public float floatValue() {
+               return value; // implicit cast to return type
+       }
+       
+       public int intValue() {
+               return value;
+       }
+       
+       public long longValue() {
+               return value; // implicit cast to return type
+       }
+       
+       public short shortValue() {
+               return (short) value;
+       }
+       
+       public String stringValue() {
+               //spec 15.17.11
+               String s = new Integer(value).toString();
+               if (s == null) return "null"; //$NON-NLS-1$
+               return s;
+       }
+
+       public String toString() {
+               return "(int)" + value; //$NON-NLS-1$
+       } 
+
+       public int typeID() {
+               return T_int;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/LongConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/LongConstant.java
new file mode 100644 (file)
index 0000000..c730665
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.impl;
+
+public class LongConstant extends Constant {
+       long value;
+public LongConstant(long value) {
+       this.value = value;
+}
+public byte byteValue() {
+       return (byte) value;
+}
+public char charValue() {
+       return (char) value;
+}
+public double doubleValue() {
+       return value; // implicit cast to return type
+}
+public float floatValue() {
+       return value; // implicit cast to return type
+}
+public int intValue() {
+       return (int) value;
+}
+public long longValue() {
+       return value; 
+}
+public short shortValue() {
+       return (short) value;
+}
+public String stringValue() {
+       //spec 15.17.11
+       
+       String s = new Long(value).toString() ;
+       if (s == null) return "null"; //$NON-NLS-1$
+       return s;
+}
+public String toString(){
+
+       return "(long)" + value ; } //$NON-NLS-1$
+public int typeID() {
+       return T_long;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java b/src/java/org/eclipse/jdt/internal/compiler/impl/ReferenceContext.java
new file mode 100644 (file)
index 0000000..f645b0a
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.impl;
+/*
+ * Implementors are valid compilation contexts from which we can
+ * escape in case of error:
+ *     For example: method, type or compilation unit.
+ */
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+public interface ReferenceContext {
+       void abort(int abortLevel, IProblem problem);
+       CompilationResult compilationResult();
+       void tagAsHavingErrors();
+       boolean hasErrors();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/ShortConstant.java
new file mode 100644 (file)
index 0000000..0bad92d
--- /dev/null
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.impl;
+
+public class ShortConstant extends Constant {
+       short value;
+public ShortConstant(short value) {
+       this.value = value;
+}
+public byte byteValue() {
+       return (byte) value;
+}
+public char charValue() {
+       return (char) value;
+}
+public double doubleValue() {
+       return value; // implicit cast to return type
+}
+public float floatValue() {
+       return value; // implicit cast to return type
+}
+public int intValue() {
+       return value; // implicit cast to return type
+}
+public long longValue() {
+       return value; // implicit cast to return type
+}
+public short shortValue() {
+       return value;
+}
+public String stringValue() {
+       //spec 15.17.11
+       
+       String s = new Integer(value).toString() ;
+       if (s == null) return "null"; //$NON-NLS-1$
+       return s;
+}
+public String toString(){
+
+       return "(short)" + value ; } //$NON-NLS-1$
+public int typeID() {
+       return T_short;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/impl/StringConstant.java b/src/java/org/eclipse/jdt/internal/compiler/impl/StringConstant.java
new file mode 100644 (file)
index 0000000..0248540
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.impl;
+
+public class StringConstant extends Constant {
+       public String value;
+    
+public StringConstant(String value) {
+       this.value = value ;
+}
+public boolean compileTimeEqual(StringConstant right){
+       //String are intermed in the compiler==>thus if two string constant
+       //get to be compared, it is an equal on the vale which is done
+       if (this.value == null) {
+               return right.value == null;
+       }
+       return this.value.equals(right.value);
+}
+public String stringValue() {
+       //spec 15.17.11
+
+       //the next line do not go into the toString() send....!
+       return value ;
+
+       /*
+       String s = value.toString() ;
+       if (s == null)
+               return "null";
+       else
+               return s;
+       */
+       
+}
+public String toString(){
+
+       return "(String)\"" + value +"\""; } //$NON-NLS-2$ //$NON-NLS-1$
+public int typeID() {
+       return T_String;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
new file mode 100644 (file)
index 0000000..da45684
--- /dev/null
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * 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.impl.Constant;
+
+public final class ArrayBinding extends TypeBinding {
+       // creation and initialization of the length field
+       // the declaringClass of this field is intentionally set to null so it can be distinguished.
+       public static final FieldBinding ArrayLength = new FieldBinding(LENGTH, IntBinding, AccPublic | AccFinal, null, Constant.NotAConstant);
+
+       public TypeBinding leafComponentType;
+       public int dimensions;
+
+       char[] constantPoolName;
+public ArrayBinding(TypeBinding type, int dimensions) {
+       this.tagBits |= IsArrayType;
+       this.leafComponentType = type;
+       this.dimensions = dimensions;
+}
+/**
+ * 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;
+
+       char[] brackets = new char[dimensions];
+       for (int i = dimensions - 1; i >= 0; i--) brackets[i] = '[';
+       return constantPoolName = CharOperation.concat(brackets, leafComponentType.signature());
+}
+String debugName() {
+       StringBuffer brackets = new StringBuffer(dimensions * 2);
+       for (int i = dimensions; --i >= 0;)
+               brackets.append("[]"); //$NON-NLS-1$
+       return leafComponentType.debugName() + brackets.toString();
+}
+public int dimensions() {
+       return this.dimensions;
+}
+
+/* Answer an array whose dimension size is one less than the receiver.
+*
+* 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 PackageBinding getPackage() {
+       return leafComponentType.getPackage();
+}
+/* Answer true if the receiver type can be assigned to the argument type (right)
+*/
+
+public boolean isCompatibleWith(TypeBinding right) {
+       if (this == right)
+               return true;
+
+       if (right.isArrayType()) {
+               ArrayBinding rightArray = (ArrayBinding) right;
+               if (rightArray.leafComponentType.isBaseType())
+                       return false; // relying on the fact that all equal arrays are identical
+               if (dimensions == rightArray.dimensions)
+                       return leafComponentType.isCompatibleWith(rightArray.leafComponentType);
+               if (dimensions < rightArray.dimensions)
+                       return false; // cannot assign 'String[]' into 'Object[][]' but can assign 'byte[][]' into 'Object[]'
+       } else {
+               if (right.isBaseType())
+                       return false;
+       }
+       //Check dimensions - Java does not support explicitly sized dimensions for types.
+       //However, if it did, the type checking support would go here.
+       switch (right.leafComponentType().id) {
+           case T_JavaLangObject :
+           case T_JavaLangCloneable :
+           case T_JavaIoSerializable :
+               return true;
+       }
+       return false;
+}
+
+public TypeBinding leafComponentType(){
+       return leafComponentType;
+}
+
+/* API
+* Answer the problem id associated with the receiver.
+* NoError if the receiver is a valid binding.
+*/
+
+public int problemId() {
+       return leafComponentType.problemId();
+}
+/**
+* Answer the source name for the type.
+* In the case of member types, as the qualified name from its top level type.
+* For example, for a member type N defined inside M & A: "A.M.N".
+*/
+
+public char[] qualifiedSourceName() {
+       char[] brackets = new char[dimensions * 2];
+       for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+               brackets[i] = ']';
+               brackets[i - 1] = '[';
+       }
+       return CharOperation.concat(leafComponentType.qualifiedSourceName(), brackets);
+}
+public char[] readableName() /* java.lang.Object[] */ {
+       char[] brackets = new char[dimensions * 2];
+       for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+               brackets[i] = ']';
+               brackets[i - 1] = '[';
+       }
+       return CharOperation.concat(leafComponentType.readableName(), brackets);
+}
+public char[] shortReadableName(){
+       char[] brackets = new char[dimensions * 2];
+       for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+               brackets[i] = ']';
+               brackets[i - 1] = '[';
+       }
+       return CharOperation.concat(leafComponentType.shortReadableName(), brackets);
+}
+public char[] sourceName() {
+       char[] brackets = new char[dimensions * 2];
+       for (int i = dimensions * 2 - 1; i >= 0; i -= 2) {
+               brackets[i] = ']';
+               brackets[i - 1] = '[';
+       }
+       return CharOperation.concat(leafComponentType.sourceName(), brackets);
+}
+public String toString() {
+       return leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
new file mode 100644 (file)
index 0000000..501e237
--- /dev/null
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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;
+
+public final class BaseTypeBinding extends TypeBinding {
+
+       public char[] simpleName;
+       private char[] constantPoolName;
+
+       BaseTypeBinding(int id, char[] name, char[] constantPoolName) {
+
+               this.tagBits |= IsBaseType;
+               this.id = id;
+               this.simpleName = name;
+               this.constantPoolName = constantPoolName;
+       }
+
+       /* Answer the receiver's constant pool name.
+       */
+       public char[] constantPoolName() {
+
+               return constantPoolName;
+       }
+
+       public PackageBinding getPackage() {
+
+               return null;
+       }
+
+       /* Answer true if the receiver type can be assigned to the argument type (right)
+       */
+       public final boolean isCompatibleWith(TypeBinding right) {
+
+               if (this == right)
+                       return true;
+               if (!right.isBaseType())
+                       return this == NullBinding;
+
+               switch (right.id) {
+                       case T_boolean :
+                       case T_byte :
+                       case T_char :
+                               return false;
+                       case T_double :
+                               switch (id) {
+                                       case T_byte :
+                                       case T_char :
+                                       case T_short :
+                                       case T_int :
+                                       case T_long :
+                                       case T_float :
+                                               return true;
+                                       default :
+                                               return false;
+                               }
+                       case T_float :
+                               switch (id) {
+                                       case T_byte :
+                                       case T_char :
+                                       case T_short :
+                                       case T_int :
+                                       case T_long :
+                                               return true;
+                                       default :
+                                               return false;
+                               }
+                       case T_long :
+                               switch (id) {
+                                       case T_byte :
+                                       case T_char :
+                                       case T_short :
+                                       case T_int :
+                                               return true;
+                                       default :
+                                               return false;
+                               }
+                       case T_int :
+                               switch (id) {
+                                       case T_byte :
+                                       case T_char :
+                                       case T_short :
+                                               return true;
+                                       default :
+                                               return false;
+                               }
+                       case T_short :
+                               return (id == T_byte);
+               }
+               return false;
+       }
+
+       public static final boolean isNarrowing(int left, int right) {
+
+               //can "left" store a "right" using some narrowing conversion
+               //(is left smaller than right)
+               switch (left) {
+                       case T_boolean :
+                               return right == T_boolean;
+                       case T_char :
+                       case T_byte :
+                               if (right == T_byte)
+                                       return true;
+                       case T_short :
+                               if (right == T_short)
+                                       return true;
+                               if (right == T_char)
+                                       return true;
+                       case T_int :
+                               if (right == T_int)
+                                       return true;
+                       case T_long :
+                               if (right == T_long)
+                                       return true;
+                       case T_float :
+                               if (right == T_float)
+                                       return true;
+                       case T_double :
+                               if (right == T_double)
+                                       return true;
+                       default :
+                               return false;
+               }
+       }
+
+       public static final boolean isWidening(int left, int right) {
+
+               //can "left" store a "right" using some widening conversion
+               //(is left "bigger" than right)
+               switch (left) {
+                       case T_boolean :
+                               return right == T_boolean;
+                       case T_char :
+                               return right == T_char;
+                       case T_double :
+                               if (right == T_double)
+                                       return true;
+                       case T_float :
+                               if (right == T_float)
+                                       return true;
+                       case T_long :
+                               if (right == T_long)
+                                       return true;
+                       case T_int :
+                               if (right == T_int)
+                                       return true;
+                               if (right == T_char)
+                                       return true;
+                       case T_short :
+                               if (right == T_short)
+                                       return true;
+                       case T_byte :
+                               if (right == T_byte)
+                                       return true;
+                       default :
+                               return false;
+               }
+       }
+
+       public char[] qualifiedSourceName() {
+               return simpleName;
+       }
+
+       public char[] readableName() {
+               return simpleName;
+       }
+
+       public char[] shortReadableName() {
+               return simpleName;
+       }
+
+       public char[] sourceName() {
+               return simpleName;
+       }
+
+       public String toString() {
+               return new String(constantPoolName) + " (id=" + id + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/BaseTypes.java
new file mode 100644 (file)
index 0000000..b1ec5eb
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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;
+
+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$
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
new file mode 100644 (file)
index 0000000..6ada2f8
--- /dev/null
@@ -0,0 +1,550 @@
+/*******************************************************************************
+ * 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.ConstructorDeclaration;
+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.problem.AbortCompilation;
+
+/*
+Not all fields defined by this type are initialized when it is created.
+Some are initialized only when needed.
+
+Accessors have been provided for some public fields so all TypeBindings have the same API...
+but access public fields directly whenever possible.
+Non-public fields have accessors which should be used everywhere you expect the field to be initialized.
+
+null is NOT a valid value for a non-public field... it just means the field is not initialized.
+*/
+
+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;
+public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType, LookupEnvironment environment) {
+       this.compoundName = CharOperation.splitOn('/', binaryType.getName());
+       computeId();
+
+       this.tagBits |= IsBinaryBinding;
+       this.environment = environment;
+       this.fPackage = packageBinding;
+       this.fileName = binaryType.getFileName();
+
+       // source name must be one name without "$".
+       char[] possibleSourceName = this.compoundName[this.compoundName.length - 1];
+       int start = CharOperation.lastIndexOf('$', possibleSourceName) + 1;
+       if (start == 0) {
+               this.sourceName = possibleSourceName;
+       } else {
+               this.sourceName = new char[possibleSourceName.length - start];
+               System.arraycopy(possibleSourceName, start, this.sourceName, 0, this.sourceName.length);
+       }
+
+       this.modifiers = binaryType.getModifiers();
+       if (binaryType.isInterface())
+               this.modifiers |= AccInterface;
+               
+       if (binaryType.isAnonymous()) {
+               this.tagBits |= AnonymousTypeMask;
+       } else if (binaryType.isLocal()) {
+               this.tagBits |= LocalTypeMask;
+       } else if (binaryType.isMember()) {
+               this.tagBits |= MemberTypeMask;
+       }
+}
+
+public FieldBinding[] availableFields() {
+       FieldBinding[] availableFields = new FieldBinding[fields.length];
+       int count = 0;
+       
+       for (int i = 0; i < fields.length;i++) {
+               try {
+                       availableFields[count] = resolveTypeFor(fields[i]);
+                       count++;
+               } catch (AbortCompilation a){
+                       // silent abort
+               }
+       }
+       
+       System.arraycopy(availableFields, 0, availableFields = new FieldBinding[count], 0, count);
+       return availableFields;
+}
+
+public MethodBinding[] availableMethods() {
+       if ((modifiers & AccUnresolved) == 0)
+               return methods;
+               
+       MethodBinding[] availableMethods = new MethodBinding[methods.length];
+       int count = 0;
+       
+       for (int i = 0; i < methods.length;i++) {
+               try {
+                       availableMethods[count] = resolveTypesFor(methods[i]);
+                       count++;
+               } catch (AbortCompilation a){
+                       // silent abort
+               }
+       }
+       System.arraycopy(availableMethods, 0, availableMethods = new MethodBinding[count], 0, count);
+       return availableMethods;
+}
+
+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.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);
+
+       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.tagBits |= MemberTypeMask;   // must be a member type not a top-level or local type
+               if (this.enclosingType().isStrictfp())
+                       this.modifiers |= AccStrictfp;
+               if (this.enclosingType().isDeprecated())
+                       this.modifiers |= AccDeprecatedImplicitly;
+       }
+
+       this.memberTypes = NoMemberTypes;
+       IBinaryNestedType[] memberTypeStructures = binaryType.getMemberTypes();
+       if (memberTypeStructures != null) {
+               int size = memberTypeStructures.length;
+               if (size > 0) {
+                       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);
+               }
+       }
+
+       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());
+       } else { // protect against incorrect use of the needFieldsAndMethods flag, see 48459
+               this.fields = NoFields;
+               this.methods = NoMethods;
+       }
+}
+private void createFields(IBinaryField[] iFields) {
+       this.fields = NoFields;
+       if (iFields != null) {
+               int size = iFields.length;
+               if (size > 0) {
+                       this.fields = new FieldBinding[size];
+                       for (int i = 0; i < size; i++) {
+                               IBinaryField field = iFields[i];
+                               this.fields[i] =
+                                       new FieldBinding(
+                                               field.getName(),
+                                               environment.getTypeFromSignature(field.getTypeName(), 0, -1),
+                                               field.getModifiers() | AccUnresolved,
+                                               this,
+                                               field.getConstant());
+                       }
+               }
+       }
+}
+private MethodBinding createMethod(IBinaryMethod method) {
+       int methodModifiers = method.getModifiers() | AccUnresolved;
+
+       ReferenceBinding[] exceptions = NoExceptions;
+       char[][] exceptionTypes = method.getExceptionTypeNames();
+       if (exceptionTypes != null) {
+               int size = exceptionTypes.length;
+               if (size > 0) {
+                       exceptions = new ReferenceBinding[size];
+                       for (int i = 0; i < size; i++)
+                               exceptions[i] = environment.getTypeFromConstantPoolName(exceptionTypes[i], 0, -1);
+               }
+       }
+
+       TypeBinding[] parameters = NoParameters;
+       char[] methodSignature = method.getMethodDescriptor();   // of the form (I[Ljava/jang/String;)V
+       int numOfParams = 0;
+       char nextChar;
+       int index = 0;   // first character is always '(' so skip it
+       while ((nextChar = methodSignature[++index]) != ')') {
+               if (nextChar != '[') {
+                       numOfParams++;
+                       if (nextChar == 'L')
+                               while ((nextChar = methodSignature[++index]) != ';'){/*empty*/}
+               }
+       }
+
+       // Ignore synthetic argument for member types.
+       int startIndex = (method.isConstructor() && isMemberType() && !isStatic()) ? 1 : 0;
+       int size = numOfParams - startIndex;
+       if (size > 0) {
+               parameters = new TypeBinding[size];
+               index = 1;
+               int end = 0;   // first character is always '(' so skip it
+               for (int i = 0; i < numOfParams; i++) {
+                       while ((nextChar = methodSignature[++end]) == '['){/*empty*/}
+                       if (nextChar == 'L')
+                               while ((nextChar = methodSignature[++end]) != ';'){/*empty*/}
+
+                       if (i >= startIndex)   // skip the synthetic arg if necessary
+                               parameters[i - startIndex] = environment.getTypeFromSignature(methodSignature, index, end);
+                       index = end + 1;
+               }
+       }
+
+       MethodBinding 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;
+}
+/**
+ * Create method bindings for binary type, filtering out <clinit> and synthetics
+ */
+private void createMethods(IBinaryMethod[] iMethods) {
+       int total = 0, initialTotal = 0, iClinit = -1;
+       int[] toSkip = null;
+       if (iMethods != null) {
+               total = initialTotal = iMethods.length;
+               for (int i = total; --i >= 0;) {
+                       IBinaryMethod method = iMethods[i];
+                       if ((method.getModifiers() & AccSynthetic) != 0) {
+                               // discard synthetics methods
+                               if (toSkip == null) toSkip = new int[iMethods.length];
+                               toSkip[i] = -1;
+                               total--;
+                       } else if (iClinit == -1) {
+                               char[] methodName = method.getSelector();
+                               if (methodName.length == 8 && methodName[0] == '<') {
+                                       // discard <clinit>
+                                       iClinit = i;
+                                       total--;
+                               }
+                       }
+               }
+       }
+       if (total == 0) {
+               this.methods = NoMethods;
+               return;
+       }
+
+       this.methods = new MethodBinding[total];
+       if (total == initialTotal) {
+               for (int i = 0; i < initialTotal; i++)
+                       this.methods[i] = createMethod(iMethods[i]);
+       } else {
+               for (int i = 0, index = 0; i < initialTotal; i++)
+                       if (iClinit != i && (toSkip == null || toSkip[i] != -1))
+                               this.methods[index++] = createMethod(iMethods[i]);
+       }
+       modifiers |= AccUnresolved; // until methods() is sent
+}
+/* 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;
+}
+// NOTE: the type of each field of a binary type is resolved when needed
+
+public FieldBinding[] fields() {
+       for (int i = fields.length; --i >= 0;)
+               resolveTypeFor(fields[i]);
+       return fields;
+}
+// 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) {
+                       resolveTypesFor(method);
+                       TypeBinding[] toMatch = method.parameters;
+                       for (int p = 0; p < argCount; p++)
+                               if (toMatch[p] != argumentTypes[p])
+                                       continue nextMethod;
+                       return method;
+               }
+       }
+       return null;
+}
+// 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) {
+       int argCount = argumentTypes.length;
+       int selectorLength = selector.length;
+       boolean foundNothing = true;
+       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) {
+                               resolveTypesFor(method);
+                               TypeBinding[] toMatch = method.parameters;
+                               for (int p = 0; p < argCount; p++)
+                                       if (toMatch[p] != argumentTypes[p])
+                                               continue nextMethod;
+                               return method;
+                       }
+               }
+       }
+
+       if (foundNothing) {
+               if (isInterface()) {
+                        if (superInterfaces.length == 1)
+                               return superInterfaces[0].getExactMethod(selector, argumentTypes);
+               } else if (superclass != null) {
+                       return superclass.getExactMethod(selector, argumentTypes);
+               }
+       }
+       return null;
+}
+// NOTE: the type of a field of a binary type is resolved when needed
+
+public FieldBinding getField(char[] fieldName, boolean needResolve) {
+       int fieldLength = fieldName.length;
+       for (int f = fields.length; --f >= 0;) {
+               char[] name = fields[f].name;
+               if (name.length == fieldLength && CharOperation.equals(name, fieldName))
+                       return needResolve ? resolveTypeFor(fields[f]) : fields[f];
+       }
+       return null;
+}
+/**
+ *  Rewrite of default getMemberType to avoid resolving eagerly all member types when one is requested
+ */
+public ReferenceBinding getMemberType(char[] typeName) {
+       for (int i = this.memberTypes.length; --i >= 0;) {
+           ReferenceBinding memberType = this.memberTypes[i];
+           if (memberType instanceof UnresolvedReferenceBinding) {
+                       char[] name = memberType.sourceName; // source name is qualified with enclosing type name
+                       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);
+           } else if (CharOperation.equals(typeName, memberType.sourceName)) {
+               return memberType;
+           }
+       }
+       return null;
+}
+// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
+
+public MethodBinding[] getMethods(char[] selector) {
+       int count = 0;
+       int lastIndex = -1;
+       int selectorLength = selector.length;
+       for (int m = 0, length = methods.length; m < length; m++) {
+               MethodBinding method = methods[m];
+               if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector)) {
+                       resolveTypesFor(method);
+                       count++;
+                       lastIndex = m;
+               }
+       }
+       if (count == 1)
+               return new MethodBinding[] {methods[lastIndex]};
+       if (count > 0) {
+               MethodBinding[] result = new MethodBinding[count];
+               count = 0;
+               for (int m = 0; m <= lastIndex; m++) {
+                       MethodBinding method = methods[m];
+                       if (method.selector.length == selectorLength && CharOperation.equals(method.selector, selector))
+                               result[count++] = method;
+               }
+               return result;
+       }
+       return NoMethods;
+}
+public boolean hasMemberTypes() {
+    return this.memberTypes.length > 0;
+}
+// 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;
+}
+// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
+
+public MethodBinding[] methods() {
+       if ((modifiers & AccUnresolved) == 0)
+               return methods;
+
+       for (int i = methods.length; --i >= 0;)
+               resolveTypesFor(methods[i]);
+       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;
+       }
+       return field;
+}
+private MethodBinding resolveTypesFor(MethodBinding method) {
+       if ((method.modifiers & AccUnresolved) == 0)
+               return method;
+
+       if (!method.isConstructor())
+               method.returnType = resolveType(method.returnType);
+       for (int i = method.parameters.length; --i >= 0;)
+               method.parameters[i] = resolveType(method.parameters[i]);
+       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;
+       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;
+}
+// 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;
+}
+MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
+       return methods;
+}
+public String toString() {
+       String s = ""; //$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$
+
+       if (superInterfaces != null) {
+               if (superInterfaces != NoSuperInterfaces) {
+                       s += "\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$
+                       }
+               }
+       } else {
+               s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
+       }
+
+       if (enclosingType != null) {
+               s += "\n\tenclosing type : "; //$NON-NLS-1$
+               s += enclosingType.debugName();
+       }
+
+       if (fields != null) {
+               if (fields != NoFields) {
+                       s += "\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$
+               }
+       } else {
+               s += "NULL FIELDS"; //$NON-NLS-1$
+       }
+
+       if (methods != null) {
+               if (methods != NoMethods) {
+                       s += "\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$
+               }
+       } else {
+               s += "NULL METHODS"; //$NON-NLS-1$
+       }
+
+       if (memberTypes != null) {
+               if (memberTypes != NoMemberTypes) {
+                       s += "\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$
+               }
+       } else {
+               s += "NULL MEMBER TYPES"; //$NON-NLS-1$
+       }
+
+       s += "\n\n\n"; //$NON-NLS-1$
+       return s;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/Binding.java
new file mode 100644 (file)
index 0000000..d6225aa
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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;
+
+public abstract class Binding implements BindingIds, CompilerModifiers, ProblemReasons {
+       /* 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();
+       /* API
+       * Answer true if the receiver is not a problem binding
+       */
+       
+       public final boolean isValidBinding() {
+               return problemId() == NoError;
+       }
+       /* API
+       * Answer the problem id associated with the receiver.
+       * NoError if the receiver is a valid binding.
+       */
+       
+       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(){
+               return readableName();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/BindingIds.java
new file mode 100644 (file)
index 0000000..9f2e688
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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;
+
+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;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
new file mode 100644 (file)
index 0000000..f0f9451
--- /dev/null
@@ -0,0 +1,826 @@
+/*******************************************************************************
+ * 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.*;
+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 {
+
+       // Local variable management
+       public LocalVariableBinding[] locals;
+       public int localIndex; // position for next variable
+       public int startIndex;  // start position in this scope - for ordering scopes vs. variables
+       public int offset; // for variable allocation throughout scopes
+       public int maxOffset; // for variable allocation throughout scopes
+
+       // finally scopes must be shifted behind respective try&catch scope(s) so as to avoid
+       // collisions of secret variables (return address, save value).
+       public BlockScope[] shiftScopes; 
+
+       public final static VariableBinding[] EmulationPathToImplicitThis = {};
+       public final static VariableBinding[] NoEnclosingInstanceInConstructorCall = {};
+       public final static VariableBinding[] NoEnclosingInstanceInStaticContext = {};
+
+       public Scope[] subscopes = new Scope[1]; // need access from code assist
+       public int subscopeCount = 0; // need access from code assist
+
+       // record the current case statement being processed (for entire switch case block).
+       public CaseStatement switchCase; // from 1.4 on, local types should not be accessed across switch case blocks (52221)
+
+       protected BlockScope(int kind, Scope parent) {
+
+               super(kind, parent);
+       }
+
+       public BlockScope(BlockScope parent) {
+
+               this(parent, true);
+       }
+
+       public BlockScope(BlockScope parent, boolean addToParentScope) {
+
+               this(BLOCK_SCOPE, parent);
+               locals = new LocalVariableBinding[5];
+               if (addToParentScope) parent.addSubscope(this);
+               this.startIndex = parent.localIndex;
+       }
+
+       public BlockScope(BlockScope parent, int variableCount) {
+
+               this(BLOCK_SCOPE, parent);
+               locals = new LocalVariableBinding[variableCount];
+               parent.addSubscope(this);
+               this.startIndex = parent.localIndex;
+       }
+
+       /* Create the class scope & binding for the anonymous type.
+        */
+       public final void addAnonymousType(
+               TypeDeclaration anonymousType,
+               ReferenceBinding superBinding) {
+
+               ClassScope anonymousClassScope = new ClassScope(this, anonymousType);
+               anonymousClassScope.buildAnonymousTypeBinding(
+                       enclosingSourceType(),
+                       superBinding);
+       }
+
+       /* Create the class scope & binding for the local type.
+        */
+       public final void addLocalType(TypeDeclaration localType) {
+
+               // check that the localType does not conflict with an enclosing type
+               ReferenceBinding type = enclosingSourceType();
+               do {
+                       if (CharOperation.equals(type.sourceName, localType.name)) {
+                               problemReporter().hidingEnclosingType(localType);
+                               return;
+                       }
+                       type = type.enclosingType();
+               } while (type != null);
+
+               // check that the localType does not conflict with another sibling local type
+               Scope scope = this;
+               do {
+                       if (((BlockScope) scope).findLocalType(localType.name) != null) {
+                               problemReporter().duplicateNestedType(localType);
+                               return;
+                       }
+               } while ((scope = scope.parent) instanceof BlockScope);
+
+               ClassScope localTypeScope = new ClassScope(this, localType);
+               addSubscope(localTypeScope);
+               localTypeScope.buildLocalTypeBinding(enclosingSourceType());
+       }
+
+       /* Insert a local variable into a given scope, updating its position
+        * and checking there are not too many locals or arguments allocated.
+        */
+       public final void addLocalVariable(LocalVariableBinding binding) {
+
+               checkAndSetModifiersForVariable(binding);
+
+               // insert local in scope
+               if (localIndex == locals.length)
+                       System.arraycopy(
+                               locals,
+                               0,
+                               (locals = new LocalVariableBinding[localIndex * 2]),
+                               0,
+                               localIndex);
+               locals[localIndex++] = binding;
+
+               // update local variable binding 
+               binding.declaringScope = this;
+               binding.id = this.outerMostMethodScope().analysisIndex++;
+               // share the outermost method scope analysisIndex
+       }
+
+       public void addSubscope(Scope childScope) {
+               if (subscopeCount == subscopes.length)
+                       System.arraycopy(
+                               subscopes,
+                               0,
+                               (subscopes = new Scope[subscopeCount * 2]),
+                               0,
+                               subscopeCount);
+               subscopes[subscopeCount++] = childScope;
+       }
+
+       /* Answer true if the receiver is suitable for assigning final blank fields.
+        *
+        * in other words, it is inside an initializer, a constructor or a clinit 
+        */
+       public final boolean allowBlankFinalFieldAssignment(FieldBinding binding) {
+
+               if (enclosingSourceType() != binding.declaringClass)
+                       return false;
+
+               MethodScope methodScope = methodScope();
+               if (methodScope.isStatic != binding.isStatic())
+                       return false;
+               return methodScope.isInsideInitializer() // inside initializer
+                               || ((AbstractMethodDeclaration) methodScope.referenceContext)
+                                       .isInitializationMethod(); // inside constructor or clinit
+       }
+       String basicToString(int tab) {
+               String newLine = "\n"; //$NON-NLS-1$
+               for (int i = tab; --i >= 0;)
+                       newLine += "\t"; //$NON-NLS-1$
+
+               String s = newLine + "--- Block Scope ---"; //$NON-NLS-1$
+               newLine += "\t"; //$NON-NLS-1$
+               s += newLine + "locals:"; //$NON-NLS-1$
+               for (int i = 0; i < localIndex; i++)
+                       s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$
+               s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$
+               return s;
+       }
+
+       private void checkAndSetModifiersForVariable(LocalVariableBinding varBinding) {
+
+               int modifiers = varBinding.modifiers;
+               if ((modifiers & AccAlternateModifierProblem) != 0 && varBinding.declaration != null){
+                       problemReporter().duplicateModifierForVariable(varBinding.declaration, this instanceof MethodScope);
+               }
+               int realModifiers = modifiers & AccJustFlag;
+               
+               int unexpectedModifiers = ~AccFinal;
+               if ((realModifiers & unexpectedModifiers) != 0 && varBinding.declaration != null){ 
+                       problemReporter().illegalModifierForVariable(varBinding.declaration, this instanceof MethodScope);
+               }
+               varBinding.modifiers = modifiers;
+       }
+
+       /* Compute variable positions in scopes given an initial position offset
+        * ignoring unused local variables.
+        * 
+        * No argument is expected here (ilocal is the first non-argument local of the outermost scope)
+        * Arguments are managed by the MethodScope method
+        */
+       void computeLocalVariablePositions(int ilocal, int initOffset, CodeStream codeStream) {
+
+               this.offset = initOffset;
+               this.maxOffset = initOffset;
+
+               // local variable init
+               int maxLocals = this.localIndex;
+               boolean hasMoreVariables = ilocal < maxLocals;
+
+               // scope init
+               int iscope = 0, maxScopes = this.subscopeCount;
+               boolean hasMoreScopes = maxScopes > 0;
+
+               // iterate scopes and variables in parallel
+               while (hasMoreVariables || hasMoreScopes) {
+                       if (hasMoreScopes
+                               && (!hasMoreVariables || (subscopes[iscope].startIndex() <= ilocal))) {
+                               // consider subscope first
+                               if (subscopes[iscope] instanceof BlockScope) {
+                                       BlockScope subscope = (BlockScope) subscopes[iscope];
+                                       int subOffset = subscope.shiftScopes == null ? this.offset : subscope.maxShiftedOffset();
+                                       subscope.computeLocalVariablePositions(0, subOffset, codeStream);
+                                       if (subscope.maxOffset > this.maxOffset)
+                                               this.maxOffset = subscope.maxOffset;
+                               }
+                               hasMoreScopes = ++iscope < maxScopes;
+                       } else {
+                               
+                               // consider variable first
+                               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));
+                                       
+                               // do not report fake used variable
+                               if (local.useFlag == LocalVariableBinding.UNUSED
+                                       && (local.declaration != null) // unused (and non secret) local
+                                       && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
+                                               
+                                       if (!(local.declaration instanceof Argument))  // do not report unused catch arguments
+                                               this.problemReporter().unusedLocalVariable(local.declaration);
+                               }
+                               
+                               // could be optimized out, but does need to preserve unread variables ?
+                               if (!generateCurrentLocalVar) {
+                                       if (local.declaration != null && environment().options.preserveAllLocalVariables) {
+                                               generateCurrentLocalVar = true; // force it to be preserved in the generated code
+                                               local.useFlag = LocalVariableBinding.USED;
+                                       }
+                               }
+                               
+                               // allocate variable
+                               if (generateCurrentLocalVar) {
+
+                                       if (local.declaration != null) {
+                                               codeStream.record(local); // record user-defined local variables for attribute generation
+                                       }
+                                       // assign variable position
+                                       local.resolvedPosition = this.offset;
+
+                                       if ((local.type == LongBinding) || (local.type == DoubleBinding)) {
+                                               this.offset += 2;
+                                       } else {
+                                               this.offset++;
+                                       }
+                                       if (this.offset > 0xFFFF) { // no more than 65535 words of locals
+                                               this.problemReporter().noMoreAvailableSpaceForLocal(
+                                                       local, 
+                                                       local.declaration == null ? (ASTNode)this.methodScope().referenceContext : local.declaration);
+                                       }
+                               } else {
+                                       local.resolvedPosition = -1; // not generated
+                               }
+                               hasMoreVariables = ++ilocal < maxLocals;
+                       }
+               }
+               if (this.offset > this.maxOffset)
+                       this.maxOffset = this.offset;
+       }
+
+       /*
+        *      Record the suitable binding denoting a synthetic field or constructor argument,
+        * mapping to the actual outer local variable in the scope context.
+        * Note that this may not need any effect, in case the outer local variable does not
+        * need to be emulated and can directly be used as is (using its back pointer to its
+        * declaring scope).
+        */
+       public void emulateOuterAccess(LocalVariableBinding outerLocalVariable) {
+
+               MethodScope currentMethodScope;
+               if ((currentMethodScope = this.methodScope())
+                       != outerLocalVariable.declaringScope.methodScope()) {
+                       NestedTypeBinding currentType = (NestedTypeBinding) this.enclosingSourceType();
+
+                       //do nothing for member types, pre emulation was performed already
+                       if (!currentType.isLocalType()) {
+                               return;
+                       }
+                       // must also add a synthetic field if we're not inside a constructor
+                       if (!currentMethodScope.isInsideInitializerOrConstructor()) {
+                               currentType.addSyntheticArgumentAndField(outerLocalVariable);
+                       } else {
+                               currentType.addSyntheticArgument(outerLocalVariable);
+                       }
+               }
+       }
+
+       /* Note that it must never produce a direct access to the targetEnclosingType,
+        * but instead a field sequence (this$2.this$1.this$0) so as to handle such a test case:
+        *
+        * class XX {
+        *      void foo() {
+        *              class A {
+        *                      class B {
+        *                              class C {
+        *                                      boolean foo() {
+        *                                              return (Object) A.this == (Object) B.this;
+        *                                      }
+        *                              }
+        *                      }
+        *              }
+        *              new A().new B().new C();
+        *      }
+        * }
+        * where we only want to deal with ONE enclosing instance for C (could not figure out an A for C)
+        */
+       public final ReferenceBinding findLocalType(char[] name) {
+
+           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;
+                               // from 1.4 on, local types should not be accessed across switch case blocks (52221)                            
+                               if (compliance >= ClassFileConstants.JDK1_4 && sourceType.switchCase != this.switchCase) continue;
+                               if (CharOperation.equals(sourceType.sourceName(), name))
+                                       return sourceType;
+                       }
+               }
+               return null;
+       }
+
+       public LocalVariableBinding findVariable(char[] variable) {
+
+               int varLength = variable.length;
+               for (int i = 0, length = locals.length; i < length; i++) {
+                       LocalVariableBinding local = locals[i];
+                       if (local == null)
+                               return null;
+                       if (local.name.length == varLength && CharOperation.equals(local.name, variable))
+                               return local;
+               }
+               return null;
+       }
+       /* API
+        * flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE.
+        * Only bindings corresponding to the mask will be answered.
+        *
+        *      if the VARIABLE mask is set then
+        *              If the first name provided is a field (or local) then the field (or local) is answered
+        *              Otherwise, package names and type names are consumed until a field is found.
+        *              In this case, the field is answered.
+        *
+        *      if the TYPE mask is set,
+        *              package names and type names are consumed until the end of the input.
+        *              Only if all of the input is consumed is the type answered
+        *
+        *      All other conditions are errors, and a problem binding is returned.
+        *      
+        *      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.
+        *
+        *      The VARIABLE mask has precedence over the TYPE mask.
+        *
+        *      InvocationSite implements
+        *              isSuperAccess(); this is used to determine if the discovered field is visible.
+        *              setFieldIndex(int); this is used to record the number of names that were consumed.
+        *
+        *      For example, getBinding({"foo","y","q", VARIABLE, site) will answer
+        *      the binding for the field or local named "foo" (or an error binding if none exists).
+        *      In addition, setFieldIndex(1) will be sent to the invocation site.
+        *      If a type named "foo" exists, it will not be detected (and an error binding will be answered)
+        *
+        *      IMPORTANT NOTE: This method is written under the assumption that compoundName is longer than length 1.
+        */
+       public Binding getBinding(char[][] compoundName, int mask, InvocationSite invocationSite, boolean needResolve) {
+
+               Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite, needResolve);
+               invocationSite.setFieldIndex(1);
+               if (binding instanceof VariableBinding) return binding;
+               compilationUnitScope().recordSimpleReference(compoundName[0]);
+               if (!binding.isValidBinding()) return binding;
+
+               int length = compoundName.length;
+               int currentIndex = 1;
+               foundType : if (binding instanceof PackageBinding) {
+                       PackageBinding packageBinding = (PackageBinding) binding;
+                       while (currentIndex < length) {
+                               compilationUnitScope().recordReference(packageBinding.compoundName, compoundName[currentIndex]);
+                               binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+                               invocationSite.setFieldIndex(currentIndex);
+                               if (binding == null) {
+                                       if (currentIndex == length) {
+                                               // must be a type if its the last name, otherwise we have no idea if its a package or type
+                                               return new ProblemReferenceBinding(
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       NotFound);
+                                       }
+                                       return new ProblemBinding(
+                                               CharOperation.subarray(compoundName, 0, currentIndex),
+                                               NotFound);
+                               }
+                               if (binding instanceof ReferenceBinding) {
+                                       if (!binding.isValidBinding())
+                                               return new ProblemReferenceBinding(
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       binding.problemId());
+                                       if (!((ReferenceBinding) binding).canBeSeenBy(this))
+                                               return new ProblemReferenceBinding(
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       (ReferenceBinding) binding,
+                                                       NotVisible);
+                                       break foundType;
+                               }
+                               packageBinding = (PackageBinding) binding;
+                       }
+
+                       // It is illegal to request a PACKAGE from this method.
+                       return new ProblemReferenceBinding(
+                               CharOperation.subarray(compoundName, 0, currentIndex),
+                               NotFound);
+               }
+
+               // know binding is now a ReferenceBinding
+               while (currentIndex < length) {
+                       ReferenceBinding typeBinding = (ReferenceBinding) binding;
+                       char[] nextName = compoundName[currentIndex++];
+                       invocationSite.setFieldIndex(currentIndex);
+                       invocationSite.setActualReceiverType(typeBinding);
+                       if ((mask & FIELD) != 0 && (binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
+                               if (!binding.isValidBinding())
+                                       return new ProblemFieldBinding(
+                                               ((FieldBinding) binding).declaringClass,
+                                               CharOperation.subarray(compoundName, 0, currentIndex),
+                                               binding.problemId());
+                               break; // binding is now a field
+                       }
+                       if ((binding = findMemberType(nextName, typeBinding)) == null) {
+                               if ((mask & FIELD) != 0) {
+                                       return new ProblemBinding(
+                                               CharOperation.subarray(compoundName, 0, currentIndex),
+                                               typeBinding,
+                                               NotFound);
+                               } 
+                               return new ProblemReferenceBinding(
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       typeBinding,
+                                       NotFound);
+                       }
+                       if (!binding.isValidBinding())
+                               return new ProblemReferenceBinding(
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       binding.problemId());
+               }
+               if ((mask & FIELD) != 0 && (binding instanceof FieldBinding)) {
+                       // was looking for a field and found a field
+                       FieldBinding field = (FieldBinding) binding;
+                       if (!field.isStatic())
+                               return new ProblemFieldBinding(
+                                       field.declaringClass,
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       NonStaticReferenceInStaticContext);
+                       return binding;
+               }
+               if ((mask & TYPE) != 0 && (binding instanceof ReferenceBinding)) {
+                       // was looking for a type and found a type
+                       return binding;
+               }
+
+               // handle the case when a field or type was asked for but we resolved the compoundName to a type or field
+               return new ProblemBinding(
+                       CharOperation.subarray(compoundName, 0, currentIndex),
+                       NotFound);
+       }
+
+       // Added for code assist... NOT Public API
+       public final Binding getBinding(
+               char[][] compoundName,
+               InvocationSite invocationSite) {
+               int currentIndex = 0;
+               int length = compoundName.length;
+               Binding binding =
+                       getBinding(
+                               compoundName[currentIndex++],
+                               VARIABLE | TYPE | PACKAGE,
+                               invocationSite, 
+                               true /*resolve*/);
+               if (!binding.isValidBinding())
+                       return binding;
+
+               foundType : if (binding instanceof PackageBinding) {
+                       while (currentIndex < length) {
+                               PackageBinding packageBinding = (PackageBinding) binding;
+                               binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]);
+                               if (binding == null) {
+                                       if (currentIndex == length) {
+                                               // must be a type if its the last name, otherwise we have no idea if its a package or type
+                                               return new ProblemReferenceBinding(
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       NotFound);
+                                       }
+                                       return new ProblemBinding(
+                                               CharOperation.subarray(compoundName, 0, currentIndex),
+                                               NotFound);
+                               }
+                               if (binding instanceof ReferenceBinding) {
+                                       if (!binding.isValidBinding())
+                                               return new ProblemReferenceBinding(
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       binding.problemId());
+                                       if (!((ReferenceBinding) binding).canBeSeenBy(this))
+                                               return new ProblemReferenceBinding(
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       (ReferenceBinding) binding, 
+                                                       NotVisible);
+                                       break foundType;
+                               }
+                       }
+                       return binding;
+               }
+
+               foundField : if (binding instanceof ReferenceBinding) {
+                       while (currentIndex < length) {
+                               ReferenceBinding typeBinding = (ReferenceBinding) binding;
+                               char[] nextName = compoundName[currentIndex++];
+                               if ((binding = findField(typeBinding, nextName, invocationSite, true /*resolve*/)) != null) {
+                                       if (!binding.isValidBinding())
+                                               return new ProblemFieldBinding(
+                                                       ((FieldBinding) binding).declaringClass,
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       binding.problemId());
+                                       if (!((FieldBinding) binding).isStatic())
+                                               return new ProblemFieldBinding(
+                                                       ((FieldBinding) binding).declaringClass,
+                                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                                       NonStaticReferenceInStaticContext);
+                                       break foundField; // binding is now a field
+                               }
+                               if ((binding = findMemberType(nextName, typeBinding)) == null)
+                                       return new ProblemBinding(
+                                               CharOperation.subarray(compoundName, 0, currentIndex),
+                                               typeBinding,
+                                               NotFound);
+                               if (!binding.isValidBinding())
+                                       return new ProblemReferenceBinding(
+                                               CharOperation.subarray(compoundName, 0, currentIndex),
+                                               binding.problemId());
+                       }
+                       return binding;
+               }
+
+               VariableBinding variableBinding = (VariableBinding) binding;
+               while (currentIndex < length) {
+                       TypeBinding typeBinding = variableBinding.type;
+                       if (typeBinding == null)
+                               return new ProblemFieldBinding(
+                                       null,
+                                       CharOperation.subarray(compoundName, 0, currentIndex + 1),
+                                       NotFound);
+                       variableBinding =
+                               findField(typeBinding, compoundName[currentIndex++], invocationSite, true /*resolve*/);
+                       if (variableBinding == null)
+                               return new ProblemFieldBinding(
+                                       null,
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       NotFound);
+                       if (!variableBinding.isValidBinding())
+                               return variableBinding;
+               }
+               return variableBinding;
+       }
+
+       /*
+        * This retrieves the argument that maps to an enclosing instance of the suitable type,
+        *      if not found then answers nil -- do not create one
+        *      
+        *              #implicitThis                                           : the implicit this will be ok
+        *              #((arg) this$n)                                         : available as a constructor arg
+        *              #((arg) this$n ... this$p)                      : available as as a constructor arg + a sequence of fields
+        *              #((fieldDescr) this$n ... this$p)       : available as a sequence of fields
+        *              nil                                                                                                     : not found
+        *
+        *      Note that this algorithm should answer the shortest possible sequence when
+        *              shortcuts are available:
+        *                              this$0 . this$0 . this$0
+        *              instead of
+        *                              this$2 . this$1 . this$0 . this$1 . this$0
+        *              thus the code generation will be more compact and runtime faster
+        */
+       public VariableBinding[] getEmulationPath(LocalVariableBinding outerLocalVariable) {
+
+               MethodScope currentMethodScope = this.methodScope();
+               SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
+
+               // identity check
+               if (currentMethodScope == outerLocalVariable.declaringScope.methodScope()) {
+                       return new VariableBinding[] { outerLocalVariable };
+                       // implicit this is good enough
+               }
+               // use synthetic constructor arguments if possible
+               if (currentMethodScope.isInsideInitializerOrConstructor()
+                       && (sourceType.isNestedType())) {
+                       SyntheticArgumentBinding syntheticArg;
+                       if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(outerLocalVariable)) != null) {
+                               return new VariableBinding[] { syntheticArg };
+                       }
+               }
+               // use a synthetic field then
+               if (!currentMethodScope.isStatic) {
+                       FieldBinding syntheticField;
+                       if ((syntheticField = sourceType.getSyntheticField(outerLocalVariable)) != null) {
+                               return new VariableBinding[] { syntheticField };
+                       }
+               }
+               return null;
+       }
+
+       /*
+        * This retrieves the argument that maps to an enclosing instance of the suitable type,
+        *      if not found then answers nil -- do not create one
+        *
+        *              #implicitThis                                                                                                           :  the implicit this will be ok
+        *              #((arg) this$n)                                                                                                 : available as a constructor arg
+        *      #((arg) this$n access$m... access$p)            : available as as a constructor arg + a sequence of synthetic accessors to synthetic fields
+        *      #((fieldDescr) this$n access#m... access$p)     : available as a first synthetic field + a sequence of synthetic accessors to synthetic fields
+        *      null                                                                                                                                    : not found
+        *      jls 15.9.2 + http://www.ergnosis.com/java-spec-report/java-language/jls-8.8.5.1-d.html
+        */
+       public Object[] getEmulationPath(
+                       ReferenceBinding targetEnclosingType, 
+                       boolean onlyExactMatch,
+                       boolean ignoreEnclosingArgInConstructorCall) {
+                               
+               MethodScope currentMethodScope = this.methodScope();
+               SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
+
+               // use 'this' if possible
+               if (!currentMethodScope.isConstructorCall && !currentMethodScope.isStatic) {
+                       if (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType))) {
+                               return EmulationPathToImplicitThis; // implicit this is good enough
+                       }
+               }
+               if (!sourceType.isNestedType() || sourceType.isStatic()) { // no emulation from within non-inner types
+                       if (currentMethodScope.isConstructorCall) {
+                               return NoEnclosingInstanceInConstructorCall;
+                       } else if (currentMethodScope.isStatic){
+                               return NoEnclosingInstanceInStaticContext;
+                       }
+                       return null;
+               }
+               boolean insideConstructor = currentMethodScope.isInsideInitializerOrConstructor();
+               // use synthetic constructor arguments if possible
+               if (insideConstructor) {
+                       SyntheticArgumentBinding syntheticArg;
+                       if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, onlyExactMatch)) != null) {
+                               // reject allocation and super constructor call
+                               if (ignoreEnclosingArgInConstructorCall 
+                                               && currentMethodScope.isConstructorCall 
+                                               && (sourceType == targetEnclosingType || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(sourceType)))) {
+                                       return NoEnclosingInstanceInConstructorCall;
+                               }
+                               return new Object[] { syntheticArg };
+                       }
+               }
+
+               // use a direct synthetic field then
+               if (currentMethodScope.isStatic) {
+                       return NoEnclosingInstanceInStaticContext;
+               }
+               FieldBinding syntheticField = sourceType.getSyntheticField(targetEnclosingType, onlyExactMatch);
+               if (syntheticField != null) {
+                       if (currentMethodScope.isConstructorCall){
+                               return NoEnclosingInstanceInConstructorCall;
+                       }
+                       return new Object[] { syntheticField };
+               }
+               // could be reached through a sequence of enclosing instance link (nested members)
+               Object[] path = new Object[2]; // probably at least 2 of them
+               ReferenceBinding currentType = sourceType.enclosingType();
+               if (insideConstructor) {
+                       path[0] = ((NestedTypeBinding) sourceType).getSyntheticArgument(currentType, onlyExactMatch);
+               } else {
+                       if (currentMethodScope.isConstructorCall){
+                               return NoEnclosingInstanceInConstructorCall;
+                       }
+                       path[0] = sourceType.getSyntheticField(currentType, onlyExactMatch);
+               }
+               if (path[0] != null) { // keep accumulating
+                       
+                       int count = 1;
+                       ReferenceBinding currentEnclosingType;
+                       while ((currentEnclosingType = currentType.enclosingType()) != null) {
+
+                               //done?
+                               if (currentType == targetEnclosingType
+                                       || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType)))        break;
+
+                               if (currentMethodScope != null) {
+                                       currentMethodScope = currentMethodScope.enclosingMethodScope();
+                                       if (currentMethodScope != null && currentMethodScope.isConstructorCall){
+                                               return NoEnclosingInstanceInConstructorCall;
+                                       }
+                                       if (currentMethodScope != null && currentMethodScope.isStatic){
+                                               return NoEnclosingInstanceInStaticContext;
+                                       }
+                               }
+                               
+                               syntheticField = ((NestedTypeBinding) currentType).getSyntheticField(currentEnclosingType, onlyExactMatch);
+                               if (syntheticField == null) break;
+
+                               // append inside the path
+                               if (count == path.length) {
+                                       System.arraycopy(path, 0, (path = new Object[count + 1]), 0, count);
+                               }
+                               // private access emulation is necessary since synthetic field is private
+                               path[count++] = ((SourceTypeBinding) syntheticField.declaringClass).addSyntheticMethod(syntheticField, true);
+                               currentType = currentEnclosingType;
+                       }
+                       if (currentType == targetEnclosingType
+                               || (!onlyExactMatch && targetEnclosingType.isSuperclassOf(currentType))) {
+                               return path;
+                       }
+               }
+               return null;
+       }
+
+       /* Answer true if the variable name already exists within the receiver's scope.
+        */
+       public final boolean isDuplicateLocalVariable(char[] name) {
+               BlockScope current = this;
+               while (true) {
+                       for (int i = 0; i < localIndex; i++) {
+                               if (CharOperation.equals(name, current.locals[i].name))
+                                       return true;
+                       }
+                       if (current.kind != BLOCK_SCOPE) return false;
+                       current = (BlockScope)current.parent;
+               }
+       }
+
+       public int maxShiftedOffset() {
+               int max = -1;
+               if (this.shiftScopes != null){
+                       for (int i = 0, length = this.shiftScopes.length; i < length; i++){
+                               int subMaxOffset = this.shiftScopes[i].maxOffset;
+                               if (subMaxOffset > max) max = subMaxOffset;
+                       }
+               }
+               return max;
+       }
+       
+       /* Answer the problem reporter to use for raising new problems.
+        *
+        * Note that as a side-effect, this updates the current reference context
+        * (unit, type or method) in case the problem handler decides it is necessary
+        * to abort.
+        */
+       public ProblemReporter problemReporter() {
+
+               return outerMostMethodScope().problemReporter();
+       }
+
+       /*
+        * Code responsible to request some more emulation work inside the invocation type, so as to supply
+        * correct synthetic arguments to any allocation of the target type.
+        */
+       public void propagateInnerEmulation(ReferenceBinding targetType, boolean isEnclosingInstanceSupplied) {
+
+               // no need to propagate enclosing instances, they got eagerly allocated already.
+               
+               SyntheticArgumentBinding[] syntheticArguments;
+               if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) {
+                       for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+                               SyntheticArgumentBinding syntheticArg = syntheticArguments[i];
+                               // need to filter out the one that could match a supplied enclosing instance
+                               if (!(isEnclosingInstanceSupplied
+                                       && (syntheticArg.type == targetType.enclosingType()))) {
+                                       this.emulateOuterAccess(syntheticArg.actualOuterLocalVariable);
+                               }
+                       }
+               }
+       }
+
+       /* Answer the reference type of this scope.
+        *
+        * It is the nearest enclosing type of this scope.
+        */
+       public TypeDeclaration referenceType() {
+
+               return methodScope().referenceType();
+       }
+
+       /*
+        * Answer the index of this scope relatively to its parent.
+        * For method scope, answers -1 (not a classScope relative position)
+        */
+       public int scopeIndex() {
+               if (this instanceof MethodScope) return -1;
+               BlockScope parentScope = (BlockScope)parent;
+               Scope[] parentSubscopes = parentScope.subscopes;
+               for (int i = 0, max = parentScope.subscopeCount; i < max; i++) {
+                       if (parentSubscopes[i] == this) return i;
+               }
+               return -1;
+       }
+       
+       // start position in this scope - for ordering scopes vs. variables
+       int startIndex() {
+               return startIndex;
+       }
+
+       public String toString() {
+               return toString(0);
+       }
+
+       public String toString(int tab) {
+
+               String s = basicToString(tab);
+               for (int i = 0; i < subscopeCount; i++)
+                       if (subscopes[i] instanceof BlockScope)
+                               s += ((BlockScope) subscopes[i]).toString(tab + 1) + "\n"; //$NON-NLS-1$
+               return s;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
new file mode 100644 (file)
index 0000000..6d83943
--- /dev/null
@@ -0,0 +1,921 @@
+/*******************************************************************************
+ * 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.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Clinit;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+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 final static char[] IncompleteHierarchy = new char[] {'h', 'a', 's', ' ', 'i', 'n', 'c', 'o', 'n', 's', 'i', 's', 't', 'e', 'n', 't', ' ', 'h', 'i', 'e', 'r', 'a', 'r', 'c', 'h', 'y'};
+
+       public ClassScope(Scope parent, TypeDeclaration context) {
+               super(CLASS_SCOPE, parent);
+               this.referenceContext = context;
+       }
+       
+       void buildAnonymousTypeBinding(SourceTypeBinding enclosingType, ReferenceBinding supertype) {
+               
+               LocalTypeBinding anonymousType = buildLocalType(enclosingType, enclosingType.fPackage);
+
+               SourceTypeBinding sourceType = referenceContext.binding;
+               if (supertype.isInterface()) {
+                       sourceType.superclass = getJavaLangObject();
+                       sourceType.superInterfaces = new ReferenceBinding[] { supertype };
+               } else {
+                       sourceType.superclass = supertype;
+                       sourceType.superInterfaces = TypeConstants.NoSuperInterfaces;
+               }
+               connectMemberTypes();
+               buildFieldsAndMethods();
+               anonymousType.faultInTypesForFieldsAndMethods();
+               sourceType.verifyMethods(environment().methodVerifier());
+       }
+       
+       private void buildFields() {
+               boolean hierarchyIsInconsistent = referenceContext.binding.isHierarchyInconsistent();
+               if (referenceContext.fields == null) {
+                       if (hierarchyIsInconsistent) { // 72468
+                               referenceContext.binding.fields = new FieldBinding[1];
+                               referenceContext.binding.fields[0] =
+                                       new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
+                       } else {
+                               referenceContext.binding.fields = NoFields;
+                       }
+                       return;
+               }
+               // count the number of fields vs. initializers
+               FieldDeclaration[] fields = referenceContext.fields;
+               int size = fields.length;
+               int count = 0;
+               for (int i = 0; i < size; i++)
+                       if (fields[i].isField())
+                               count++;
+
+               if (hierarchyIsInconsistent)
+                       count++;
+               // iterate the field declarations to create the bindings, lose all duplicates
+               FieldBinding[] fieldBindings = new FieldBinding[count];
+               HashtableOfObject knownFieldNames = new HashtableOfObject(count);
+               boolean duplicate = false;
+               count = 0;
+               for (int i = 0; i < size; i++) {
+                       FieldDeclaration field = fields[i];
+                       if (!field.isField()) {
+                               if (referenceContext.binding.isInterface())
+                                       problemReporter().interfaceCannotHaveInitializers(referenceContext.binding, field);
+                       } else {
+                               FieldBinding fieldBinding = new FieldBinding(field, null, field.modifiers | AccUnresolved, referenceContext.binding);
+                               // field's type will be resolved when needed for top level types
+                               checkAndSetModifiersForField(fieldBinding, field);
+
+                               if (knownFieldNames.containsKey(field.name)) {
+                                       duplicate = true;
+                                       FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
+                                       if (previousBinding != null) {
+                                               for (int f = 0; f < i; f++) {
+                                                       FieldDeclaration previousField = fields[f];
+                                                       if (previousField.binding == previousBinding) {
+                                                               problemReporter().duplicateFieldInType(referenceContext.binding, previousField);
+                                                               previousField.binding = null;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
+                                       problemReporter().duplicateFieldInType(referenceContext.binding, field);
+                                       field.binding = null;
+                               } else {
+                                       knownFieldNames.put(field.name, fieldBinding);
+                                       // remember that we have seen a field with this name
+                                       if (fieldBinding != null)
+                                               fieldBindings[count++] = fieldBinding;
+                               }
+                       }
+               }
+               // remove duplicate fields
+               if (duplicate) {
+                       FieldBinding[] newFieldBindings = new FieldBinding[knownFieldNames.size() - 1];
+                       // we know we'll be removing at least 1 duplicate name
+                       size = count;
+                       count = 0;
+                       for (int i = 0; i < size; i++) {
+                               FieldBinding fieldBinding = fieldBindings[i];
+                               if (knownFieldNames.get(fieldBinding.name) != null)
+                                       newFieldBindings[count++] = fieldBinding;
+                       }
+                       fieldBindings = newFieldBindings;
+               }
+               if (hierarchyIsInconsistent)
+                       fieldBindings[count++] = new FieldBinding(IncompleteHierarchy, VoidBinding, AccPrivate, referenceContext.binding, null);
+
+               if (count != fieldBindings.length)
+                       System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
+               for (int i = 0; i < count; i++)
+                       fieldBindings[i].id = i;
+               referenceContext.binding.fields = fieldBindings;
+       }
+       
+       void buildFieldsAndMethods() {
+               buildFields();
+               buildMethods();
+
+               SourceTypeBinding sourceType = referenceContext.binding;
+               if (sourceType.isMemberType() && !sourceType.isLocalType())
+                        ((MemberTypeBinding) sourceType).checkSyntheticArgsAndFields();
+
+               ReferenceBinding[] memberTypes = sourceType.memberTypes;
+               for (int i = 0, length = memberTypes.length; i < length; i++)
+                        ((SourceTypeBinding) memberTypes[i]).scope.buildFieldsAndMethods();
+       }
+       
+       private LocalTypeBinding buildLocalType(
+               SourceTypeBinding enclosingType,
+               PackageBinding packageBinding) {
+           
+               referenceContext.scope = this;
+               referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
+               referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
+
+               // build the binding or the local type
+               LocalTypeBinding localType = new LocalTypeBinding(this, enclosingType, this.switchCase());
+               referenceContext.binding = localType;
+               checkAndSetModifiers();
+
+               // 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()) {
+                                       problemReporter().nestedClassCannotDeclareInterface(memberContext);
+                                       continue nextMember;
+                               }
+                               ReferenceBinding type = localType;
+                               // 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 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, referenceContext.memberTypes[i]);
+                               LocalTypeBinding memberBinding = memberScope.buildLocalType(localType, packageBinding);
+                               memberBinding.setAsMemberType();
+                               memberTypeBindings[count++] = memberBinding;
+                       }
+                       if (count != size)
+                               System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
+               }
+               localType.memberTypes = memberTypeBindings;
+               return localType;
+       }
+       
+       void buildLocalTypeBinding(SourceTypeBinding enclosingType) {
+
+               LocalTypeBinding localType = buildLocalType(enclosingType, enclosingType.fPackage);
+               connectTypeHierarchy();
+               buildFieldsAndMethods();
+               localType.faultInTypesForFieldsAndMethods();
+
+               referenceContext.binding.verifyMethods(environment().methodVerifier());
+       }
+       
+       private void buildMethods() {
+               if (referenceContext.methods == null) {
+                       referenceContext.binding.methods = NoMethods;
+                       return;
+               }
+
+               // iterate the method declarations to create the bindings
+               AbstractMethodDeclaration[] methods = referenceContext.methods;
+               int size = methods.length;
+               int clinitIndex = -1;
+               for (int i = 0; i < size; i++) {
+                       if (methods[i] instanceof Clinit) {
+                               clinitIndex = i;
+                               break;
+                       }
+               }
+               MethodBinding[] methodBindings = new MethodBinding[clinitIndex == -1 ? size : size - 1];
+
+               int count = 0;
+               for (int i = 0; i < size; i++) {
+                       if (i != clinitIndex) {
+                               MethodScope scope = new MethodScope(this, methods[i], false);
+                               MethodBinding methodBinding = scope.createMethod(methods[i]);
+                               if (methodBinding != null) // is null if binding could not be created
+                                       methodBindings[count++] = methodBinding;
+                       }
+               }
+               if (count != methodBindings.length)
+                       System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
+
+               referenceContext.binding.methods = methodBindings;
+               referenceContext.binding.modifiers |= AccUnresolved; // until methods() is sent
+       }
+       SourceTypeBinding buildType(SourceTypeBinding enclosingType, PackageBinding packageBinding) {
+               // provide the typeDeclaration with needed scopes
+               referenceContext.scope = this;
+               referenceContext.staticInitializerScope = new MethodScope(this, referenceContext, true);
+               referenceContext.initializerScope = new MethodScope(this, referenceContext, false);
+
+               if (enclosingType == null) {
+                       char[][] className = CharOperation.arrayConcat(packageBinding.compoundName, referenceContext.name);
+                       referenceContext.binding = new SourceTypeBinding(className, packageBinding, this);
+               } else {
+                       char[][] className = CharOperation.deepCopy(enclosingType.compoundName);
+                       className[className.length - 1] =
+                               CharOperation.concat(className[className.length - 1], referenceContext.name, '$');
+                       referenceContext.binding = new MemberTypeBinding(className, this, enclosingType);
+               }
+
+               SourceTypeBinding sourceType = referenceContext.binding;
+               sourceType.fPackage.addType(sourceType);
+               checkAndSetModifiers();
+
+               // Look at member types
+               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);
+               }
+               sourceType.memberTypes = memberTypeBindings;
+               return sourceType;
+       }
+       
+       private void checkAndSetModifiers() {
+               SourceTypeBinding sourceType = referenceContext.binding;
+               int modifiers = sourceType.modifiers;
+               if ((modifiers & AccAlternateModifierProblem) != 0)
+                       problemReporter().duplicateModifierForType(sourceType);
+
+               ReferenceBinding enclosingType = sourceType.enclosingType();
+               boolean isMemberType = sourceType.isMemberType();
+               
+               if (isMemberType) {
+                       // checks for member types before local types to catch local members
+                       if (enclosingType.isStrictfp())
+                               modifiers |= AccStrictfp;
+                       if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
+                               modifiers |= AccDeprecatedImplicitly;
+                       if (enclosingType.isInterface())
+                               modifiers |= AccPublic;
+               } else if (sourceType.isLocalType()) {
+                       if (sourceType.isAnonymousType()) 
+                           modifiers |= AccFinal;
+                       Scope scope = this;
+                       do {
+                               switch (scope.kind) {
+                                       case METHOD_SCOPE :
+                                               MethodScope methodScope = (MethodScope) scope;
+                                               if (methodScope.isInsideInitializer()) {
+                                                       SourceTypeBinding type = ((TypeDeclaration) methodScope.referenceContext).binding;
+                       
+                                                       // inside field declaration ? check field modifier to see if deprecated
+                                                       if (methodScope.initializedField != null) {
+                                                                       // currently inside this field initialization
+                                                               if (methodScope.initializedField.isViewedAsDeprecated() && !sourceType.isDeprecated()){
+                                                                       modifiers |= AccDeprecatedImplicitly;
+                                                               }
+                                                       } else {
+                                                               if (type.isStrictfp())
+                                                                       modifiers |= AccStrictfp;
+                                                               if (type.isViewedAsDeprecated() && !sourceType.isDeprecated()) 
+                                                                       modifiers |= AccDeprecatedImplicitly;
+                                                       }                                       
+                                               } else {
+                                                       MethodBinding method = ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
+                                                       if (method != null){
+                                                               if (method.isStrictfp())
+                                                                       modifiers |= AccStrictfp;
+                                                               if (method.isViewedAsDeprecated() && !sourceType.isDeprecated())
+                                                                       modifiers |= AccDeprecatedImplicitly;
+                                                       }
+                                               }
+                                               break;
+                                       case CLASS_SCOPE :
+                                               // local member
+                                               if (enclosingType.isStrictfp())
+                                                       modifiers |= AccStrictfp;
+                                               if (enclosingType.isViewedAsDeprecated() && !sourceType.isDeprecated())
+                                                       modifiers |= AccDeprecatedImplicitly;
+                                               break;
+                               }
+                               scope = scope.parent;
+                       } while (scope != null);
+               }
+               // after this point, tests on the 16 bits reserved.
+               int realModifiers = modifiers & AccJustFlag;
+
+               if ((realModifiers & AccInterface) != 0) {
+                       // detect abnormal cases for interfaces
+                       if (isMemberType) {
+                               int unexpectedModifiers =
+                                       ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccInterface | AccStrictfp);
+                               if ((realModifiers & unexpectedModifiers) != 0)
+                                       problemReporter().illegalModifierForMemberInterface(sourceType);
+                               /*
+                               } else if (sourceType.isLocalType()) { //interfaces cannot be defined inside a method
+                                       int unexpectedModifiers = ~(AccAbstract | AccInterface | AccStrictfp);
+                                       if ((realModifiers & unexpectedModifiers) != 0)
+                                               problemReporter().illegalModifierForLocalInterface(sourceType);
+                               */
+                       } else {
+                               int unexpectedModifiers = ~(AccPublic | AccAbstract | AccInterface | AccStrictfp);
+                               if ((realModifiers & unexpectedModifiers) != 0)
+                                       problemReporter().illegalModifierForInterface(sourceType);
+                       }
+                       modifiers |= AccAbstract;
+               } else {
+                       // detect abnormal cases for types
+                       if (isMemberType) { // includes member types defined inside local types
+                               int unexpectedModifiers =
+                                       ~(AccPublic | AccPrivate | AccProtected | AccStatic | AccAbstract | AccFinal | AccStrictfp);
+                               if ((realModifiers & unexpectedModifiers) != 0)
+                                       problemReporter().illegalModifierForMemberClass(sourceType);
+                       } else if (sourceType.isLocalType()) {
+                               int unexpectedModifiers = ~(AccAbstract | AccFinal | AccStrictfp);
+                               if ((realModifiers & unexpectedModifiers) != 0)
+                                       problemReporter().illegalModifierForLocalClass(sourceType);
+                       } else {
+                               int unexpectedModifiers = ~(AccPublic | AccAbstract | AccFinal | AccStrictfp);
+                               if ((realModifiers & unexpectedModifiers) != 0)
+                                       problemReporter().illegalModifierForClass(sourceType);
+                       }
+
+                       // check that Final and Abstract are not set together
+                       if ((realModifiers & (AccFinal | AccAbstract)) == (AccFinal | AccAbstract))
+                               problemReporter().illegalModifierCombinationFinalAbstractForClass(sourceType);
+               }
+
+               if (isMemberType) {
+                       // test visibility modifiers inconsistency, isolate the accessors bits
+                       if (enclosingType.isInterface()) {
+                               if ((realModifiers & (AccProtected | AccPrivate)) != 0) {
+                                       problemReporter().illegalVisibilityModifierForInterfaceMemberType(sourceType);
+
+                                       // need to keep the less restrictive
+                                       if ((realModifiers & AccProtected) != 0)
+                                               modifiers ^= AccProtected;
+                                       if ((realModifiers & AccPrivate) != 0)
+                                               modifiers ^= AccPrivate;
+                               }
+                       } else {
+                               int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
+                               if ((accessorBits & (accessorBits - 1)) > 1) {
+                                       problemReporter().illegalVisibilityModifierCombinationForMemberType(sourceType);
+
+                                       // need to keep the less restrictive
+                                       if ((accessorBits & AccPublic) != 0) {
+                                               if ((accessorBits & AccProtected) != 0)
+                                                       modifiers ^= AccProtected;
+                                               if ((accessorBits & AccPrivate) != 0)
+                                                       modifiers ^= AccPrivate;
+                                       }
+                                       if ((accessorBits & AccProtected) != 0)
+                                               if ((accessorBits & AccPrivate) != 0)
+                                                       modifiers ^= AccPrivate;
+                               }
+                       }
+
+                       // static modifier test
+                       if ((realModifiers & AccStatic) == 0) {
+                               if (enclosingType.isInterface())
+                                       modifiers |= AccStatic;
+                       } else {
+                               if (!enclosingType.isStatic())
+                                       // error the enclosing type of a static field must be static or a top-level type
+                                       problemReporter().illegalStaticModifierForMemberType(sourceType);
+                       }
+               }
+
+               sourceType.modifiers = modifiers;
+       }
+       
+       /* This method checks the modifiers of a field.
+       *
+       * 9.3 & 8.3
+       * Need to integrate the check for the final modifiers for nested types
+       *
+       * Note : A scope is accessible by : fieldBinding.declaringClass.scope
+       */
+       private void checkAndSetModifiersForField(FieldBinding fieldBinding, FieldDeclaration fieldDecl) {
+               int modifiers = fieldBinding.modifiers;
+               if ((modifiers & AccAlternateModifierProblem) != 0)
+                       problemReporter().duplicateModifierForField(fieldBinding.declaringClass, fieldDecl);
+
+               if (fieldBinding.declaringClass.isInterface()) {
+                       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);
+                       fieldBinding.modifiers = modifiers;
+                       return;
+               }
+
+               // after this point, tests on the 16 bits reserved.
+               int realModifiers = modifiers & AccJustFlag;
+               int unexpectedModifiers =
+                       ~(AccPublic | AccPrivate | AccProtected | AccFinal | AccStatic | AccTransient | AccVolatile);
+               if ((realModifiers & unexpectedModifiers) != 0)
+                       problemReporter().illegalModifierForField(fieldBinding.declaringClass, fieldDecl);
+
+               int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
+               if ((accessorBits & (accessorBits - 1)) > 1) {
+                       problemReporter().illegalVisibilityModifierCombinationForField(
+                               fieldBinding.declaringClass,
+                               fieldDecl);
+
+                       // need to keep the less restrictive
+                       if ((accessorBits & AccPublic) != 0) {
+                               if ((accessorBits & AccProtected) != 0)
+                                       modifiers ^= AccProtected;
+                               if ((accessorBits & AccPrivate) != 0)
+                                       modifiers ^= AccPrivate;
+                       }
+                       if ((accessorBits & AccProtected) != 0)
+                               if ((accessorBits & AccPrivate) != 0)
+                                       modifiers ^= AccPrivate;
+               }
+
+               if ((realModifiers & (AccFinal | AccVolatile)) == (AccFinal | AccVolatile))
+                       problemReporter().illegalModifierCombinationFinalVolatileForField(
+                               fieldBinding.declaringClass,
+                               fieldDecl);
+
+               if (fieldDecl.initialization == null && (modifiers & AccFinal) != 0) {
+                       modifiers |= AccBlankFinal;
+               }
+               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
+               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
+                       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);
+                               interfacesToVisit[lastPosition] = itsInterfaces;
+                       }
+               } while ((currentType = currentType.superclass()) != null);
+
+               boolean hasMembers = false;
+               if (interfacesToVisit != null) {
+                       done : 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;
+                                               }
+
+                                               ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
+                                               if (itsInterfaces != NoSuperInterfaces) {
+                                                       if (++lastPosition == interfacesToVisit.length)
+                                                               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)
+                                               interfaces[j].tagBits |= HasNoMemberTypes;
+                               }
+                       }
+               }
+
+               if (!hasMembers) {
+                       currentType = sourceType;
+                       do {
+                               currentType.tagBits |= HasNoMemberTypes;
+                       } while ((currentType = currentType.superclass()) != null);
+               }
+       }
+       
+       private void connectMemberTypes() {
+               SourceTypeBinding sourceType = referenceContext.binding;
+               if (sourceType.memberTypes != NoMemberTypes)
+                       for (int i = 0, size = sourceType.memberTypes.length; i < size; i++)
+                                ((SourceTypeBinding) sourceType.memberTypes[i]).scope.connectTypeHierarchy();
+       }
+       /*
+               Our current belief based on available JCK tests is:
+                       inherited member types are visible as a potential superclass.
+                       inherited interfaces are not visible when defining a superinterface.
+       
+               Error recovery story:
+                       ensure the superclass is set to java.lang.Object if a problem is detected
+                       resolving the superclass.
+       
+               Answer false if an error was reported against the sourceType.
+       */
+       private boolean connectSuperclass() {
+               SourceTypeBinding sourceType = referenceContext.binding;
+               if (sourceType.id == T_Object) { // handle the case of redefining java.lang.Object up front
+                       sourceType.superclass = null;
+                       sourceType.superInterfaces = NoSuperInterfaces;
+                       if (referenceContext.superclass != null || referenceContext.superInterfaces != null)
+                               problemReporter().objectCannotHaveSuperTypes(sourceType);
+                       return true; // do not propagate Object's hierarchy problems down to every subtype
+               }
+               if (referenceContext.superclass == null) {
+                       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);
+                       } else if (superclass.isFinal()) {
+                               problemReporter().classExtendFinalClass(sourceType, referenceContext.superclass, superclass);
+                       } else {
+                               // only want to reach here when no errors are reported
+                               sourceType.superclass = superclass;
+                               return true;
+                       }
+               }
+               sourceType.tagBits |= HierarchyHasProblems;
+               sourceType.superclass = getJavaLangObject();
+               if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
+                       detectCycle(sourceType, sourceType.superclass, null);
+               return false; // reported some error against the source type
+       }
+
+       /*
+               Our current belief based on available JCK 1.3 tests is:
+                       inherited member types are visible as a potential superclass.
+                       inherited interfaces are visible when defining a superinterface.
+       
+               Error recovery story:
+                       ensure the superinterfaces contain only valid visible interfaces.
+       
+               Answer false if an error was reported against the sourceType.
+       */
+       private boolean connectSuperInterfaces() {
+               SourceTypeBinding sourceType = referenceContext.binding;
+               sourceType.superInterfaces = NoSuperInterfaces;
+               if (referenceContext.superInterfaces == null)
+                       return true;
+               if (sourceType.id == T_Object) // already handled the case of redefining java.lang.Object
+                       return true;
+
+               boolean noProblems = true;
+               int length = referenceContext.superInterfaces.length;
+               ReferenceBinding[] interfaceBindings = new ReferenceBinding[length];
+               int count = 0;
+               nextInterface : for (int i = 0; i < length; i++) {
+                       ReferenceBinding superInterface = findSupertype(referenceContext.superInterfaces[i]);
+                       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;
+                       }
+                       // 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) {
+                                       // should this be treated as a warning?
+                                       problemReporter().duplicateSuperinterface(sourceType, referenceContext, superInterface);
+                                       continue nextInterface;
+                               }
+                       }
+                       if (superInterface.isClass()) {
+                               problemReporter().superinterfaceMustBeAnInterface(sourceType, referenceContext, superInterface);
+                               sourceType.tagBits |= HierarchyHasProblems;
+                               noProblems = false;
+                               continue nextInterface;
+                       }
+
+                       // only want to reach here when no errors are reported
+                       interfaceBindings[count++] = superInterface;
+               }
+               // hold onto all correctly resolved superinterfaces
+               if (count > 0) {
+                       if (count != length)
+                               System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
+                       sourceType.superInterfaces = interfaceBindings;
+               }
+               return noProblems;
+       }
+       
+       void connectTypeHierarchy() {
+               SourceTypeBinding sourceType = referenceContext.binding;
+               if ((sourceType.tagBits & BeginHierarchyCheck) == 0) {
+                       boolean noProblems = true;
+                       sourceType.tagBits |= BeginHierarchyCheck;
+                       if (sourceType.isClass())
+                               noProblems &= connectSuperclass();
+                       noProblems &= connectSuperInterfaces();
+                       sourceType.tagBits |= EndHierarchyCheck;
+                       if (noProblems && sourceType.isHierarchyInconsistent())
+                               problemReporter().hierarchyHasProblems(sourceType);
+               }
+               connectMemberTypes();
+               try {
+                       checkForInheritedMemberTypes(sourceType);
+               } catch (AbortCompilation e) {
+                       e.updateContext(referenceContext, referenceCompilationUnit().compilationResult);
+                       throw e;
+               }
+       }
+       
+       private void connectTypeHierarchyWithoutMembers() {
+               // must ensure the imports are resolved
+               if (parent instanceof CompilationUnitScope) {
+                       if (((CompilationUnitScope) parent).imports == null)
+                                ((CompilationUnitScope) parent).checkAndSetImports();
+               } else if (parent instanceof ClassScope) {
+                       // ensure that the enclosing type has already been checked
+                        ((ClassScope) parent).connectTypeHierarchyWithoutMembers();
+               }
+
+               // double check that the hierarchy search has not already begun...
+               SourceTypeBinding sourceType = referenceContext.binding;
+               if ((sourceType.tagBits & BeginHierarchyCheck) != 0)
+                       return;
+
+               boolean noProblems = true;
+               sourceType.tagBits |= BeginHierarchyCheck;
+               if (sourceType.isClass())
+                       noProblems &= connectSuperclass();
+               noProblems &= connectSuperInterfaces();
+               sourceType.tagBits |= EndHierarchyCheck;
+               if (noProblems && sourceType.isHierarchyInconsistent())
+                       problemReporter().hierarchyHasProblems(sourceType);
+       }
+       
+       // Answer whether a cycle was found between the sourceType & the superType
+       private boolean detectCycle(
+               SourceTypeBinding sourceType,
+               ReferenceBinding superType,
+               TypeReference reference) {
+               if (sourceType == superType) {
+                       problemReporter().hierarchyCircularity(sourceType, superType, reference);
+                       sourceType.tagBits |= HierarchyHasProblems;
+                       return true;
+               }
+
+               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
+                       //              - another source type... this case is reported against the other source type
+                       boolean hasCycle = false;
+                       if (superType.superclass() != null) {
+                               if (sourceType == superType.superclass()) {
+                                       problemReporter().hierarchyCircularity(sourceType, superType, reference);
+                                       sourceType.tagBits |= HierarchyHasProblems;
+                                       superType.tagBits |= HierarchyHasProblems;
+                                       return true;
+                               }
+                               hasCycle |= detectCycle(sourceType, superType.superclass(), reference);
+                               if ((superType.superclass().tagBits & HierarchyHasProblems) != 0) {
+                                       sourceType.tagBits |= HierarchyHasProblems;
+                                       superType.tagBits |= HierarchyHasProblems; // propagate down the hierarchy
+                               }
+                       }
+
+                       ReferenceBinding[] itsInterfaces = superType.superInterfaces();
+                       if (itsInterfaces != NoSuperInterfaces) {
+                               for (int i = 0, length = itsInterfaces.length; i < length; i++) {
+                                       ReferenceBinding anInterface = itsInterfaces[i];
+                                       if (sourceType == anInterface) {
+                                               problemReporter().hierarchyCircularity(sourceType, superType, reference);
+                                               sourceType.tagBits |= HierarchyHasProblems;
+                                               superType.tagBits |= HierarchyHasProblems;
+                                               return true;
+                                       }
+                                       hasCycle |= detectCycle(sourceType, anInterface, reference);
+                                       if ((anInterface.tagBits & HierarchyHasProblems) != 0) {
+                                               sourceType.tagBits |= HierarchyHasProblems;
+                                               superType.tagBits |= HierarchyHasProblems;
+                                       }
+                               }
+                       }
+                       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.tagBits & BeginHierarchyCheck) == 0)
+                       // ensure if this is a source superclass that it has already been checked
+                        ((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);
+                               }
+                       }
+                       // 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;
+                               }
+                       }
+                       return superType;
+               } catch (AbortCompilation e) {
+                       e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
+                       throw e;
+               }
+       }
+
+       /* Answer the problem reporter to use for raising new problems.
+       *
+       * Note that as a side-effect, this updates the current reference context
+       * (unit, type or method) in case the problem handler decides it is necessary
+       * to abort.
+       */
+       public ProblemReporter problemReporter() {
+               MethodScope outerMethodScope;
+               if ((outerMethodScope = outerMostMethodScope()) == null) {
+                       ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
+                       problemReporter.referenceContext = referenceContext;
+                       return problemReporter;
+               }
+               return outerMethodScope.problemReporter();
+       }
+
+       /* Answer the reference type of this scope.
+       * It is the nearest enclosing type of this scope.
+       */
+       public TypeDeclaration referenceType() {
+               return referenceContext;
+       }
+       
+       public String toString() {
+               if (referenceContext != null)
+                       return "--- Class Scope ---\n\n"  //$NON-NLS-1$
+                                                       + referenceContext.binding.toString();
+               return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
new file mode 100644 (file)
index 0000000..d4a8d4f
--- /dev/null
@@ -0,0 +1,604 @@
+/*******************************************************************************
+ * 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.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.CompoundNameVector;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
+import org.eclipse.jdt.internal.compiler.util.ObjectVector;
+import org.eclipse.jdt.internal.compiler.util.SimpleNameVector;
+
+public class CompilationUnitScope extends Scope {
+       
+       public LookupEnvironment environment;
+       public CompilationUnitDeclaration referenceContext;
+       public char[][] currentPackageName;
+       public PackageBinding fPackage;
+       public ImportBinding[] imports;
+       public HashtableOfObject resolvedSingeTypeImports;
+       
+       public SourceTypeBinding[] topLevelTypes;
+
+       private CompoundNameVector qualifiedReferences;
+       private SimpleNameVector simpleNameReferences;
+       private ObjectVector referencedTypes;
+       
+       HashtableOfType constantPoolNameUsage;
+
+public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment environment) {
+       super(COMPILATION_UNIT_SCOPE, null);
+       this.environment = environment;
+       this.referenceContext = unit;
+       unit.scope = this;
+       this.currentPackageName = unit.currentPackage == null ? CharOperation.NO_CHAR_CHAR : unit.currentPackage.tokens;
+
+       if (environment.options.produceReferenceInfo) {
+               this.qualifiedReferences = new CompoundNameVector();
+               this.simpleNameReferences = new SimpleNameVector();
+               this.referencedTypes = new ObjectVector();
+       } else {
+               this.qualifiedReferences = null; // used to test if dependencies should be recorded
+               this.simpleNameReferences = null;
+               this.referencedTypes = null;
+       }
+}
+void buildFieldsAndMethods() {
+       for (int i = 0, length = topLevelTypes.length; i < length; i++)
+               topLevelTypes[i].scope.buildFieldsAndMethods();
+}
+void buildTypeBindings() {
+       topLevelTypes = new SourceTypeBinding[0]; // want it initialized if the package cannot be resolved
+       if (referenceContext.compilationResult.compilationUnit != null) {
+               char[][] expectedPackageName = referenceContext.compilationResult.compilationUnit.getPackageName();
+               if (expectedPackageName != null 
+                               && !CharOperation.equals(currentPackageName, expectedPackageName)) {
+
+                       // only report if the unit isn't structurally empty
+                       if (referenceContext.currentPackage != null 
+                                       || referenceContext.types != null 
+                                       || referenceContext.imports != null) {
+                               problemReporter().packageIsNotExpectedPackage(referenceContext);
+                       }
+                       currentPackageName = expectedPackageName.length == 0 ? CharOperation.NO_CHAR_CHAR : expectedPackageName;
+               }
+       }
+       if (currentPackageName == CharOperation.NO_CHAR_CHAR) {
+               if ((fPackage = environment.defaultPackage) == null) {
+                       problemReporter().mustSpecifyPackage(referenceContext);
+                       return;
+               }
+       } else {
+               if ((fPackage = environment.createPackage(currentPackageName)) == null) {
+                       problemReporter().packageCollidesWithType(referenceContext);
+                       return;
+               }
+               recordQualifiedReference(currentPackageName); // always dependent on your own package
+       }
+
+       // Skip typeDeclarations which know of previously reported errors
+       TypeDeclaration[] types = referenceContext.types;
+       int typeLength = (types == null) ? 0 : types.length;
+       topLevelTypes = new SourceTypeBinding[typeLength];
+       int count = 0;
+       nextType: for (int i = 0; i < typeLength; i++) {
+               TypeDeclaration typeDecl = types[i];
+               ReferenceBinding typeBinding = fPackage.getType0(typeDecl.name);
+               recordSimpleReference(typeDecl.name); // needed to detect collision cases
+               if (typeBinding != null && !(typeBinding instanceof UnresolvedReferenceBinding)) {
+                       // if a type exists, it must be a valid type - cannot be a NotFound problem type
+                       // unless its an unresolved type which is now being defined
+                       problemReporter().duplicateTypes(referenceContext, typeDecl);
+                       continue nextType;
+               }
+               if (fPackage != environment.defaultPackage && fPackage.getPackage(typeDecl.name) != null) {
+                       // if a package exists, it must be a valid package - cannot be a NotFound problem package
+                       problemReporter().typeCollidesWithPackage(referenceContext, typeDecl);
+                       continue nextType;
+               }
+
+               if ((typeDecl.modifiers & AccPublic) != 0) {
+                       char[] mainTypeName;
+                       if ((mainTypeName = referenceContext.getMainTypeName()) != null // mainTypeName == null means that implementor of ICompilationUnit decided to return null
+                                       && !CharOperation.equals(mainTypeName, typeDecl.name)) {
+                               problemReporter().publicClassMustMatchFileName(referenceContext, typeDecl);
+                               continue nextType;
+                       }
+               }
+
+               ClassScope child = new ClassScope(this, typeDecl);
+               SourceTypeBinding type = child.buildType(null, fPackage);
+               if(type != null) {
+                       topLevelTypes[count++] = type;
+               }
+       }
+
+       // shrink topLevelTypes... only happens if an error was reported
+       if (count != topLevelTypes.length)
+               System.arraycopy(topLevelTypes, 0, topLevelTypes = new SourceTypeBinding[count], 0, count);
+}
+void checkAndSetImports() {
+       if (referenceContext.imports == null) {
+               imports = getDefaultImports();
+               return;
+       }
+
+       // allocate the import array, add java.lang.* by default
+       int numberOfStatements = referenceContext.imports.length;
+       int numberOfImports = numberOfStatements + 1;
+       for (int i = 0; i < numberOfStatements; i++) {
+               ImportReference importReference = referenceContext.imports[i];
+               if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+                       numberOfImports--;
+                       break;
+               }
+       }
+       ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
+       resolvedImports[0] = getDefaultImports()[0];
+       int index = 1;
+
+       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))
+                                       continue nextImport;
+               if (importReference.onDemand == true)
+                       if (CharOperation.equals(compoundName, currentPackageName))
+                               continue nextImport;
+
+               if (importReference.onDemand) {
+                       Binding importBinding = findOnDemandImport(compoundName);
+                       if (!importBinding.isValidBinding())
+                               continue nextImport;    // we report all problems in faultInImports()
+                       resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
+               } else {
+                       resolvedImports[index++] = new ImportBinding(compoundName, false, null, importReference);
+               }
+       }
+
+       // shrink resolvedImports... only happens if an error was reported
+       if (resolvedImports.length > index)
+               System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index);
+       imports = resolvedImports;
+}
+/*
+ * INTERNAL USE-ONLY
+ * Innerclasses get their name computed as they are generated, since some may not
+ * be actually outputed if sitting inside unreachable code.
+ */
+public char[] computeConstantPoolName(LocalTypeBinding localType) {
+       if (localType.constantPoolName() != null) {
+               return localType.constantPoolName();
+       }
+       // delegates to the outermost enclosing classfile, since it is the only one with a global vision of its innertypes.
+
+       if (constantPoolNameUsage == null)
+               constantPoolNameUsage = new HashtableOfType();
+
+       ReferenceBinding outerMostEnclosingType = localType.scope.outerMostClassScope().enclosingSourceType();
+       
+       // ensure there is not already such a local type name defined by the user
+       int index = 0;
+       char[] candidateName;
+       while(true) {
+               if (localType.isMemberType()){
+                       if (index == 0){
+                               candidateName = CharOperation.concat(
+                                       localType.enclosingType().constantPoolName(),
+                                       localType.sourceName,
+                                       '$');
+                       } else {
+                               // in case of collision, then member name gets extra $1 inserted
+                               // e.g. class X { { class L{} new X(){ class L{} } } }
+                               candidateName = CharOperation.concat(
+                                       localType.enclosingType().constantPoolName(),
+                                       '$',
+                                       String.valueOf(index).toCharArray(),
+                                       '$',
+                                       localType.sourceName);
+                       }
+               } else if (localType.isAnonymousType()){
+                               candidateName = CharOperation.concat(
+                                       outerMostEnclosingType.constantPoolName(),
+                                       String.valueOf(index+1).toCharArray(),
+                                       '$');
+               } else {
+                               candidateName = CharOperation.concat(
+                                       outerMostEnclosingType.constantPoolName(),
+                                       '$',
+                                       String.valueOf(index+1).toCharArray(),
+                                       '$',
+                                       localType.sourceName);
+               }                                               
+               if (constantPoolNameUsage.get(candidateName) != null) {
+                       index ++;
+               } else {
+                       constantPoolNameUsage.put(candidateName, localType);
+                       break;
+               }
+       }
+       return candidateName;
+}
+
+void connectTypeHierarchy() {
+       for (int i = 0, length = topLevelTypes.length; i < length; i++)
+               topLevelTypes[i].scope.connectTypeHierarchy();
+}
+void faultInImports() {
+       if (referenceContext.imports == null)
+               return;
+
+       // collect the top level type names if a single type import exists
+       int numberOfStatements = referenceContext.imports.length;
+       HashtableOfType typesBySimpleNames = null;
+       for (int i = 0; i < numberOfStatements; i++) {
+               if (!referenceContext.imports[i].onDemand) {
+                       typesBySimpleNames = new HashtableOfType(topLevelTypes.length + numberOfStatements);
+                       for (int j = 0, length = topLevelTypes.length; j < length; j++)
+                               typesBySimpleNames.put(topLevelTypes[j].sourceName, topLevelTypes[j]);
+                       break;
+               }
+       }
+
+       // allocate the import array, add java.lang.* by default
+       int numberOfImports = numberOfStatements + 1;
+       for (int i = 0; i < numberOfStatements; i++) {
+               ImportReference importReference = referenceContext.imports[i];
+               if (importReference.onDemand && CharOperation.equals(JAVA_LANG, importReference.tokens)) {
+                       numberOfImports--;
+                       break;
+               }
+       }
+       ImportBinding[] resolvedImports = new ImportBinding[numberOfImports];
+       resolvedImports[0] = getDefaultImports()[0];
+       int index = 1;
+
+       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)) {
+                                       problemReporter().unusedImport(importReference); // since skipped, must be reported now
+                                       continue nextImport;
+                               }
+               if (importReference.onDemand == true)
+                       if (CharOperation.equals(compoundName, currentPackageName)) {
+                               problemReporter().unusedImport(importReference); // since skipped, must be reported now
+                               continue nextImport;
+                       }
+               if (importReference.onDemand) {
+                       Binding importBinding = findOnDemandImport(compoundName);
+                       if (!importBinding.isValidBinding()) {
+                               problemReporter().importProblem(importReference, importBinding);
+                               continue nextImport;
+                       }
+                       resolvedImports[index++] = new ImportBinding(compoundName, true, importBinding, importReference);
+               } else {
+                       Binding typeBinding = findSingleTypeImport(compoundName);
+                       if (!typeBinding.isValidBinding()) {
+                               problemReporter().importProblem(importReference, typeBinding);
+                               continue nextImport;
+                       }
+                       if (typeBinding instanceof PackageBinding) {
+                               problemReporter().cannotImportPackage(importReference);
+                               continue nextImport;
+                       }
+                       if (typeBinding instanceof ReferenceBinding) {
+                               ReferenceBinding referenceBinding = (ReferenceBinding) typeBinding;
+                               if (importReference.isTypeUseDeprecated(referenceBinding, this)) {
+                                       problemReporter().deprecatedType((TypeBinding) typeBinding, importReference);
+                               }
+                       }
+                       ReferenceBinding existingType = typesBySimpleNames.get(compoundName[compoundName.length - 1]);
+                       if (existingType != null) {
+                               // duplicate test above should have caught this case, but make sure
+                               if (existingType == typeBinding) {
+                                       continue nextImport;
+                               }
+                               // either the type collides with a top level type or another imported type
+                               for (int j = 0, length = topLevelTypes.length; j < length; j++) {
+                                       if (CharOperation.equals(topLevelTypes[j].sourceName, existingType.sourceName)) {
+                                               problemReporter().conflictingImport(importReference);
+                                               continue nextImport;
+                                       }
+                               }
+                               problemReporter().duplicateImport(importReference);
+                               continue nextImport;
+                       }
+                       resolvedImports[index++] = new ImportBinding(compoundName, false, typeBinding, importReference);
+                       typesBySimpleNames.put(compoundName[compoundName.length - 1], (ReferenceBinding) typeBinding);
+               }
+       }
+
+       // shrink resolvedImports... only happens if an error was reported
+       if (resolvedImports.length > index)
+               System.arraycopy(resolvedImports, 0, resolvedImports = new ImportBinding[index], 0, index);
+       imports = resolvedImports;
+
+       int length = imports.length;
+       resolvedSingeTypeImports = new HashtableOfObject(length);
+       for (int i = 0; i < length; i++) {
+               ImportBinding binding = imports[i];
+               if (!binding.onDemand)
+                       resolvedSingeTypeImports.put(binding.compoundName[binding.compoundName.length - 1], binding);
+       }
+}
+public void faultInTypes() {
+       faultInImports();
+
+       for (int i = 0, length = topLevelTypes.length; i < length; i++)
+               topLevelTypes[i].faultInTypesForFieldsAndMethods();
+}
+private Binding findOnDemandImport(char[][] compoundName) {
+       recordQualifiedReference(compoundName);
+
+       Binding binding = environment.getTopLevelPackage(compoundName[0]);
+       int i = 1;
+       int length = compoundName.length;
+       foundNothingOrType: if (binding != null) {
+               PackageBinding packageBinding = (PackageBinding) binding;
+               while (i < length) {
+                       binding = packageBinding.getTypeOrPackage(compoundName[i++]);
+                       if (binding == null || !binding.isValidBinding()) {
+                               binding = null;
+                               break foundNothingOrType;
+                       }
+                       if (!(binding instanceof PackageBinding))
+                               break foundNothingOrType;
+
+                       packageBinding = (PackageBinding) binding;
+               }
+               return packageBinding;
+       }
+
+       ReferenceBinding type;
+       if (binding == null) {
+               if (environment.defaultPackage == null
+                               || environment.options.complianceLevel >= 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);
+               i = 1; // reset to look for member types inside the default package type
+       } else {
+               type = (ReferenceBinding) binding;
+       }
+
+       for (; i < length; i++) {
+               if (!type.canBeSeenBy(fPackage)) {
+                       return new ProblemReferenceBinding(CharOperation.subarray(compoundName, 0, i), type, NotVisible);               
+               }
+               // does not look for inherited member types on purpose
+               if ((type = type.getMemberType(compoundName[i])) == null) {
+                       return new ProblemReferenceBinding(
+                               CharOperation.subarray(compoundName, 0, i + 1),
+                               NotFound);
+               }
+       }
+       if (!type.canBeSeenBy(fPackage))
+               return new ProblemReferenceBinding(compoundName, type, NotVisible);
+       return type;
+}
+private Binding findSingleTypeImport(char[][] compoundName) {
+       if (compoundName.length == 1) {
+               // findType records the reference
+               // the name cannot be a package
+               if (environment.defaultPackage == null 
+                       || environment.options.complianceLevel >= 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);
+}
+ImportBinding[] getDefaultImports() {
+       // initialize the default imports if necessary... share the default java.lang.* import
+       if (environment.defaultImports != null) return environment.defaultImports;
+
+       Binding importBinding = environment.getTopLevelPackage(JAVA);
+       if (importBinding != null)
+               importBinding = ((PackageBinding) importBinding).getTypeOrPackage(JAVA_LANG[1]);
+
+       // abort if java.lang cannot be found...
+       if (importBinding == null || !importBinding.isValidBinding())
+               problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
+
+       return environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)};
+}
+/* Answer the problem reporter to use for raising new problems.
+*
+* Note that as a side-effect, this updates the current reference context
+* (unit, type or method) in case the problem handler decides it is necessary
+* to abort.
+*/
+
+public ProblemReporter problemReporter() {
+       ProblemReporter problemReporter = referenceContext.problemReporter;
+       problemReporter.referenceContext = referenceContext;
+       return problemReporter;
+}
+
+/*
+What do we hold onto:
+
+1. when we resolve 'a.b.c', say we keep only 'a.b.c'
+ & when we fail to resolve 'c' in 'a.b', lets keep 'a.b.c'
+THEN when we come across a new/changed/removed item named 'a.b.c',
+ we would find all references to 'a.b.c'
+-> This approach fails because every type is resolved in every onDemand import to
+ detect collision cases... so the references could be 10 times bigger than necessary.
+
+2. when we resolve 'a.b.c', lets keep 'a.b' & 'c'
+ & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'c'
+THEN when we come across a new/changed/removed item named 'a.b.c',
+ we would find all references to 'a.b' & 'c'
+-> This approach does not have a space problem but fails to handle collision cases.
+ What happens if a type is added named 'a.b'? We would search for 'a' & 'b' but
+ would not find a match.
+
+3. when we resolve 'a.b.c', lets keep 'a', 'a.b' & 'a', 'b', 'c'
+ & when we fail to resolve 'c' in 'a.b', lets keep 'a', 'a.b' & 'a', 'b', 'c'
+THEN when we come across a new/changed/removed item named 'a.b.c',
+ we would find all references to 'a.b' & 'c'
+OR 'a.b' -> 'a' & 'b'
+OR 'a' -> '' & 'a'
+-> As long as each single char[] is interned, we should not have a space problem
+ and can handle collision cases.
+
+4. when we resolve 'a.b.c', lets keep 'a.b' & 'a', 'b', 'c'
+ & when we fail to resolve 'c' in 'a.b', lets keep 'a.b' & 'a', 'b', 'c'
+THEN when we come across a new/changed/removed item named 'a.b.c',
+ we would find all references to 'a.b' & 'c'
+OR 'a.b' -> 'a' & 'b' in the simple name collection
+OR 'a' -> 'a' in the simple name collection
+-> As long as each single char[] is interned, we should not have a space problem
+ and can handle collision cases.
+*/
+void recordQualifiedReference(char[][] qualifiedName) {
+       if (qualifiedReferences == null) return; // not recording dependencies
+
+       int length = qualifiedName.length;
+       if (length > 1) {
+               while (!qualifiedReferences.contains(qualifiedName)) {
+                       qualifiedReferences.add(qualifiedName);
+                       if (length == 2) {
+                               recordSimpleReference(qualifiedName[0]);
+                               recordSimpleReference(qualifiedName[1]);
+                               return;
+                       }
+                       length--;
+                       recordSimpleReference(qualifiedName[length]);
+                       System.arraycopy(qualifiedName, 0, qualifiedName = new char[length][], 0, length);
+               }
+       } else if (length == 1) {
+               recordSimpleReference(qualifiedName[0]);
+       }
+}
+void recordReference(char[][] qualifiedEnclosingName, char[] simpleName) {
+       recordQualifiedReference(qualifiedEnclosingName);
+       recordSimpleReference(simpleName);
+}
+void recordSimpleReference(char[] simpleName) {
+       if (simpleNameReferences == null) return; // not recording dependencies
+
+       if (!simpleNameReferences.contains(simpleName))
+               simpleNameReferences.add(simpleName);
+}
+void recordTypeReference(TypeBinding type) {
+       if (referencedTypes == null) return; // not recording dependencies
+
+       if (type.isArrayType())
+               type = ((ArrayBinding) type).leafComponentType;
+
+       if (type.isBaseType()) return;
+       if (referencedTypes.containsIdentical(type)) return;
+       if (((ReferenceBinding) type).isLocalType()) return;
+
+       referencedTypes.add(type);
+}
+void recordTypeReferences(TypeBinding[] types) {
+       if (qualifiedReferences == null) return; // not recording dependencies
+       if (types == null || types.length == 0) return;
+
+       for (int i = 0, max = types.length; i < max; i++) {
+               // No need to record supertypes of method arguments & thrown exceptions, just the compoundName
+               // If a field/method is retrieved from such a type then a separate call does the job
+               TypeBinding type = types[i];
+               if (type.isArrayType())
+                       type = ((ArrayBinding) type).leafComponentType;
+               if (!type.isBaseType()) {
+                       ReferenceBinding actualType = (ReferenceBinding) type;
+                       if (!actualType.isLocalType())
+                               recordQualifiedReference(actualType.isMemberType()
+                                       ? CharOperation.splitOn('.', actualType.readableName())
+                                       : actualType.compoundName);
+               }
+       }
+}
+Binding resolveSingleTypeImport(ImportBinding importBinding) {
+       if (importBinding.resolvedImport == null) {
+               importBinding.resolvedImport = findSingleTypeImport(importBinding.compoundName);
+               if (!importBinding.resolvedImport.isValidBinding() || importBinding.resolvedImport instanceof PackageBinding) {
+                       if (this.imports != null){
+                               ImportBinding[] newImports = new ImportBinding[imports.length - 1];
+                               for (int i = 0, n = 0, max = this.imports.length; i < max; i++)
+                                       if (this.imports[i] != importBinding){
+                                               newImports[n++] = this.imports[i];
+                                       }
+                               this.imports = newImports;
+                       }
+                       return null;
+               }
+       }
+       return importBinding.resolvedImport;
+}
+public void storeDependencyInfo() {
+       // add the type hierarchy of each referenced type
+       // cannot do early since the hierarchy may not be fully resolved
+       for (int i = 0; i < referencedTypes.size; i++) { // grows as more types are added
+               ReferenceBinding type = (ReferenceBinding) referencedTypes.elementAt(i);
+               if (!type.isLocalType()) {
+                       recordQualifiedReference(type.isMemberType()
+                               ? CharOperation.splitOn('.', type.readableName())
+                               : type.compoundName);
+                       ReferenceBinding enclosing = type.enclosingType();
+                       if (enclosing != null && !referencedTypes.containsIdentical(enclosing))
+                               referencedTypes.add(enclosing); // to record its supertypes
+               }
+               ReferenceBinding superclass = type.superclass();
+               if (superclass != null && !referencedTypes.containsIdentical(superclass))
+                               referencedTypes.add(superclass); // to record its supertypes
+               ReferenceBinding[] interfaces = type.superInterfaces();
+               if (interfaces != null && interfaces.length > 0)
+                       for (int j = 0, length = interfaces.length; j < length; j++)
+                               if (!referencedTypes.containsIdentical(interfaces[j]))
+                                       referencedTypes.add(interfaces[j]); // to record its supertypes
+       }
+
+       int size = qualifiedReferences.size;
+       char[][][] qualifiedRefs = new char[size][][];
+       for (int i = 0; i < size; i++)
+               qualifiedRefs[i] = qualifiedReferences.elementAt(i);
+       referenceContext.compilationResult.qualifiedReferences = qualifiedRefs;
+
+       size = simpleNameReferences.size;
+       char[][] simpleRefs = new char[size][];
+       for (int i = 0; i < size; i++)
+               simpleRefs[i] = simpleNameReferences.elementAt(i);
+       referenceContext.compilationResult.simpleNameReferences = simpleRefs;
+}
+public String toString() {
+       return "--- CompilationUnit Scope : " + new String(referenceContext.getFileName()); //$NON-NLS-1$
+}
+public void verifyMethods(MethodVerifier verifier) {
+       for (int i = 0, length = topLevelTypes.length; i < length; i++)
+               topLevelTypes[i].verifyMethods(verifier);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/CompilerModifiers.java
new file mode 100644 (file)
index 0000000..31f21cc
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.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
+       // 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 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)
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
new file mode 100644 (file)
index 0000000..4889096
--- /dev/null
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * 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.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+
+public class FieldBinding extends VariableBinding {
+       public ReferenceBinding declaringClass;
+protected FieldBinding() {
+       // for creating problem field
+}
+public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
+       this.modifiers = modifiers;
+       this.type = type;
+       this.name = name;
+       this.declaringClass = declaringClass;
+       this.constant = constant;
+
+       // propagate the deprecated modifier
+       if (this.declaringClass != null)
+               if (this.declaringClass.isViewedAsDeprecated() && !isDeprecated())
+                       this.modifiers |= AccDeprecatedImplicitly;
+}
+public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, ReferenceBinding declaringClass) {
+       this(field.name, type, modifiers, declaringClass, null);
+       field.binding = this; // record binding in declaration
+}
+// special API used to change field declaring class for runtime visibility check
+public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
+       this.modifiers = initialFieldBinding.modifiers;
+       this.type = initialFieldBinding.type;
+       this.name = initialFieldBinding.name;
+       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() {
+       return FIELD;
+}
+/* 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.
+*
+* NOTE: Cannot invoke this method with a compilation unit scope.
+*/
+
+public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
+       if (isPublic()) return true;
+
+       SourceTypeBinding invocationType = scope.enclosingSourceType();
+       if (invocationType == declaringClass && invocationType == receiverType) return true;
+
+       if (isProtected()) {
+               // answer true if the invocationType is the declaringClass or they are in the same package
+               // OR the invocationType is a subclass of the declaringClass
+               //    AND the receiverType is the invocationType or its subclass
+               //    OR the method is a static method accessed directly through a type
+               //    OR previous assertions are true for one of the enclosing type
+               if (invocationType == declaringClass) return true;
+               if (invocationType.fPackage == declaringClass.fPackage) return true;
+               
+               ReferenceBinding currentType = invocationType;
+               int depth = 0;
+               do {
+                       if (declaringClass.isSuperclassOf(currentType)) {
+                               if (invocationSite.isSuperAccess()){
+                                       return true;
+                               }
+                               // receiverType can be an array binding in one case... see if you can change it
+                               if (receiverType instanceof ArrayBinding){
+                                       return false;
+                               }
+                               if (isStatic()){
+                                       if (depth > 0) invocationSite.setDepth(depth);
+                                       return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
+                               }
+                               if (currentType == receiverType || currentType.isSuperclassOf((ReferenceBinding) receiverType)){
+                                       if (depth > 0) invocationSite.setDepth(depth);
+                                       return true;
+                               }
+                       }
+                       depth++;
+                       currentType = currentType.enclosingType();
+               } while (currentType != null);
+               return false;
+       }
+
+       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;
+
+               if (invocationType != declaringClass) {
+                       ReferenceBinding outerInvocationType = invocationType;
+                       ReferenceBinding temp = outerInvocationType.enclosingType();
+                       while (temp != null) {
+                               outerInvocationType = temp;
+                               temp = temp.enclosingType();
+                       }
+
+                       ReferenceBinding outerDeclaringClass = declaringClass;
+                       temp = outerDeclaringClass.enclosingType();
+                       while (temp != null) {
+                               outerDeclaringClass = temp;
+                               temp = temp.enclosingType();
+                       }
+                       if (outerInvocationType != outerDeclaringClass) return false;
+               }
+               return true;
+       }
+
+       // isDefault()
+       if (invocationType.fPackage != declaringClass.fPackage) return false;
+
+       // receiverType can be an array binding in one case... see if you can change it
+       if (receiverType instanceof ArrayBinding)
+               return false;
+       ReferenceBinding currentType = (ReferenceBinding) receiverType;
+       PackageBinding declaringPackage = declaringClass.fPackage;
+       do {
+               if (declaringClass == currentType) return true;
+               if (declaringPackage != currentType.fPackage) return false;
+       } while ((currentType = currentType.superclass()) != null);
+       return false;
+}
+public final int getAccessFlags() {
+       return modifiers & AccJustFlag;
+}
+
+/* Answer true if the receiver has default visibility
+*/
+
+public final boolean isDefault() {
+       return !isPublic() && !isProtected() && !isPrivate();
+}
+/* Answer true if the receiver is a deprecated field
+*/
+
+public final boolean isDeprecated() {
+       return (modifiers & AccDeprecated) != 0;
+}
+/* Answer true if the receiver has private visibility
+*/
+
+public final boolean isPrivate() {
+       return (modifiers & AccPrivate) != 0;
+}
+/* Answer true if the receiver has private visibility and is used locally
+*/
+
+public final boolean isPrivateUsed() {
+       return (modifiers & AccPrivateUsed) != 0;
+}
+/* Answer true if the receiver has protected visibility
+*/
+
+public final boolean isProtected() {
+       return (modifiers & AccProtected) != 0;
+}
+/* Answer true if the receiver has public visibility
+*/
+
+public final boolean isPublic() {
+       return (modifiers & AccPublic) != 0;
+}
+/* Answer true if the receiver is a static field
+*/
+
+public final boolean isStatic() {
+       return (modifiers & AccStatic) != 0;
+}
+/* Answer true if the receiver is not defined in the source of the declaringClass
+*/
+
+public final boolean isSynthetic() {
+       return (modifiers & AccSynthetic) != 0;
+}
+/* Answer true if the receiver is a transient field
+*/
+
+public final boolean isTransient() {
+       return (modifiers & AccTransient) != 0;
+}
+/* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types)
+*/
+
+public final boolean isViewedAsDeprecated() {
+       return (modifiers & AccDeprecated) != 0 ||
+               (modifiers & AccDeprecatedImplicitly) != 0;
+}
+/* Answer true if the receiver is a volatile field
+*/
+
+public final boolean isVolatile() {
+       return (modifiers & AccVolatile) != 0;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ImportBinding.java
new file mode 100644 (file)
index 0000000..6eb0985
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.ImportReference;
+
+public class ImportBinding extends Binding {
+       public char[][] compoundName;
+       public boolean onDemand;
+       public ImportReference reference;
+
+       Binding resolvedImport; // must ensure the import is resolved
+       
+public ImportBinding(char[][] compoundName, boolean isOnDemand, Binding binding, ImportReference reference) {
+       this.compoundName = compoundName;
+       this.onDemand = isOnDemand;
+       this.resolvedImport = binding;
+       this.reference = reference;
+}
+/* API
+* Answer the receiver's binding type from Binding.BindingID.
+*/
+
+public final int bindingType() {
+       return IMPORT;
+}
+public char[] readableName() {
+       if (onDemand)
+               return CharOperation.concat(CharOperation.concatWith(compoundName, '.'), ".*".toCharArray()); //$NON-NLS-1$
+       else
+               return CharOperation.concatWith(compoundName, '.');
+}
+public String toString() {
+       return "import : " + new String(readableName()); //$NON-NLS-1$
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/InnerEmulationDependency.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/InnerEmulationDependency.java
new file mode 100644 (file)
index 0000000..e722789
--- /dev/null
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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;
+
+public class InnerEmulationDependency{
+
+       public BlockScope scope;
+       public boolean wasEnclosingInstanceSupplied;
+    
+       public InnerEmulationDependency(BlockScope scope, boolean wasEnclosingInstanceSupplied) {
+               this.scope = scope;
+               this.wasEnclosingInstanceSupplied = wasEnclosingInstanceSupplied;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
new file mode 100644 (file)
index 0000000..e9703ba
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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;
+
+public interface InvocationSite {
+       boolean isSuperAccess();
+       boolean isTypeAccess();
+       void setDepth(int depth);
+       void setFieldIndex(int depth);
+       
+       // in case the receiver type does not match the actual receiver type 
+       // e.g. pkg.Type.C (receiver type of C is type of source context, 
+       //              but actual receiver type is pkg.Type)
+       // e.g2. in presence of implicit access to enclosing type
+       void setActualReceiverType(ReferenceBinding receiverType);
+       int sourceStart();
+       int sourceEnd();
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
new file mode 100644 (file)
index 0000000..cacc605
--- /dev/null
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * 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.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', '$' };
+
+       private InnerEmulationDependency[] dependents;
+       public ArrayBinding[] localArrayBindings; // used to cache array bindings of various dimensions for this local type
+       public CaseStatement switchCase; // from 1.4 on, local types should not be accessed across switch case blocks (52221)
+       
+public LocalTypeBinding(ClassScope scope, SourceTypeBinding enclosingType, CaseStatement switchCase) {
+       super(
+               new char[][] {CharOperation.concat(LocalTypePrefix, scope.referenceContext.name)},
+               scope,
+               enclosingType);
+       
+       if (this.sourceName == TypeDeclaration.ANONYMOUS_EMPTY_NAME)
+               this.tagBits |= AnonymousTypeMask;
+       else
+               this.tagBits |= LocalTypeMask;
+       this.switchCase = switchCase;
+}
+/* Record a dependency onto a source target type which may be altered
+* by the end of the innerclass emulation. Later on, we will revisit
+* all its dependents so as to update them (see updateInnerEmulationDependents()).
+*/
+
+public void addInnerEmulationDependent(BlockScope dependentScope, boolean wasEnclosingInstanceSupplied) {
+       int index;
+       if (dependents == null) {
+               index = 0;
+               dependents = new InnerEmulationDependency[1];
+       } else {
+               index = dependents.length;
+               for (int i = 0; i < index; i++)
+                       if (dependents[i].scope == dependentScope)
+                               return; // already stored
+               System.arraycopy(dependents, 0, (dependents = new InnerEmulationDependency[index + 1]), 0, index);
+       }
+       dependents[index] = new InnerEmulationDependency(dependentScope, wasEnclosingInstanceSupplied);
+       //  System.out.println("Adding dependency: "+ new String(scope.enclosingType().readableName()) + " --> " + new String(this.readableName()));
+}
+/* Answer the receiver's constant pool name.
+*
+* NOTE: This method should only be used during/after code gen.
+*/
+
+public char[] constantPoolName() /* java/lang/Object */ {
+       return constantPoolName;
+}
+
+ArrayBinding createArrayType(int dimensionCount) {
+       if (localArrayBindings == null) {
+               localArrayBindings = new ArrayBinding[] {new ArrayBinding(this, dimensionCount)};
+               return localArrayBindings[0];
+       }
+
+       // find the cached array binding for this dimensionCount (if any)
+       int length = localArrayBindings.length;
+       for (int i = 0; i < length; i++)
+               if (localArrayBindings[i].dimensions == dimensionCount)
+                       return localArrayBindings[i];
+
+       // no matching array
+       System.arraycopy(localArrayBindings, 0, localArrayBindings = new ArrayBinding[length + 1], 0, length); 
+       return localArrayBindings[length] = new ArrayBinding(this, dimensionCount);
+}
+
+public 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$
+               else
+                       return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].readableName())) + ">").toCharArray();                      //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+       } else if (isMemberType()) {
+               return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+       } else {
+               return sourceName;
+       }
+}
+
+public 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$
+               else
+                       return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].shortReadableName())) + ">").toCharArray();                         //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+       } else if (isMemberType()) {
+               return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+       } else {
+               return sourceName;
+       }
+}
+
+// Record that the type is a local member type
+public void setAsMemberType() {
+       tagBits |= MemberTypeMask;
+}
+
+public void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Object */ {
+       this.constantPoolName = computedConstantPoolName;
+}
+
+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$
+               else
+                       return ("<"+Util.bind("binding.implementation",new String(superInterfaces[0].sourceName())) + ">").toCharArray();                        //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$
+                       
+       } else
+               return sourceName;
+}
+public String toString() {
+       if (isAnonymousType())
+               return "Anonymous type : " + super.toString(); //$NON-NLS-1$
+       if (isMemberType())
+               return "Local member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
+       return "Local type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
+}
+/* Trigger the dependency mechanism forcing the innerclass emulation
+* to be propagated to all dependent source types.
+*/
+
+public void updateInnerEmulationDependents() {
+       if (dependents != null) {
+               for (int i = 0; i < dependents.length; i++) {
+                       InnerEmulationDependency dependency = dependents[i];
+                       // System.out.println("Updating " + new String(this.readableName()) + " --> " + new String(dependency.scope.enclosingType().readableName()));
+                       dependency.scope.propagateInnerEmulation(this, dependency.wasEnclosingInstanceSupplied);
+               }
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
new file mode 100644 (file)
index 0000000..0ab99f2
--- /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.lookup;
+
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+
+public class LocalVariableBinding extends VariableBinding {
+
+       public boolean isArgument;
+       public int resolvedPosition; // for code generation (position in method context)
+       
+       public static final int UNUSED = 0;
+       public static final int USED = 1;
+       public static final int FAKE_USED = 2;
+       public int useFlag; // for flow analysis (default is UNUSED)
+       
+       public BlockScope declaringScope; // back-pointer to its declaring scope
+       public LocalDeclaration declaration; // for source-positions
+
+       public int[] initializationPCs;
+       public int initializationCount = 0;
+
+       // for synthetic local variables        
+       public LocalVariableBinding(char[] name, TypeBinding type, int modifiers, boolean isArgument) {
+
+               this.name = name;
+               this.type = type;
+               this.modifiers = modifiers;
+               this.isArgument = isArgument;
+               if (isArgument)
+                       this.constant = Constant.NotAConstant;
+       }
+       
+       // regular local variable or argument
+       public LocalVariableBinding(LocalDeclaration declaration, TypeBinding type, int modifiers, boolean isArgument) {
+
+               this(declaration.name, type, modifiers, isArgument);
+               this.declaration = declaration;
+       }
+
+       /* API
+       * Answer the receiver's binding type from Binding.BindingID.
+       */
+       public final int bindingType() {
+
+               return LOCAL;
+       }
+       
+       // Answer whether the variable binding is a secret variable added for code gen purposes
+       public boolean isSecret() {
+
+               return declaration == null && !isArgument;
+       }
+
+       public void recordInitializationEndPC(int pc) {
+
+               if (initializationPCs[((initializationCount - 1) << 1) + 1] == -1)
+                       initializationPCs[((initializationCount - 1) << 1) + 1] = pc;
+       }
+
+       public void recordInitializationStartPC(int pc) {
+
+               if (initializationPCs == null)  return;
+               // optimize cases where reopening a contiguous interval
+               if ((initializationCount > 0) && (initializationPCs[ ((initializationCount - 1) << 1) + 1] == pc)) {
+                       initializationPCs[ ((initializationCount - 1) << 1) + 1] = -1; // reuse previous interval (its range will be augmented)
+               } else {
+                       int index = initializationCount << 1;
+                       if (index == initializationPCs.length) {
+                               System.arraycopy(initializationPCs, 0, (initializationPCs = new int[initializationCount << 2]), 0, index);
+                       }
+                       initializationPCs[index] = pc;
+                       initializationPCs[index + 1] = -1;
+                       initializationCount++;
+               }
+       }
+
+       public String toString() {
+
+               String s = super.toString();
+               switch (useFlag){
+                       case USED:
+                               s += "[pos: " + String.valueOf(resolvedPosition) + "]"; //$NON-NLS-2$ //$NON-NLS-1$
+                               break;
+                       case UNUSED:
+                               s += "[pos: unused]"; //$NON-NLS-1$
+                               break;
+                       case FAKE_USED:
+                               s += "[pos: fake_used]"; //$NON-NLS-1$
+                               break;
+               }
+               s += "[id:" + String.valueOf(id) + "]"; //$NON-NLS-2$ //$NON-NLS-1$
+               if (initializationCount > 0) {
+                       s += "[pc: "; //$NON-NLS-1$
+                       for (int i = 0; i < initializationCount; i++) {
+                               if (i > 0)
+                                       s += ", "; //$NON-NLS-1$
+                               s += String.valueOf(initializationPCs[i << 1]) + "-" + ((initializationPCs[(i << 1) + 1] == -1) ? "?" : String.valueOf(initializationPCs[(i<< 1) + 1])); //$NON-NLS-2$ //$NON-NLS-1$
+                       }
+                       s += "]"; //$NON-NLS-1$
+               }
+               return s;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
new file mode 100644 (file)
index 0000000..a7a9c9c
--- /dev/null
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * 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.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.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;
+
+public class LookupEnvironment implements BaseTypes, ProblemReasons, TypeConstants {
+       public CompilerOptions options;
+       public ProblemReporter problemReporter;
+       public ITypeRequestor typeRequestor;
+
+       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 INameEnvironment nameEnvironment;
+       private MethodVerifier verifier;
+       private ArrayBinding[][] uniqueArrayBindings;
+
+       private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
+       private int lastUnitIndex = -1;
+       private int lastCompletedUnitIndex = -1;
+       public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units
+
+       // 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;
+
+       // 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;
+
+public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions options, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
+       this.typeRequestor = typeRequestor;
+       this.options = options;
+       this.problemReporter = problemReporter;
+       this.defaultPackage = new PackageBinding(this); // assume the default package always exists
+       this.defaultImports = null;
+       this.nameEnvironment = nameEnvironment;
+       this.knownPackages = new HashtableOfPackage();
+       this.uniqueArrayBindings = new ArrayBinding[5][];
+       this.uniqueArrayBindings[0] = new ArrayBinding[50]; // start off the most common 1 dimension array @ 50
+}
+/* Ask the oracle 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);
+       if (answer == null)
+               return null;
+
+       if (answer.isBinaryType())
+               // the type was found as a .class file
+               typeRequestor.accept(answer.getBinaryType(), computePackageFrom(compoundName));
+       else if (answer.isCompilationUnit())
+               // the type was found as a .java file, try to build it then search the cache
+               typeRequestor.accept(answer.getCompilationUnit());
+       else if (answer.isSourceType())
+               // the type was found as a source model
+               typeRequestor.accept(answer.getSourceTypes(), computePackageFrom(compoundName));
+
+       return getCachedType(compoundName);
+}
+/* Ask the oracle for a type named name in the packageBinding.
+* Answer null if the name cannot be found.
+*/
+
+ReferenceBinding askForType(PackageBinding packageBinding, char[] name) {
+       if (packageBinding == null) {
+               if (defaultPackage == null)
+                       return null;
+               packageBinding = defaultPackage;
+       }
+       NameEnvironmentAnswer answer = nameEnvironment.findType(name, packageBinding.compoundName);
+       if (answer == null)
+               return null;
+
+       if (answer.isBinaryType())
+               // the type was found as a .class file
+               typeRequestor.accept(answer.getBinaryType(), packageBinding);
+       else if (answer.isCompilationUnit())
+               // the type was found as a .java file, try to build it then search the cache
+               typeRequestor.accept(answer.getCompilationUnit());
+       else if (answer.isSourceType())
+               // the type was found as a source model
+               typeRequestor.accept(answer.getSourceTypes(), packageBinding);
+
+       return packageBinding.getType0(name);
+}
+/* Create the initial type bindings for the compilation unit.
+*
+* See completeTypeBindings() for a description of the remaining steps
+*
+* NOTE: This method can be called multiple times as additional source files are needed
+*/
+
+public void buildTypeBindings(CompilationUnitDeclaration unit) {
+       CompilationUnitScope scope = new CompilationUnitScope(unit, this);
+       scope.buildTypeBindings();
+
+       int unitsLength = units.length;
+       if (++lastUnitIndex >= unitsLength)
+               System.arraycopy(units, 0, units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength);
+       units[lastUnitIndex] = unit;
+}
+/* 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) {
+       return cacheBinaryType(binaryType, true);
+}
+/* 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) {
+       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 null; // the type already exists & can be retrieved from the cache
+}
+/*
+* 1. Connect the type hierarchy for the type bindings created for parsedUnits.
+* 2. Create the field bindings
+* 3. Create the method bindings
+*/
+
+/* We know each known compilationUnit is free of errors at this point...
+*
+* Each step will create additional bindings unless a problem is detected, in which
+* case either the faulty import/superinterface/field/method will be skipped or a
+* suitable replacement will be substituted (such as Object for a missing superclass)
+*/
+
+public void completeTypeBindings() {
+       stepCompleted = BUILD_TYPE_HIERARCHY;
+       
+       for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
+           (this.unitBeingCompleted = this.units[i]).scope.checkAndSetImports();
+       }
+       stepCompleted = CHECK_AND_SET_IMPORTS;
+
+       for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
+           (this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy();
+       }
+       stepCompleted = CONNECT_TYPE_HIERARCHY;
+
+       for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
+               (this.unitBeingCompleted = this.units[i]).scope.buildFieldsAndMethods();
+               this.units[i] = null; // release unnecessary reference to the parsed unit
+       }
+       stepCompleted = BUILD_FIELDS_AND_METHODS;
+       this.lastCompletedUnitIndex = this.lastUnitIndex;
+       this.unitBeingCompleted = null;
+}
+/*
+* 1. Connect the type hierarchy for the type bindings created for parsedUnits.
+* 2. Create the field bindings
+* 3. Create the method bindings
+*/
+
+/*
+* Each step will create additional bindings unless a problem is detected, in which
+* case either the faulty import/superinterface/field/method will be skipped or a
+* suitable replacement will be substituted (such as Object for a missing superclass)
+*/
+
+public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) {
+       if (stepCompleted == BUILD_FIELDS_AND_METHODS) {
+               // This can only happen because the original set of units are completely built and
+               // are now being processed, so we want to treat all the additional units as a group
+               // until they too are completely processed.
+               completeTypeBindings();
+       } else {
+               if (parsedUnit.scope == null) return; // parsing errors were too severe
+               
+               if (stepCompleted >= CHECK_AND_SET_IMPORTS)
+                       (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
+
+               if (stepCompleted >= CONNECT_TYPE_HIERARCHY)
+                       (this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy();
+               
+               this.unitBeingCompleted = null;
+       }
+}
+/*
+* Used by other compiler tools which do not start by calling completeTypeBindings().
+*
+* 1. Connect the type hierarchy for the type bindings created for parsedUnits.
+* 2. Create the field bindings
+* 3. Create the method bindings
+*/
+
+public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) {
+       if (parsedUnit.scope == null) return; // parsing errors were too severe
+
+       (this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
+       parsedUnit.scope.connectTypeHierarchy();
+       if (buildFieldsAndMethods)
+               parsedUnit.scope.buildFieldsAndMethods();
+       this.unitBeingCompleted = null;
+}
+private PackageBinding computePackageFrom(char[][] constantPoolName) {
+       if (constantPoolName.length == 1)
+               return defaultPackage;
+
+       PackageBinding packageBinding = getPackage0(constantPoolName[0]);
+       if (packageBinding == null || packageBinding == TheNotFoundPackage) {
+               packageBinding = new PackageBinding(constantPoolName[0], this);
+               knownPackages.put(constantPoolName[0], packageBinding);
+       }
+
+       for (int i = 1, length = constantPoolName.length - 1; i < length; i++) {
+               PackageBinding parent = packageBinding;
+               if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) {
+                       packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this);
+                       parent.addPackage(packageBinding);
+               }
+       }
+       return packageBinding;
+}
+/* Used to guarantee array type identity.
+*/
+
+ArrayBinding createArrayType(TypeBinding type, int dimensionCount) {
+       if (type instanceof LocalTypeBinding) // cache local type arrays with the local type itself
+               return ((LocalTypeBinding) type).createArrayType(dimensionCount);
+
+       // find the array binding cache for this dimension
+       int dimIndex = dimensionCount - 1;
+       int length = uniqueArrayBindings.length;
+       ArrayBinding[] arrayBindings;
+       if (dimIndex < length) {
+               if ((arrayBindings = uniqueArrayBindings[dimIndex]) == null)
+                       uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
+       } else {
+               System.arraycopy(
+                       uniqueArrayBindings, 0, 
+                       uniqueArrayBindings = new ArrayBinding[dimensionCount][], 0, 
+                       length); 
+               uniqueArrayBindings[dimIndex] = arrayBindings = new ArrayBinding[10];
+       }
+
+       // find the cached array binding for this leaf component type (if any)
+       int index = -1;
+       length = arrayBindings.length;
+       while (++index < length) {
+               ArrayBinding currentBinding = arrayBindings[index];
+               if (currentBinding == null) // no matching array, but space left
+                       return arrayBindings[index] = new ArrayBinding(type, dimensionCount);
+               if (currentBinding.leafComponentType == type)
+                       return currentBinding;
+       }
+
+       // no matching array, no space left
+       System.arraycopy(
+               arrayBindings, 0,
+               (arrayBindings = new ArrayBinding[length * 2]), 0,
+               length); 
+       uniqueArrayBindings[dimIndex] = arrayBindings;
+       return arrayBindings[length] = new ArrayBinding(type, dimensionCount);
+}
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding) {
+       return createBinaryTypeFrom(binaryType, packageBinding, true);
+}
+public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods) {
+       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.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);
+       }
+
+       packageBinding.addType(binaryBinding);
+       binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
+       return binaryBinding;
+}
+/* Used to create packages from the package statement.
+*/
+
+PackageBinding createPackage(char[][] compoundName) {
+       PackageBinding packageBinding = getPackage0(compoundName[0]);
+       if (packageBinding == null || packageBinding == TheNotFoundPackage) {
+               packageBinding = new PackageBinding(compoundName[0], this);
+               knownPackages.put(compoundName[0], packageBinding);
+       }
+
+       for (int i = 1, length = compoundName.length; i < length; i++) {
+               // check to see if it collides with a known type...
+               // this case can only happen if the package does not exist as a directory in the file system
+               // otherwise when the source type was defined, the correct error would have been reported
+               // unless its an unresolved type which is referenced from an inconsistent class file
+               ReferenceBinding type = packageBinding.getType0(compoundName[i]);
+               if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding))
+                       return null;
+
+               PackageBinding parent = packageBinding;
+               if ((packageBinding = parent.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) {
+                       // if the package is unknown, check to see if a type exists which would collide with the new package
+                       // catches the case of a package statement of: package java.lang.Object;
+                       // since the package can be added after a set of source files have already been compiled, we need
+                       // whenever a package statement is encountered
+                       if (nameEnvironment.findType(compoundName[i], parent.compoundName) != null)
+                               return null;
+
+                       packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this);
+                       parent.addPackage(packageBinding);
+               }
+       }
+       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 ReferenceBinding getCachedType(char[][] compoundName) {
+       if (compoundName.length == 1) {
+               if (defaultPackage == null)
+                       return null;
+               return defaultPackage.getType0(compoundName[0]);
+       }
+
+       PackageBinding packageBinding = getPackage0(compoundName[0]);
+       if (packageBinding == null || packageBinding == TheNotFoundPackage)
+               return null;
+
+       for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
+               if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage)
+                       return null;
+       return packageBinding.getType0(compoundName[compoundName.length - 1]);
+}
+/* Answer the top level package named name if it exists in the cache.
+* Answer theNotFoundPackage if it could not be resolved the first time
+* it was looked up, otherwise answer null.
+*
+* NOTE: Senders must convert theNotFoundPackage into a real problem
+* package if its to returned.
+*/
+
+PackageBinding getPackage0(char[] name) {
+       return knownPackages.get(name);
+}
+/* Answer the top level package named name.
+* Ask the oracle for the package if its not in the cache.
+* Answer null if the package cannot be found.
+*/
+
+PackageBinding getTopLevelPackage(char[] name) {
+       PackageBinding packageBinding = getPackage0(name);
+       if (packageBinding != null) {
+               if (packageBinding == TheNotFoundPackage)
+                       return null;
+               return packageBinding;
+       }
+
+       if (nameEnvironment.isPackage(null, name)) {
+               knownPackages.put(name, packageBinding = new PackageBinding(name, this));
+               return packageBinding;
+       }
+
+       knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time
+       return null;
+}
+/* Answer the type corresponding to the compoundName.
+* Ask the oracle for the type if its not in the cache.
+* Answer null if the type cannot be found... likely a fatal error.
+*/
+
+public ReferenceBinding getType(char[][] compoundName) {
+       ReferenceBinding referenceBinding;
+
+       if (compoundName.length == 1) {
+               if (defaultPackage == null)
+                       return null;
+
+               if ((referenceBinding = defaultPackage.getType0(compoundName[0])) == null) {
+                       PackageBinding packageBinding = getPackage0(compoundName[0]);
+                       if (packageBinding != null && packageBinding != TheNotFoundPackage)
+                               return null; // collides with a known package... should not call this method in such a case
+                       referenceBinding = askForType(defaultPackage, compoundName[0]);
+               }
+       } else {
+               PackageBinding packageBinding = getPackage0(compoundName[0]);
+               if (packageBinding == TheNotFoundPackage)
+                       return null;
+
+               if (packageBinding != null) {
+                       for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) {
+                               if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null)
+                                       break;
+                               if (packageBinding == TheNotFoundPackage)
+                                       return null;
+                       }
+               }
+
+               if (packageBinding == null)
+                       referenceBinding = askForType(compoundName);
+               else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null)
+                       referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1]);
+       }
+
+       if (referenceBinding == null || referenceBinding == TheNotFoundType)
+               return null;
+       if (referenceBinding instanceof UnresolvedReferenceBinding)
+               referenceBinding = ((UnresolvedReferenceBinding) referenceBinding).resolve(this);
+
+       // compoundName refers to a nested type incorrectly (for example, package1.A$B)
+       if (referenceBinding.isNestedType())
+               return new ProblemReferenceBinding(compoundName, InternalNameProvided);
+       return referenceBinding;
+}
+/* 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.
+*
+* NOTE: Does NOT answer base types nor array types!
+*
+* NOTE: Aborts compilation if the class file cannot be found.
+*/
+
+ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end) {
+       if (end == -1)
+               end = signature.length;
+
+       char[][] compoundName = CharOperation.splitOn('/', signature, start, end);
+       ReferenceBinding binding = getCachedType(compoundName);
+       if (binding == null) {
+               PackageBinding packageBinding = computePackageFrom(compoundName);
+               binding = new UnresolvedReferenceBinding(compoundName, packageBinding);
+               packageBinding.addType(binding);
+       } else if (binding == TheNotFoundType) {
+               problemReporter.isClassPathCorrect(compoundName, null);
+               return null; // will not get here since the above error aborts the compilation
+       }
+       return binding;
+}
+/* Answer the type corresponding to the signature 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.
+*
+* NOTE: Does answer base types & array types.
+*
+* NOTE: Aborts compilation if the class file cannot be found.
+*/
+
+TypeBinding getTypeFromSignature(char[] signature, int start, int end) {
+       int dimension = 0;
+       while (signature[start] == '[') {
+               start++;
+               dimension++;
+       }
+       if (end == -1)
+               end = signature.length - 1;
+
+       // Just switch on signature[start] - the L case is the else
+       TypeBinding binding = null;
+       if (start == end) {
+               switch (signature[start]) {
+                       case 'I' :
+                               binding = IntBinding;
+                               break;
+                       case 'Z' :
+                               binding = BooleanBinding;
+                               break;
+                       case 'V' :
+                               binding = VoidBinding;
+                               break;
+                       case 'C' :
+                               binding = CharBinding;
+                               break;
+                       case 'D' :
+                               binding = DoubleBinding;
+                               break;
+                       case 'B' :
+                               binding = ByteBinding;
+                               break;
+                       case 'F' :
+                               binding = FloatBinding;
+                               break;
+                       case 'J' :
+                               binding = LongBinding;
+                               break;
+                       case 'S' :
+                               binding = ShortBinding;
+                               break;
+                       default :
+                               throw new Error(Util.bind("error.undefinedBaseType",String.valueOf(signature[start]))); //$NON-NLS-1$
+               }
+       } else {
+               binding = getTypeFromConstantPoolName(signature, start + 1, end);
+       }
+
+       if (dimension == 0)
+               return binding;
+       return createArrayType(binding, dimension);
+}
+/* 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);
+       return nameEnvironment.isPackage(compoundName, name);
+}
+// The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
+
+public MethodVerifier methodVerifier() {
+       if (verifier == null)
+               verifier = new MethodVerifier(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.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.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;
+                               }
+                       }
+               }
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
new file mode 100644 (file)
index 0000000..dc24ea2
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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 final class MemberTypeBinding extends NestedTypeBinding {
+public MemberTypeBinding(char[][] compoundName, ClassScope scope, SourceTypeBinding enclosingType) {
+       super(compoundName, scope, enclosingType);
+       this.tagBits |= MemberTypeMask;
+}
+void checkSyntheticArgsAndFields() {
+       if (this.isStatic()) return;
+       if (this.isInterface()) return;
+       this.addSyntheticArgumentAndField(this.enclosingType);
+}
+/* Answer the receiver's constant pool name.
+*
+* NOTE: This method should only be used during/after code gen.
+*/
+
+public char[] constantPoolName() /* java/lang/Object */ {
+       if (constantPoolName != null)
+               return constantPoolName;
+
+       return constantPoolName = CharOperation.concat(enclosingType().constantPoolName(), sourceName, '$');
+}
+public String toString() {
+       return "Member type : " + new String(sourceName()) + " " + super.toString(); //$NON-NLS-2$ //$NON-NLS-1$
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
new file mode 100644 (file)
index 0000000..0441fb3
--- /dev/null
@@ -0,0 +1,538 @@
+/*******************************************************************************
+ * 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.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+
+public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
+       public int modifiers;
+       public char[] selector;
+       public TypeBinding returnType;
+       public TypeBinding[] parameters;
+       public ReferenceBinding[] thrownExceptions;
+       public ReferenceBinding declaringClass;
+
+       char[] signature;
+
+protected MethodBinding() {
+       // for creating problem or synthetic method
+}
+public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
+       this.modifiers = modifiers;
+       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.declaringClass = declaringClass;
+
+       // propagate the strictfp & deprecated modifiers
+       if (this.declaringClass != null) {
+               if (this.declaringClass.isStrictfp())
+                       if (!(isNative() || isAbstract()))
+                               this.modifiers |= AccStrictfp;
+               if (this.declaringClass.isViewedAsDeprecated() && !isDeprecated())
+                       this.modifiers |= AccDeprecatedImplicitly;
+       }
+}
+public MethodBinding(int modifiers, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
+       this(modifiers, ConstructorDeclaration.ConstantPoolName, VoidBinding, args, exceptions, declaringClass);
+}
+// special API used to change method declaring class for runtime visibility check
+public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
+       this.modifiers = initialMethodBinding.modifiers;
+       this.selector = initialMethodBinding.selector;
+       this.returnType = initialMethodBinding.returnType;
+       this.parameters = initialMethodBinding.parameters;
+       this.thrownExceptions = initialMethodBinding.thrownExceptions;
+       this.declaringClass = declaringClass;
+}
+/* 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)
+               return true;
+
+       int length = parameters.length;
+       if (length != args.length)
+               return false;
+       
+       for (int i = 0; i < length; i++)
+               if (parameters[i] != args[i])
+                       return false;
+       return true;
+}
+/* API
+* Answer the receiver's binding type from Binding.BindingID.
+*/
+
+public final int bindingType() {
+       return METHOD;
+}
+/* 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.
+*
+* NOTE: This method should ONLY be sent if the receiver is a constructor.
+*
+* NOTE: Cannot invoke this method with a compilation unit scope.
+*/
+
+public final boolean canBeSeenBy(InvocationSite invocationSite, Scope scope) {
+       if (isPublic()) return true;
+
+       SourceTypeBinding invocationType = scope.enclosingSourceType();
+       if (invocationType == declaringClass) return true;
+
+       if (isProtected()) {
+               // answer true if the receiver is in the same package as the invocationType
+               if (invocationType.fPackage == declaringClass.fPackage) return true;
+               return invocationSite.isSuperAccess();
+       }
+
+       if (isPrivate()) {
+               // answer true if the invocationType and the declaringClass have a common enclosingType
+               // already know they are not the identical type
+               ReferenceBinding outerInvocationType = invocationType;
+               ReferenceBinding temp = outerInvocationType.enclosingType();
+               while (temp != null) {
+                       outerInvocationType = temp;
+                       temp = temp.enclosingType();
+               }
+
+               ReferenceBinding outerDeclaringClass = declaringClass;
+               temp = outerDeclaringClass.enclosingType();
+               while (temp != null) {
+                       outerDeclaringClass = temp;
+                       temp = temp.enclosingType();
+               }
+               return outerInvocationType == outerDeclaringClass;
+       }
+
+       // isDefault()
+       return invocationType.fPackage == declaringClass.fPackage;
+}
+/* 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.
+*
+* NOTE: Cannot invoke this method with a compilation unit scope.
+*/
+public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invocationSite, Scope scope) {
+       if (isPublic()) return true;
+
+       SourceTypeBinding invocationType = scope.enclosingSourceType();
+       if (invocationType == declaringClass && invocationType == receiverType) return true;
+
+       if (isProtected()) {
+               // answer true if the invocationType is the declaringClass or they are in the same package
+               // OR the invocationType is a subclass of the declaringClass
+               //    AND the receiverType is the invocationType or its subclass
+               //    OR the method is a static method accessed directly through a type
+               //    OR previous assertions are true for one of the enclosing type
+               if (invocationType == declaringClass) return true;
+               if (invocationType.fPackage == declaringClass.fPackage) return true;
+               
+               ReferenceBinding currentType = invocationType;
+               int depth = 0;
+               do {
+                       if (declaringClass.isSuperclassOf(currentType)) {
+                               if (invocationSite.isSuperAccess()){
+                                       return true;
+                               }
+                               // receiverType can be an array binding in one case... see if you can change it
+                               if (receiverType instanceof ArrayBinding){
+                                       return false;
+                               }
+                               if (isStatic()){
+                                       if (depth > 0) invocationSite.setDepth(depth);
+                                       return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
+                               }
+                               if (currentType == receiverType || currentType.isSuperclassOf((ReferenceBinding) receiverType)){
+                                       if (depth > 0) invocationSite.setDepth(depth);
+                                       return true;
+                               }
+                       }
+                       depth++;
+                       currentType = currentType.enclosingType();
+               } while (currentType != null);
+               return false;
+       }
+
+       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;
+
+               if (invocationType != declaringClass) {
+                       ReferenceBinding outerInvocationType = invocationType;
+                       ReferenceBinding temp = outerInvocationType.enclosingType();
+                       while (temp != null) {
+                               outerInvocationType = temp;
+                               temp = temp.enclosingType();
+                       }
+
+                       ReferenceBinding outerDeclaringClass = declaringClass;
+                       temp = outerDeclaringClass.enclosingType();
+                       while (temp != null) {
+                               outerDeclaringClass = temp;
+                               temp = temp.enclosingType();
+                       }
+                       if (outerInvocationType != outerDeclaringClass) return false;
+               }
+               return true;
+       }
+
+       // isDefault()
+       if (invocationType.fPackage != declaringClass.fPackage) return false;
+
+       // receiverType can be an array binding in one case... see if you can change it
+       if (receiverType instanceof ArrayBinding)
+               return false;
+       ReferenceBinding type = (ReferenceBinding) receiverType;
+       PackageBinding declaringPackage = declaringClass.fPackage;
+       do {
+               if (declaringClass == type) return true;
+               if (declaringPackage != type.fPackage) return false;
+       } while ((type = type.superclass()) != null);
+       return false;
+}
+/* 
+ * Answer the declaring class to use in the constant pool
+ * may not be a reference binding (see subtypes)
+ */
+public TypeBinding constantPoolDeclaringClass() {
+       return this.declaringClass;
+}
+/* Answer the receiver's constant pool name.
+*
+* <init> for constructors
+* <clinit> for clinit methods
+* or the source name of the method
+*/
+public final char[] constantPoolName() {
+       return selector;
+}
+public final int getAccessFlags() {
+       return modifiers & AccJustFlag;
+}
+
+/* Answer true if the receiver is an abstract method
+*/
+public final boolean isAbstract() {
+       return (modifiers & AccAbstract) != 0;
+}
+
+/* Answer true if the receiver is a bridge method
+*/
+public final boolean isBridge() {
+       return (modifiers & AccBridge) != 0;
+}
+
+/* Answer true if the receiver is a constructor
+*/
+public final boolean isConstructor() {
+       return selector == ConstructorDeclaration.ConstantPoolName;
+}
+protected boolean isConstructorRelated() {
+       return isConstructor();
+}
+
+/* Answer true if the receiver has default visibility
+*/
+public final boolean isDefault() {
+       return !isPublic() && !isProtected() && !isPrivate();
+}
+
+/* Answer true if the receiver is a system generated default abstract method
+*/
+public final boolean isDefaultAbstract() {
+       return (modifiers & AccDefaultAbstract) != 0;
+}
+
+/* Answer true if the receiver is a deprecated method
+*/
+public final boolean isDeprecated() {
+       return (modifiers & AccDeprecated) != 0;
+}
+
+/* Answer true if the receiver is final and cannot be overridden
+*/
+public final boolean isFinal() {
+       return (modifiers & AccFinal) != 0;
+}
+
+/* Answer true if the receiver is implementing another method
+ * in other words, it is overriding and concrete, and overriden method is abstract
+ * Only set for source methods
+*/
+public final boolean isImplementing() {
+       return (modifiers & AccImplementing) != 0;
+}
+
+/* Answer true if the receiver is a native method
+*/
+public final boolean isNative() {
+       return (modifiers & AccNative) != 0;
+}
+
+/* Answer true if the receiver is overriding another method
+ * Only set for source methods
+*/
+public final boolean isOverriding() {
+       return (modifiers & AccOverriding) != 0;
+}
+/*
+ * Answer true if the receiver is a "public static void main(String[])" method
+ */
+public final boolean isMain() {
+       if (this.selector.length == 4 && CharOperation.equals(this.selector, MAIN)
+                       && ((this.modifiers & (AccPublic | AccStatic)) != 0)
+                       && VoidBinding == this.returnType  
+                       && this.parameters.length == 1) {
+               TypeBinding paramType = this.parameters[0];
+               if (paramType.dimensions() == 1 && paramType.leafComponentType().id == TypeIds.T_JavaLangString) {
+                       return true;
+               }
+       }
+       return false;
+}
+/* Answer true if the receiver has private visibility
+*/
+public final boolean isPrivate() {
+       return (modifiers & AccPrivate) != 0;
+}
+
+/* Answer true if the receiver has private visibility and is used locally
+*/
+public final boolean isPrivateUsed() {
+       return (modifiers & AccPrivateUsed) != 0;
+}
+
+/* Answer true if the receiver has protected visibility
+*/
+public final boolean isProtected() {
+       return (modifiers & AccProtected) != 0;
+}
+
+/* Answer true if the receiver has public visibility
+*/
+public final boolean isPublic() {
+       return (modifiers & AccPublic) != 0;
+}
+
+/* Answer true if the receiver got requested to clear the private modifier
+ * during private access emulation.
+ */
+public final boolean isRequiredToClearPrivateModifier() {
+       return (modifiers & AccClearPrivateModifier) != 0;
+}
+
+/* Answer true if the receiver is a static method
+*/
+public final boolean isStatic() {
+       return (modifiers & AccStatic) != 0;
+}
+
+/* Answer true if all float operations must adher to IEEE 754 float/double rules
+*/
+public final boolean isStrictfp() {
+       return (modifiers & AccStrictfp) != 0;
+}
+
+/* Answer true if the receiver is a synchronized method
+*/
+public final boolean isSynchronized() {
+       return (modifiers & AccSynchronized) != 0;
+}
+
+/* Answer true if the receiver has public visibility
+*/
+public final boolean isSynthetic() {
+       return (modifiers & AccSynthetic) != 0;
+}
+
+/* Answer true if the receiver is a vararg method
+*/
+public final boolean isVararg() {
+       return (modifiers & AccVarargs) != 0;
+}
+
+/* Answer true if the receiver's declaring type is deprecated (or any of its enclosing types)
+*/
+public final boolean isViewedAsDeprecated() {
+       return (modifiers & AccDeprecated) != 0 ||
+               (modifiers & AccDeprecatedImplicitly) != 0;
+}
+
+public char[] readableName() /* foo(int, Thread) */ {
+       StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
+       if (isConstructor())
+               buffer.append(declaringClass.sourceName());
+       else
+               buffer.append(selector);
+       buffer.append('(');
+       if (parameters != NoParameters) {
+               for (int i = 0, length = parameters.length; i < length; i++) {
+                       if (i > 0)
+                               buffer.append(", "); //$NON-NLS-1$
+                       buffer.append(parameters[i].sourceName());
+               }
+       }
+       buffer.append(')');
+       return buffer.toString().toCharArray();
+}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.Binding#shortReadableName()
+ */
+public char[] shortReadableName() {
+       StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
+       if (isConstructor())
+               buffer.append(declaringClass.shortReadableName());
+       else
+               buffer.append(selector);
+       buffer.append('(');
+       if (parameters != NoParameters) {
+               for (int i = 0, length = parameters.length; i < length; i++) {
+                       if (i > 0)
+                               buffer.append(", "); //$NON-NLS-1$
+                       buffer.append(parameters[i].shortReadableName());
+               }
+       }
+       buffer.append(')');
+       return buffer.toString().toCharArray();
+}
+
+protected final void setSelector(char[] selector) {
+       this.selector = selector;
+       this.signature = null;
+}
+
+/* Answer the receiver's signature.
+*
+* NOTE: This method should only be used during/after code gen.
+* The signature is cached so if the signature of the return type or any parameter
+* type changes, the cached state is invalid.
+*/
+public final char[] signature() /* (ILjava/lang/Thread;)Ljava/lang/Object; */ {
+       if (signature != null)
+               return signature;
+
+       StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20);
+       buffer.append('(');
+       
+       TypeBinding[] targetParameters = this.parameters;
+       boolean considerSynthetics = isConstructorRelated() && declaringClass.isNestedType();
+       if (considerSynthetics) {
+               
+               // take into account the synthetic argument type signatures as well
+               ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes();
+               int count = syntheticArgumentTypes == null ? 0 : syntheticArgumentTypes.length;
+               for (int i = 0; i < count; i++) {
+                       buffer.append(syntheticArgumentTypes[i].signature());
+               }
+               
+               if (this instanceof SyntheticAccessMethodBinding) {
+                       targetParameters = ((SyntheticAccessMethodBinding)this).targetMethod.parameters;
+               }
+       }
+
+       if (targetParameters != NoParameters) {
+               for (int i = 0; i < targetParameters.length; i++) {
+                       buffer.append(targetParameters[i].signature());
+               }
+       }
+       if (considerSynthetics) {
+               SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass.syntheticOuterLocalVariables();
+               int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length;
+               for (int i = 0; i < count; i++) {
+                       buffer.append(syntheticOuterArguments[i].type.signature());
+               }
+               // move the extra padding arguments of the synthetic constructor invocation to the end          
+               for (int i = targetParameters.length, extraLength = parameters.length; i < extraLength; i++) {
+                       buffer.append(parameters[i].signature());
+               }
+       }
+       buffer.append(')');
+       buffer.append(returnType.signature());
+       return signature = buffer.toString().toCharArray();
+}
+public final int sourceEnd() {
+       AbstractMethodDeclaration method = sourceMethod();
+       if (method == null)
+               return 0;
+       return method.sourceEnd;
+}
+AbstractMethodDeclaration sourceMethod() {
+       SourceTypeBinding sourceType;
+       try {
+               sourceType = (SourceTypeBinding) declaringClass;
+       } catch (ClassCastException e) {
+               return null;            
+       }
+
+       AbstractMethodDeclaration[] methods = sourceType.scope.referenceContext.methods;
+       for (int i = methods.length; --i >= 0;)
+               if (this == methods[i].binding)
+                       return methods[i];
+       return null;            
+}
+public final int sourceStart() {
+       AbstractMethodDeclaration method = sourceMethod();
+       if (method == null)
+               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.
+ */
+
+public final void tagForClearingPrivateModifier() {
+       modifiers |= AccClearPrivateModifier;
+}
+public String toString() {
+       String s = (returnType != null) ? returnType.debugName() : "NULL TYPE"; //$NON-NLS-1$
+       s += " "; //$NON-NLS-1$
+       s += (selector != null) ? new String(selector) : "UNNAMED METHOD"; //$NON-NLS-1$
+
+       s += "("; //$NON-NLS-1$
+       if (parameters != null) {
+               if (parameters != NoParameters) {
+                       for (int i = 0, length = parameters.length; i < length; i++) {
+                               if (i  > 0)
+                                       s += ", "; //$NON-NLS-1$
+                               s += (parameters[i] != null) ? parameters[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
+                       }
+               }
+       } else {
+               s += "NULL PARAMETERS"; //$NON-NLS-1$
+       }
+       s += ") "; //$NON-NLS-1$
+
+       if (thrownExceptions != null) {
+               if (thrownExceptions != NoExceptions) {
+                       s += "throws "; //$NON-NLS-1$
+                       for (int i = 0, length = thrownExceptions.length; i < length; i++) {
+                               if (i  > 0)
+                                       s += ", "; //$NON-NLS-1$
+                               s += (thrownExceptions[i] != null) ? thrownExceptions[i].debugName() : "NULL TYPE"; //$NON-NLS-1$
+                       }
+               }
+       } else {
+               s += "NULL THROWN EXCEPTIONS"; //$NON-NLS-1$
+       }
+       return s;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
new file mode 100644 (file)
index 0000000..92b806b
--- /dev/null
@@ -0,0 +1,492 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+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.codegen.CodeStream;
+import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
+import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+/**
+ * Particular block scope used for methods, constructors or clinits, representing
+ * its outermost blockscope. Note also that such a scope will be provided to enclose
+ * field initializers subscopes as well.
+ */
+public class MethodScope extends BlockScope {
+
+       public ReferenceContext referenceContext;
+       public boolean isStatic; // method modifier or initializer one
+
+       //fields used during name resolution
+       public boolean isConstructorCall = false; 
+       public FieldBinding initializedField; // the field being initialized
+       public int lastVisibleFieldID = -1; // the ID of the last field which got declared 
+       // note that #initializedField can be null AND lastVisibleFieldID >= 0, when processing instance field initializers.
+
+       // flow analysis
+       public int analysisIndex; // for setting flow-analysis id
+       public boolean isPropagatingInnerClassEmulation;
+
+       // for local variables table attributes
+       public int lastIndex = 0;
+       public long[] definiteInits = new long[4];
+       public long[][] extraDefiniteInits = new long[4][];
+
+       // inner-emulation
+       public SyntheticArgumentBinding[] extraSyntheticArguments;
+       
+       public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
+
+               super(METHOD_SCOPE, parent);
+               locals = new LocalVariableBinding[5];
+               this.referenceContext = context;
+               this.isStatic = isStatic;
+               this.startIndex = 0;
+       }
+
+       /* Spec : 8.4.3 & 9.4
+        */
+       private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) {
+               
+               int modifiers = methodBinding.modifiers;
+               if ((modifiers & AccAlternateModifierProblem) != 0)
+                       problemReporter().duplicateModifierForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+               if (((ConstructorDeclaration) referenceContext).isDefaultConstructor) {
+                       if (methodBinding.declaringClass.isPublic())
+                               modifiers |= AccPublic;
+                       else if (methodBinding.declaringClass.isProtected())
+                               modifiers |= AccProtected;
+               }
+
+               // after this point, tests on the 16 bits reserved.
+               int realModifiers = modifiers & AccJustFlag;
+
+               // check for abnormal modifiers
+               int unexpectedModifiers =
+                       ~(AccPublic | AccPrivate | AccProtected | AccStrictfp);
+               if ((realModifiers & unexpectedModifiers) != 0)
+                       problemReporter().illegalModifierForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+               else if (
+                       (((AbstractMethodDeclaration) referenceContext).modifiers & AccStrictfp) != 0)
+                       // must check the parse node explicitly
+                       problemReporter().illegalModifierForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+               // check for incompatible modifiers in the visibility bits, isolate the visibility bits
+               int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
+               if ((accessorBits & (accessorBits - 1)) != 0) {
+                       problemReporter().illegalVisibilityModifierCombinationForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+                       // need to keep the less restrictive
+                       if ((accessorBits & AccPublic) != 0) {
+                               if ((accessorBits & AccProtected) != 0)
+                                       modifiers ^= AccProtected;
+                               if ((accessorBits & AccPrivate) != 0)
+                                       modifiers ^= AccPrivate;
+                       }
+                       if ((accessorBits & AccProtected) != 0)
+                               if ((accessorBits & AccPrivate) != 0)
+                                       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;
+
+               methodBinding.modifiers = modifiers;
+       }
+       
+       /* Spec : 8.4.3 & 9.4
+        */
+       private void checkAndSetModifiersForMethod(MethodBinding methodBinding) {
+               
+               int modifiers = methodBinding.modifiers;
+               if ((modifiers & AccAlternateModifierProblem) != 0)
+                       problemReporter().duplicateModifierForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+               // 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);
+                       return;
+               }
+
+               // check for abnormal modifiers
+               int unexpectedModifiers =
+                       ~(
+                               AccPublic
+                                       | AccPrivate
+                                       | AccProtected
+                                       | AccAbstract
+                                       | AccStatic
+                                       | AccFinal
+                                       | AccSynchronized
+                                       | AccNative
+                                       | AccStrictfp);
+               if ((realModifiers & unexpectedModifiers) != 0)
+                       problemReporter().illegalModifierForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+               // check for incompatible modifiers in the visibility bits, isolate the visibility bits
+               int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
+               if ((accessorBits & (accessorBits - 1)) != 0) {
+                       problemReporter().illegalVisibilityModifierCombinationForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+                       // need to keep the less restrictive
+                       if ((accessorBits & AccPublic) != 0) {
+                               if ((accessorBits & AccProtected) != 0)
+                                       modifiers ^= AccProtected;
+                               if ((accessorBits & AccPrivate) != 0)
+                                       modifiers ^= AccPrivate;
+                       }
+                       if ((accessorBits & AccProtected) != 0)
+                               if ((accessorBits & AccPrivate) != 0)
+                                       modifiers ^= AccPrivate;
+               }
+
+               // check for modifiers incompatible with abstract modifier
+               if ((modifiers & AccAbstract) != 0) {
+                       int incompatibleWithAbstract =
+                               AccPrivate | AccStatic | AccFinal | AccSynchronized | AccNative | AccStrictfp;
+                       if ((modifiers & incompatibleWithAbstract) != 0)
+                               problemReporter().illegalAbstractModifierCombinationForMethod(
+                                       methodBinding.declaringClass,
+                                       (AbstractMethodDeclaration) referenceContext);
+                       if (!methodBinding.declaringClass.isAbstract())
+                               problemReporter().abstractMethodInAbstractClass(
+                                       (SourceTypeBinding) methodBinding.declaringClass,
+                                       (AbstractMethodDeclaration) referenceContext);
+               }
+
+               /* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final)
+               // methods from a final class are final : 8.4.3.3 
+               if (methodBinding.declaringClass.isFinal())
+                       modifiers |= AccFinal;
+               */
+               // native methods cannot also be tagged as strictfp
+               if ((modifiers & AccNative) != 0 && (modifiers & AccStrictfp) != 0)
+                       problemReporter().nativeMethodsCannotBeStrictfp(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+               // static members are only authorized in a static member or top level type
+               if (((realModifiers & AccStatic) != 0)
+                       && methodBinding.declaringClass.isNestedType()
+                       && !methodBinding.declaringClass.isStatic())
+                       problemReporter().unexpectedStaticModifierForMethod(
+                               methodBinding.declaringClass,
+                               (AbstractMethodDeclaration) referenceContext);
+
+               methodBinding.modifiers = modifiers;
+       }
+       
+       /* Compute variable positions in scopes given an initial position offset
+        * ignoring unused local variables.
+        * 
+        * Deal with arguments here, locals and subscopes are processed in BlockScope method
+        */
+       public void computeLocalVariablePositions(int initOffset, CodeStream codeStream) {
+
+               boolean isReportingUnusedArgument = false;
+
+               if (referenceContext instanceof AbstractMethodDeclaration) {
+                       AbstractMethodDeclaration methodDecl = (AbstractMethodDeclaration)referenceContext;
+                       MethodBinding method = methodDecl.binding;
+                       CompilerOptions options = compilationUnitScope().environment.options;
+                       if (!(method.isAbstract()
+                                       || (method.isImplementing() && !options.reportUnusedParameterWhenImplementingAbstract) 
+                                       || (method.isOverriding() && !method.isImplementing() && !options.reportUnusedParameterWhenOverridingConcrete)
+                                       || method.isMain())) {
+                               isReportingUnusedArgument = true;
+                       }
+               }
+               this.offset = initOffset;
+               this.maxOffset = initOffset;
+
+               // manage arguments     
+               int ilocal = 0, maxLocals = this.localIndex;    
+               while (ilocal < maxLocals) {
+                       LocalVariableBinding local = locals[ilocal];
+                       if (local == null || !local.isArgument) break; // done with arguments
+
+                       // do not report fake used variable
+                       if (isReportingUnusedArgument
+                                       && local.useFlag == LocalVariableBinding.UNUSED
+                                       && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
+                               this.problemReporter().unusedArgument(local.declaration);
+                       }
+
+                       // record user-defined argument for attribute generation
+                       codeStream.record(local); 
+
+                       // assign variable position
+                       local.resolvedPosition = this.offset;
+
+                       if ((local.type == LongBinding) || (local.type == DoubleBinding)) {
+                               this.offset += 2;
+                       } else {
+                               this.offset++;
+                       }
+                       // check for too many arguments/local variables
+                       if (this.offset > 0xFF) { // no more than 255 words of arguments
+                               this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration);
+                       }
+                       ilocal++;
+               }
+               
+               // sneak in extra argument before other local variables
+               if (extraSyntheticArguments != null) {
+                       for (int iarg = 0, maxArguments = extraSyntheticArguments.length; iarg < maxArguments; iarg++){
+                               SyntheticArgumentBinding argument = extraSyntheticArguments[iarg];
+                               argument.resolvedPosition = this.offset;
+                               if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
+                                       this.offset += 2;
+                               } else {
+                                       this.offset++;
+                               }
+                               if (this.offset > 0xFF) { // no more than 255 words of arguments
+                                       this.problemReporter().noMoreAvailableSpaceForArgument(argument, (ASTNode)this.referenceContext); 
+                               }
+                       }
+               }
+               this.computeLocalVariablePositions(ilocal, this.offset, codeStream);
+       }
+
+       /* Error management:
+        *              keep null for all the errors that prevent the method to be created
+        *              otherwise return a correct method binding (but without the element
+        *              that caused the problem) : ie : Incorrect thrown exception
+        */
+       MethodBinding createMethod(AbstractMethodDeclaration method) {
+
+               // is necessary to ensure error reporting
+               this.referenceContext = method;
+               method.scope = this;
+               SourceTypeBinding declaringClass = referenceType().binding;
+               int modifiers = method.modifiers | AccUnresolved;
+               if (method.isConstructor()) {
+                       if (method.isDefaultConstructor()) {
+                               modifiers |= AccIsDefaultConstructor;
+                       }
+                       method.binding = new MethodBinding(modifiers, null, null, declaringClass);
+                       checkAndSetModifiersForConstructor(method.binding);
+               } else {
+                       if (declaringClass.isInterface())
+                               modifiers |= AccPublic | AccAbstract;
+                       method.binding =
+                               new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
+                       checkAndSetModifiersForMethod(method.binding);
+               }
+               this.isStatic = method.binding.isStatic();
+               return method.binding;
+       }
+
+       /* Overridden to detect the error case inside an explicit constructor call:
+       
+       class X {
+               int i;
+               X myX;
+               X(X x) {
+                       this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors
+               }
+       }
+       */
+       public FieldBinding findField(
+               TypeBinding receiverType,
+               char[] fieldName,
+               InvocationSite invocationSite,
+               boolean needResolve) {
+
+               FieldBinding field = super.findField(receiverType, fieldName, invocationSite, needResolve);
+               if (field == null)
+                       return null;
+               if (!field.isValidBinding())
+                       return field; // answer the error field
+               if (field.isStatic())
+                       return field; // static fields are always accessible
+
+               if (!isConstructorCall || receiverType != enclosingSourceType())
+                       return field;
+
+               if (invocationSite instanceof SingleNameReference)
+                       return new ProblemFieldBinding(
+                               field, // closest match
+                               field.declaringClass,
+                               fieldName,
+                               NonStaticReferenceInConstructorInvocation);
+               if (invocationSite instanceof QualifiedNameReference) {
+                       // look to see if the field is the first binding
+                       QualifiedNameReference name = (QualifiedNameReference) invocationSite;
+                       if (name.binding == null)
+                               // only true when the field is the fieldbinding at the beginning of name's tokens
+                               return new ProblemFieldBinding(
+                                       field, // closest match
+                                       field.declaringClass,
+                                       fieldName,
+                                       NonStaticReferenceInConstructorInvocation);
+               }
+               return field;
+       }
+
+       public boolean isInsideConstructor() {
+
+               return (referenceContext instanceof ConstructorDeclaration);
+       }
+       
+       public boolean isInsideInitializer() {
+
+               return (referenceContext instanceof TypeDeclaration);
+       }
+
+       public boolean isInsideInitializerOrConstructor() {
+
+               return (referenceContext instanceof TypeDeclaration)
+                       || (referenceContext instanceof ConstructorDeclaration);
+       }
+
+       /* Answer the problem reporter to use for raising new problems.
+        *
+        * Note that as a side-effect, this updates the current reference context
+        * (unit, type or method) in case the problem handler decides it is necessary
+        * to abort.
+        */
+       public ProblemReporter problemReporter() {
+
+               MethodScope outerMethodScope;
+               if ((outerMethodScope = outerMostMethodScope()) == this) {
+                       ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
+                       problemReporter.referenceContext = referenceContext;
+                       return problemReporter;
+               }
+               return outerMethodScope.problemReporter();
+       }
+
+       public final int recordInitializationStates(FlowInfo flowInfo) {
+
+               if (!flowInfo.isReachable()) return -1;
+
+               UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInits();
+               long[] extraInits = unconditionalFlowInfo.extraDefiniteInits;
+               long inits = unconditionalFlowInfo.definiteInits;
+               checkNextEntry : for (int i = lastIndex; --i >= 0;) {
+                       if (definiteInits[i] == inits) {
+                               long[] otherInits = extraDefiniteInits[i];
+                               if ((extraInits != null) && (otherInits != null)) {
+                                       if (extraInits.length == otherInits.length) {
+                                               int j, max;
+                                               for (j = 0, max = extraInits.length; j < max; j++) {
+                                                       if (extraInits[j] != otherInits[j]) {
+                                                               continue checkNextEntry;
+                                                       }
+                                               }
+                                               return i;
+                                       }
+                               } else {
+                                       if ((extraInits == null) && (otherInits == null)) {
+                                               return i;
+                                       }
+                               }
+                       }
+               }
+
+               // add a new entry
+               if (definiteInits.length == lastIndex) {
+                       // need a resize
+                       System.arraycopy(
+                               definiteInits,
+                               0,
+                               (definiteInits = new long[lastIndex + 20]),
+                               0,
+                               lastIndex);
+                       System.arraycopy(
+                               extraDefiniteInits,
+                               0,
+                               (extraDefiniteInits = new long[lastIndex + 20][]),
+                               0,
+                               lastIndex);
+               }
+               definiteInits[lastIndex] = inits;
+               if (extraInits != null) {
+                       extraDefiniteInits[lastIndex] = new long[extraInits.length];
+                       System.arraycopy(
+                               extraInits,
+                               0,
+                               extraDefiniteInits[lastIndex],
+                               0,
+                               extraInits.length);
+               }
+               return lastIndex++;
+       }
+
+       /* Answer the reference method of this scope, or null if initialization scoope.
+       */
+       public AbstractMethodDeclaration referenceMethod() {
+
+               if (referenceContext instanceof AbstractMethodDeclaration) return (AbstractMethodDeclaration) referenceContext;
+               return null;
+       }
+
+       /* Answer the reference type of this scope.
+       *
+       * It is the nearest enclosing type of this scope.
+       */
+       public TypeDeclaration referenceType() {
+
+               return ((ClassScope) parent).referenceContext;
+       }
+
+       String basicToString(int tab) {
+
+               String newLine = "\n"; //$NON-NLS-1$
+               for (int i = tab; --i >= 0;)
+                       newLine += "\t"; //$NON-NLS-1$
+
+               String s = newLine + "--- Method Scope ---"; //$NON-NLS-1$
+               newLine += "\t"; //$NON-NLS-1$
+               s += newLine + "locals:"; //$NON-NLS-1$
+               for (int i = 0; i < localIndex; i++)
+                       s += newLine + "\t" + locals[i].toString(); //$NON-NLS-1$
+               s += newLine + "startIndex = " + startIndex; //$NON-NLS-1$
+               s += newLine + "isConstructorCall = " + isConstructorCall; //$NON-NLS-1$
+               s += newLine + "initializedField = " + initializedField; //$NON-NLS-1$
+               s += newLine + "lastVisibleFieldID = " + lastVisibleFieldID; //$NON-NLS-1$
+               s += newLine + "referenceContext = " + referenceContext; //$NON-NLS-1$
+               return s;
+       }
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java
new file mode 100644 (file)
index 0000000..115864c
--- /dev/null
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * 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.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+
+public final class MethodVerifier implements TagBits, TypeConstants {
+       SourceTypeBinding type;
+       HashtableOfObject inheritedMethods;
+       HashtableOfObject currentMethods;
+       ReferenceBinding runtimeException;
+       ReferenceBinding errorException;
+       LookupEnvironment environment;
+/*
+Binding creation is responsible for reporting all problems with types:
+       - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - abstract/final)
+               - plus invalid modifiers given the context (the verifier did not do this before)
+       - qualified name collisions between a type and a package (types in default packages are excluded)
+       - all type hierarchy problems:
+               - cycles in the superclass or superinterface hierarchy
+               - an ambiguous, invisible or missing superclass or superinterface
+               - extending a final class
+               - extending an interface instead of a class
+               - implementing a class instead of an interface
+               - implementing the same interface more than once (ie. duplicate interfaces)
+       - with nested types:
+               - shadowing an enclosing type's source name
+               - 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) {
+       this.type = null;  // Initialized with the public method verify(SourceTypeBinding)
+       this.inheritedMethods = null;
+       this.currentMethods = null;
+       this.runtimeException = null;
+       this.errorException = null;
+       this.environment = environment;
+}
+private boolean areParametersEqual(MethodBinding one, MethodBinding two) {
+       TypeBinding[] oneArgs = one.parameters;
+       TypeBinding[] twoArgs = two.parameters;
+       if (oneArgs == twoArgs) return true;
+
+       int length = oneArgs.length;
+       if (length != twoArgs.length) return false;
+
+       for (int i = 0; i < length; i++)
+               if (!areTypesEqual(oneArgs[i], twoArgs[i])) return false;
+       return true;
+}
+private boolean areReturnTypesEqual(MethodBinding one, MethodBinding two) {
+       return areTypesEqual(one.returnType, two.returnType);
+}
+private boolean areTypesEqual(TypeBinding one, TypeBinding two) {
+       if (one == two) return true;
+       if (one instanceof ReferenceBinding && two instanceof ReferenceBinding)
+               // can compare unresolved to resolved reference bindings
+               return CharOperation.equals(((ReferenceBinding) one).compoundName, ((ReferenceBinding) two).compoundName);
+       return false; // all other type bindings are identical
+}
+private void checkAbstractMethod(MethodBinding abstractMethod) {
+       if (mustImplementAbstractMethod(abstractMethod)) {
+               TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+               if (typeDeclaration != null) {
+                       MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(abstractMethod);
+                       missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
+               } else {
+                       this.problemReporter().abstractMethodMustBeImplemented(this.type, abstractMethod);
+               }
+       }
+}
+private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
+       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);
+                       continue nextMethod;
+               }
+
+               if (!currentMethod.isAbstract() && inheritedMethod.isAbstract()) {
+                       if ((currentMethod.modifiers & CompilerModifiers.AccOverriding) == 0)
+                               currentMethod.modifiers |= CompilerModifiers.AccImplementing;
+               } else {
+                       currentMethod.modifiers |= CompilerModifiers.AccOverriding;
+               }
+
+               if (!areReturnTypesEqual(currentMethod, inheritedMethod)) {
+                       this.problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
+               } else {
+                       if (currentMethod.thrownExceptions != NoExceptions)
+                               this.checkExceptions(currentMethod, inheritedMethod);
+                       if (inheritedMethod.isFinal())
+                               this.problemReporter(currentMethod).finalMethodCannotBeOverridden(currentMethod, inheritedMethod);
+                       if (!this.isAsVisible(currentMethod, inheritedMethod))
+                               this.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
+                                       ReferenceBinding declaringClass = inheritedMethod.declaringClass;
+                                       if (declaringClass.isInterface())
+                                               for (int j = length; --j >= 0;)
+                                                       if (i != j && methods[j].declaringClass.implementsInterface(declaringClass, false))
+                                                               continue nextMethod;
+
+                                       this.problemReporter(currentMethod).overridesDeprecatedMethod(currentMethod, inheritedMethod);
+                               }
+                       }
+               }
+       }
+}
+/*
+"8.4.4"
+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) {
+       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*/}
+               if (j == -1)
+                       if (!(newException.isCompatibleWith(this.runtimeException()) || newException.isCompatibleWith(this.errorException())))
+                               this.problemReporter(newMethod).incompatibleExceptionInThrowsClause(this.type, newMethod, inheritedMethod, newException);
+       }
+}
+private 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);
+               return;
+       }
+
+       MethodBinding concreteMethod = null;
+       if (!type.isInterface()) {  // ignore concrete methods for interfaces
+               for (int i = length; --i >= 0;) {  // Remember that only one of the methods can be non-abstract
+                       if (!methods[i].isAbstract()) {
+                               concreteMethod = methods[i];
+                               break;
+                       }
+               }
+       }
+       if (concreteMethod == null) {
+               if (this.type.isClass() && !this.type.isAbstract()) {
+                       for (int i = length; --i >= 0;) {
+                               if (mustImplementAbstractMethod(methods[i])) {
+                                       TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+                                       if (typeDeclaration != null) {
+                                               MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
+                                               missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+                                       } else {
+                                               this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+                                       }
+                                       return;
+                               }
+                       }
+               }
+               return;
+       }
+
+       MethodBinding[] abstractMethods = new MethodBinding[length - 1];
+       index = 0;
+       for (int i = length; --i >= 0;)
+               if (methods[i] != concreteMethod)
+                       abstractMethods[index++] = methods[i];
+
+       // 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);   
+       if (!concreteMethod.isPublic())
+               // Cannot reduce visibility of a public method specified by an interface
+               this.problemReporter().inheritedMethodReducesVisibility(type, concreteMethod, abstractMethods);
+       if (concreteMethod.thrownExceptions != NoExceptions)
+               for (int i = abstractMethods.length; --i >= 0;)
+                       this.checkExceptions(concreteMethod, abstractMethods[i]);
+}
+/*
+For each inherited method identifier (message pattern - vm signature minus the return type)
+       if current method exists
+               if current's vm signature does not match an inherited signature then complain 
+               else compare current's exceptions & visibility against each inherited method
+       else
+               if inherited methods = 1
+                       if inherited is abstract && type is NOT an interface or abstract, complain
+               else
+                       if vm signatures do not match complain
+                       else
+                               find the concrete implementation amongst the abstract methods (can only be 1)
+                               if one exists then
+                                       it must be a public instance method
+                                       compare concrete's exceptions against each abstract method
+                               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
+       char[][] methodSelectors = this.inheritedMethods.keyTable;
+       nextSelector : for (int s = methodSelectors.length; --s >= 0;) {
+               if (methodSelectors[s] == null) continue nextSelector;
+
+               MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]);
+               if (current == null && skipInheritedMethods)
+                       continue nextSelector;
+
+               MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s];
+               if (inherited.length == 1 && current == null) { // handle the common case
+                       if (mustImplementAbstractMethods && inherited[0].isAbstract())
+                               checkAbstractMethod(inherited[0]);
+                       continue nextSelector;
+               }
+
+               int index = -1;
+               MethodBinding[] matchingInherited = new MethodBinding[inherited.length];
+               if (current != null) {
+                       for (int i = 0, length1 = current.length; i < length1; i++) {
+                               while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
+                               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 (index >= 0)
+                                       this.checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
+                       }
+               }
+
+               for (int i = 0, length = inherited.length; i < length; i++) {
+                       while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
+                       MethodBinding inheritedMethod = inherited[i];
+                       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];
+                                               inherited[j] = null; // do not want to find it again
+                                       }
+                               }
+                       }
+                       if (index > 0)
+                               this.checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
+                       else if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract())
+                               checkAbstractMethod(matchingInherited[0]);
+               }
+       }
+}
+private void checkPackagePrivateAbstractMethod(MethodBinding abstractMethod) {
+       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
+               }
+       } 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);
+}
+/*
+Binding creation is responsible for reporting:
+       - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations)
+               - plus invalid modifiers given the context... examples:
+                       - interface methods can only be public
+                       - abstract methods can only be defined by abstract classes
+       - collisions... 2 methods with identical vmSelectors
+       - multiple methods with the same message pattern but different return types
+       - ambiguous, invisible or missing return/argument/exception types
+       - check the type of any array is not void
+       - check that each exception type is Throwable or a subclass of it
+*/
+private void computeInheritedMethods() {
+       this.inheritedMethods = new HashtableOfObject(51); // maps method selectors to an array of methods... must search to match paramaters & return type
+       ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[3][];
+       int lastPosition = -1;
+       ReferenceBinding[] itsInterfaces = type.superInterfaces();
+       if (itsInterfaces != NoSuperInterfaces)
+               interfacesToVisit[++lastPosition] = itsInterfaces;
+
+       ReferenceBinding superType = this.type.isClass()
+               ? this.type.superclass()
+               : 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;
+                               }
+                       }
+
+                       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[] 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);
+                               } 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;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       superType = superType.superclass();
+               }
+       }
+
+       for (int i = 0; i <= lastPosition; i++) {
+               ReferenceBinding[] interfaces = interfacesToVisit[i];
+               for (int j = 0, l = interfaces.length; j < l; j++) {
+                       superType = interfaces[j];
+                       if ((superType.tagBits & InterfaceVisited) == 0) {
+                               superType.tagBits |= InterfaceVisited;
+                               if (superType.isValidBinding()) {
+                                       if ((itsInterfaces = superType.superInterfaces()) != NoSuperInterfaces) {
+                                               if (++lastPosition == interfacesToVisit.length)
+                                                       System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+                                               interfacesToVisit[lastPosition] = itsInterfaces;
+                                       }
+
+                                       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);
+                                               if (existingMethods == null) {
+                                                       existingMethods = new MethodBinding[] {method};
+                                               } 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))
+                                                                       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;
+                                               }
+                                               this.inheritedMethods.put(method.selector, existingMethods);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // bit reinitialization
+       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;
+       }
+}
+private 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
+       for (int m = size; --m >= 0;) {
+               MethodBinding method = methods[m];
+               if (!(method.isConstructor() || method.isDefaultAbstract())) { // keep all methods which are NOT constructors or default abstract
+                       MethodBinding[] existingMethods = (MethodBinding[]) this.currentMethods.get(method.selector);
+                       if (existingMethods == null)
+                               existingMethods = new MethodBinding[1];
+                       else
+                               System.arraycopy(existingMethods, 0,
+                                       (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
+                       existingMethods[existingMethods.length - 1] = method;
+                       this.currentMethods.put(method.selector, existingMethods);
+               }
+       }
+}
+private ReferenceBinding errorException() {
+       if (errorException == null)
+               this.errorException = this.type.scope.getJavaLangError();
+       return errorException;
+}
+private boolean isAsVisible(MethodBinding newMethod, MethodBinding inheritedMethod) {
+       if (inheritedMethod.modifiers == newMethod.modifiers) return true;
+
+       if (newMethod.isPublic()) return true;          // Covers everything
+       if (inheritedMethod.isPublic()) return false;
+
+       if (newMethod.isProtected()) return true;
+       if (inheritedMethod.isProtected()) return false;
+
+       return !newMethod.isPrivate();          // The inheritedMethod cannot be private since it would not be visible
+}
+private boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) {
+       do {
+               if (testClass == superclass) return true;
+       } while ((testClass = testClass.superclass()) != null);
+       return false;
+}
+private boolean mustImplementAbstractMethod(MethodBinding abstractMethod) {
+       // 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
+       } else {
+               if (this.type.implementsInterface(declaringClass, false)) {
+                       if (this.type.isAbstract()) return false; // leave it for the subclasses
+                       if (!superclass.implementsInterface(declaringClass, true)) // only if a superclass does not also implement the interface
+                               return true;
+               }
+               while (superclass.isAbstract() && !superclass.implementsInterface(declaringClass, false))
+                       superclass = superclass.superclass(); // find the first concrete superclass or the superclass which implements the interface
+       }
+       return superclass.isAbstract();         // if it is a concrete class then we have already reported problem against it
+}
+private ProblemReporter problemReporter() {
+       return this.type.scope.problemReporter();
+}
+private 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();
+       return reporter;
+}
+ReferenceBinding[] resolvedExceptionTypesFor(MethodBinding method) {
+       ReferenceBinding[] exceptions = method.thrownExceptions;
+       if ((method.modifiers & CompilerModifiers.AccUnresolved) == 0)
+               return exceptions;
+
+       if (!(method.declaringClass instanceof BinaryTypeBinding))
+               return TypeConstants.NoExceptions; // safety check
+       BinaryTypeBinding binaryType = (BinaryTypeBinding) method.declaringClass;
+
+       for (int i = exceptions.length; --i >= 0;)
+               if (exceptions[i] instanceof UnresolvedReferenceBinding)
+                       exceptions[i] = (ReferenceBinding) binaryType.resolveType(exceptions[i]);
+       return exceptions;
+}
+private ReferenceBinding runtimeException() {
+       if (runtimeException == null)
+               this.runtimeException = this.type.scope.getJavaLangRuntimeException();
+       return runtimeException;
+}
+public void verify(SourceTypeBinding someType) {
+       this.type = someType;
+       this.computeMethods();
+       this.computeInheritedMethods();
+       this.checkMethods();
+}
+public String toString() {
+       StringBuffer buffer = new StringBuffer(10);
+       buffer.append("MethodVerifier for type: "); //$NON-NLS-1$
+       buffer.append(type.readableName());
+       buffer.append('\n');
+       buffer.append("\t-inherited methods: "); //$NON-NLS-1$
+       buffer.append(this.inheritedMethods);
+       return buffer.toString();
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
new file mode 100644 (file)
index 0000000..8143f9b
--- /dev/null
@@ -0,0 +1,217 @@
+/*******************************************************************************
+ * 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;
+
+public class NestedTypeBinding extends SourceTypeBinding {
+
+       public SourceTypeBinding enclosingType;
+
+       public SyntheticArgumentBinding[] enclosingInstances;
+       public SyntheticArgumentBinding[] outerLocalVariables;
+       public int enclosingInstancesSlotSize; // amount of slots used by synthetic enclosing instances
+       public int outerLocalVariablesSlotSize; // amount of slots used by synthetic outer local variables
+       
+       public NestedTypeBinding(char[][] typeName, ClassScope scope, SourceTypeBinding enclosingType) {
+               super(typeName, enclosingType.fPackage, scope);
+               this.tagBits |= IsNestedType;
+               this.enclosingType = enclosingType;
+       }
+       
+       /* Add a new synthetic argument for <actualOuterLocalVariable>.
+       * Answer the new argument or the existing argument if one already existed.
+       */
+       public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
+               SyntheticArgumentBinding synthLocal = null;
+       
+               if (outerLocalVariables == null) {
+                       synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
+                       outerLocalVariables = new SyntheticArgumentBinding[] {synthLocal};
+               } else {
+                       int size = outerLocalVariables.length;
+                       int newArgIndex = size;
+                       for (int i = size; --i >= 0;) {         // must search backwards
+                               if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
+                                       return outerLocalVariables[i];  // already exists
+                               if (outerLocalVariables[i].id > actualOuterLocalVariable.id)
+                                       newArgIndex = i;
+                       }
+                       SyntheticArgumentBinding[] synthLocals = new SyntheticArgumentBinding[size + 1];
+                       System.arraycopy(outerLocalVariables, 0, synthLocals, 0, newArgIndex);
+                       synthLocals[newArgIndex] = synthLocal = new SyntheticArgumentBinding(actualOuterLocalVariable);
+                       System.arraycopy(outerLocalVariables, newArgIndex, synthLocals, newArgIndex + 1, size - newArgIndex);
+                       outerLocalVariables = synthLocals;
+               }
+               //System.out.println("Adding synth arg for local var: " + new String(actualOuterLocalVariable.name) + " to: " + new String(this.readableName()));
+               if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
+                       this.updateInnerEmulationDependents();
+               return synthLocal;
+       }
+
+       /* Add a new synthetic argument for <enclosingType>.
+       * Answer the new argument or the existing argument if one already existed.
+       */
+       public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding targetEnclosingType) {
+               SyntheticArgumentBinding synthLocal = null;
+               if (enclosingInstances == null) {
+                       synthLocal = new SyntheticArgumentBinding(targetEnclosingType);
+                       enclosingInstances = new SyntheticArgumentBinding[] {synthLocal};
+               } else {
+                       int size = enclosingInstances.length;
+                       int newArgIndex = size;
+                       for (int i = size; --i >= 0;) {
+                               if (enclosingInstances[i].type == targetEnclosingType)
+                                       return enclosingInstances[i]; // already exists
+                               if (this.enclosingType() == targetEnclosingType)
+                                       newArgIndex = 0;
+                       }
+                       SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1];
+                       System.arraycopy(enclosingInstances, 0, newInstances, newArgIndex == 0 ? 1 : 0, size);
+                       newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(targetEnclosingType);
+                       enclosingInstances = newInstances;
+               }
+               //System.out.println("Adding synth arg for enclosing type: " + new String(enclosingType.readableName()) + " to: " + new String(this.readableName()));
+               if (scope.referenceCompilationUnit().isPropagatingInnerClassEmulation)
+                       this.updateInnerEmulationDependents();
+               return synthLocal;
+       }
+
+       /* Add a new synthetic argument and field for <actualOuterLocalVariable>.
+       * Answer the new argument or the existing argument if one already existed.
+       */
+       public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBinding actualOuterLocalVariable) {
+               SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable);
+               if (synthLocal == null) return null;
+       
+               if (synthLocal.matchingField == null)
+                       synthLocal.matchingField = addSyntheticField(actualOuterLocalVariable);
+               return synthLocal;
+       }
+
+       /* Add a new synthetic argument and field for <enclosingType>.
+       * Answer the new argument or the existing argument if one already existed.
+       */
+       public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding targetEnclosingType) {
+               SyntheticArgumentBinding synthLocal = addSyntheticArgument(targetEnclosingType);
+               if (synthLocal == null) return null;
+       
+               if (synthLocal.matchingField == null)
+                       synthLocal.matchingField = addSyntheticField(targetEnclosingType);
+               return synthLocal;
+       }
+
+       /**
+        * Compute the resolved positions for all the synthetic arguments
+        */
+       final public void computeSyntheticArgumentSlotSizes() {
+       
+               int slotSize = 0; 
+               // insert enclosing instances first, followed by the outerLocals
+               int enclosingInstancesCount = this.enclosingInstances == null ? 0 : this.enclosingInstances.length;
+               for (int i = 0; i < enclosingInstancesCount; i++){
+                       SyntheticArgumentBinding argument = this.enclosingInstances[i];
+                       // position the enclosing instance synthetic arg
+                       argument.resolvedPosition = slotSize + 1; // shift by 1 to leave room for aload0==this
+                       if (slotSize + 1 > 0xFF) { // no more than 255 words of arguments
+                               this.scope.problemReporter().noMoreAvailableSpaceForArgument(argument, this.scope.referenceType()); 
+                       }
+                       if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
+                               slotSize += 2;
+                       } else {
+                               slotSize ++;
+                       }
+               }
+               this.enclosingInstancesSlotSize = slotSize; 
+               
+               slotSize = 0; // reset, outer local are not positionned yet, since will be appended to user arguments
+               int outerLocalsCount = this.outerLocalVariables == null ? 0 : this.outerLocalVariables.length;
+                       for (int i = 0; i < outerLocalsCount; i++){
+                       SyntheticArgumentBinding argument = this.outerLocalVariables[i];
+                       // do NOT position the outerlocal synthetic arg yet,  since will be appended to user arguments
+                       if ((argument.type == LongBinding) || (argument.type == DoubleBinding)){
+                               slotSize += 2;
+                       } else {
+                               slotSize ++;
+                       }
+               }
+               this.outerLocalVariablesSlotSize = slotSize;
+       }
+       
+       /* Answer the receiver's enclosing type... null if the receiver is a top level type.
+       */
+       public ReferenceBinding enclosingType() {
+
+               return enclosingType;
+       }
+
+       /* Answer the synthetic argument for <actualOuterLocalVariable> or null if one does not exist.
+       */
+       public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
+
+               if (outerLocalVariables == null) return null;           // is null if no outer local variables are known
+       
+               for (int i = outerLocalVariables.length; --i >= 0;)
+                       if (outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
+                               return outerLocalVariables[i];
+               return null;
+       }
+
+       public SyntheticArgumentBinding[] syntheticEnclosingInstances() {
+               return enclosingInstances;              // is null if no enclosing instances are required
+       }
+
+       public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
+               if (enclosingInstances == null)
+                       return null;
+       
+               int length = enclosingInstances.length;
+               ReferenceBinding types[] = new ReferenceBinding[length];
+               for (int i = 0; i < length; i++)
+                       types[i] = (ReferenceBinding) enclosingInstances[i].type;
+               return types;
+       }
+
+       public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
+
+               return outerLocalVariables;             // is null if no outer locals are required
+       }
+
+       /*
+        * Trigger the dependency mechanism forcing the innerclass emulation
+        * to be propagated to all dependent source types.
+        */
+       public void updateInnerEmulationDependents() {
+               // nothing to do in general, only local types are doing anything
+       }
+       
+       /* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
+       */
+       public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
+
+               if (enclosingInstances == null) return null;            // is null if no enclosing instances are known
+       
+               // exact match
+               for (int i = enclosingInstances.length; --i >= 0;)
+                       if (enclosingInstances[i].type == targetEnclosingType)
+                               if (enclosingInstances[i].actualOuterLocalVariable == null)
+                                       return enclosingInstances[i];
+       
+               // type compatibility : to handle cases such as
+               // class T { class M{}}
+               // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
+               if (!onlyExactMatch){
+                       for (int i = enclosingInstances.length; --i >= 0;)
+                               if (enclosingInstances[i].actualOuterLocalVariable == null)
+                                       if (targetEnclosingType.isSuperclassOf((ReferenceBinding) enclosingInstances[i].type))
+                                               return enclosingInstances[i];
+               }
+               return null;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
new file mode 100644 (file)
index 0000000..ee68a49
--- /dev/null
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * 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.util.HashtableOfPackage;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfType;
+
+public class PackageBinding extends Binding implements TypeConstants {
+       public char[][] compoundName;
+       PackageBinding parent;
+       LookupEnvironment environment;
+       HashtableOfType knownTypes;
+       HashtableOfPackage knownPackages;
+protected PackageBinding() {
+       // for creating problem package
+}
+public PackageBinding(char[][] compoundName, PackageBinding parent, LookupEnvironment environment) {
+       this.compoundName = compoundName;
+       this.parent = parent;
+       this.environment = environment;
+       this.knownTypes = null; // initialized if used... class counts can be very large 300-600
+       this.knownPackages = new HashtableOfPackage(3); // sub-package counts are typically 0-3
+}
+public PackageBinding(char[] topLevelPackageName, LookupEnvironment environment) {
+       this(new char[][] {topLevelPackageName}, null, environment);
+}
+/* Create the default package.
+*/
+
+public PackageBinding(LookupEnvironment environment) {
+       this(CharOperation.NO_CHAR_CHAR, null, environment);
+}
+private void addNotFoundPackage(char[] simpleName) {
+       knownPackages.put(simpleName, LookupEnvironment.TheNotFoundPackage);
+}
+private void addNotFoundType(char[] simpleName) {
+       if (knownTypes == null)
+               knownTypes = new HashtableOfType(25);
+       knownTypes.put(simpleName, LookupEnvironment.TheNotFoundType);
+}
+void addPackage(PackageBinding element) {
+       knownPackages.put(element.compoundName[element.compoundName.length - 1], element);
+}
+void addType(ReferenceBinding element) {
+       if (knownTypes == null)
+               knownTypes = new HashtableOfType(25);
+       knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
+}
+/* API
+* Answer the receiver's binding type from Binding.BindingID.
+*/
+
+public final int bindingType() {
+       return PACKAGE;
+}
+private PackageBinding findPackage(char[] name) {
+       if (!environment.isPackage(this.compoundName, name))
+               return null;
+
+       char[][] subPkgCompoundName = CharOperation.arrayConcat(this.compoundName, name);
+       PackageBinding subPackageBinding = new PackageBinding(subPkgCompoundName, this, environment);
+       addPackage(subPackageBinding);
+       return subPackageBinding;
+}
+/* Answer the subpackage named name; ask the oracle for the package if its not in the cache.
+* Answer null if it could not be resolved.
+*
+* NOTE: This should only be used when we know there is NOT a type with the same name.
+*/
+
+PackageBinding getPackage(char[] name) {
+       PackageBinding binding = getPackage0(name);
+       if (binding != null) {
+               if (binding == LookupEnvironment.TheNotFoundPackage)
+                       return null;
+               else
+                       return binding;
+       }
+       if ((binding = findPackage(name)) != null)
+               return binding;
+
+       // not found so remember a problem package binding in the cache for future lookups
+       addNotFoundPackage(name);
+       return null;
+}
+/* Answer the subpackage named name if it exists in the cache.
+* Answer theNotFoundPackage if it could not be resolved the first time
+* it was looked up, otherwise answer null.
+*
+* NOTE: Senders must convert theNotFoundPackage into a real problem
+* package if its to returned.
+*/
+
+PackageBinding getPackage0(char[] name) {
+       return knownPackages.get(name);
+}
+/* Answer the type named name; ask the oracle for the type if its not in the cache.
+* Answer a NotVisible problem type if the type is not visible from the invocationPackage.
+* Answer null if it could not be resolved.
+*
+* NOTE: This should only be used by source types/scopes which know there is NOT a
+* package with the same name.
+*/
+
+ReferenceBinding getType(char[] name) {
+       ReferenceBinding binding = getType0(name);
+       if (binding == null) {
+               if ((binding = 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)
+               return null;
+       if (binding instanceof UnresolvedReferenceBinding)
+               binding = ((UnresolvedReferenceBinding) binding).resolve(environment);
+       if (binding.isNestedType())
+               return new ProblemReferenceBinding(name, InternalNameProvided);
+       return binding;
+}
+/* Answer the type named name 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: Senders must convert theNotFoundType into a real problem
+* reference type if its to returned.
+*/
+
+ReferenceBinding getType0(char[] name) {
+       if (knownTypes == null)
+               return null;
+       return knownTypes.get(name);
+}
+/* Answer the package or type named name; ask the oracle if it is not in the cache.
+* Answer null if it could not be resolved.
+*
+* When collisions exist between a type name & a package name, answer the type.
+* Treat the package as if it does not exist... a problem was already reported when the type was defined.
+*
+* NOTE: no visibility checks are performed.
+* THIS SHOULD ONLY BE USED BY SOURCE TYPES/SCOPES.
+*/
+
+public Binding getTypeOrPackage(char[] name) {
+       ReferenceBinding typeBinding = getType0(name);
+       if (typeBinding != null && typeBinding != LookupEnvironment.TheNotFoundType) {
+               if (typeBinding instanceof UnresolvedReferenceBinding)
+                       typeBinding = ((UnresolvedReferenceBinding) typeBinding).resolve(environment);
+               if (typeBinding.isNestedType())
+                       return new ProblemReferenceBinding(name, InternalNameProvided);
+               return typeBinding;
+       }
+
+       PackageBinding packageBinding = getPackage0(name);
+       if (packageBinding != null && packageBinding != LookupEnvironment.TheNotFoundPackage)
+               return packageBinding;
+
+       if (typeBinding == null) { // have not looked for it before
+               if ((typeBinding = environment.askForType(this, name)) != null) {
+                       if (typeBinding.isNestedType())
+                               return new ProblemReferenceBinding(name, InternalNameProvided);
+                       return typeBinding;
+               }
+
+               // Since name could not be found, add a problem binding
+               // to the collections so it will be reported as an error next time.
+               addNotFoundType(name);
+       }
+
+       if (packageBinding == null) { // have not looked for it before
+               if ((packageBinding = findPackage(name)) != null)
+                       return packageBinding;
+               addNotFoundPackage(name);
+       }
+
+       return null;
+}
+public char[] readableName() /*java.lang*/ {
+       return CharOperation.concatWith(compoundName, '.');
+}
+public String toString() {
+       if (compoundName == CharOperation.NO_CHAR_CHAR)
+               return "The Default Package"; //$NON-NLS-1$
+       else
+               return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemBinding.java
new file mode 100644 (file)
index 0000000..c4fab5f
--- /dev/null
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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 ProblemBinding extends Binding {
+       public char[] name;
+       public ReferenceBinding searchType;
+       private int problemId;
+// NOTE: must only answer the subset of the name related to the problem
+
+public ProblemBinding(char[][] compoundName, int problemId) {
+       this(CharOperation.concatWith(compoundName, '.'), problemId);
+}
+// NOTE: must only answer the subset of the name related to the problem
+
+public ProblemBinding(char[][] compoundName, ReferenceBinding searchType, int problemId) {
+       this(CharOperation.concatWith(compoundName, '.'), searchType, problemId);
+}
+ProblemBinding(char[] name, int problemId) {
+       this.name = name;
+       this.problemId = problemId;
+}
+ProblemBinding(char[] name, ReferenceBinding searchType, int problemId) {
+       this(name, problemId);
+       this.searchType = searchType;
+}
+/* API
+* Answer the receiver's binding type from Binding.BindingID.
+*/
+
+public final int bindingType() {
+       return VARIABLE | TYPE;
+}
+/* API
+* Answer the problem id associated with the receiver.
+* NoError if the receiver is a valid binding.
+*/
+
+public final int problemId() {
+       return problemId;
+}
+public char[] readableName() {
+       return name;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemFieldBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemFieldBinding.java
new file mode 100644 (file)
index 0000000..ec3012d
--- /dev/null
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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 ProblemFieldBinding extends FieldBinding {
+       private int problemId;
+       public FieldBinding closestMatch;
+               
+// NOTE: must only answer the subset of the name related to the problem
+
+public ProblemFieldBinding(ReferenceBinding declaringClass, char[][] compoundName, int problemId) {
+       this(null, declaringClass, CharOperation.concatWith(compoundName, '.'), problemId);
+}
+public ProblemFieldBinding(ReferenceBinding declaringClass, char[] name, int problemId) {
+       this(null, declaringClass, name, problemId);
+}
+public ProblemFieldBinding(FieldBinding closestMatch, ReferenceBinding declaringClass, char[] name, int problemId) {
+       this.closestMatch = closestMatch;
+       this.declaringClass = declaringClass;
+       this.name = name;
+       this.problemId = problemId;
+}
+/* API
+* Answer the problem id associated with the receiver.
+* NoError if the receiver is a valid binding.
+*/
+
+public final int problemId() {
+       return problemId;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
new file mode 100644 (file)
index 0000000..71f0547
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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;
+
+public class ProblemMethodBinding extends MethodBinding {
+       private int problemId;
+       public MethodBinding closestMatch;
+public ProblemMethodBinding(char[] selector, TypeBinding[] args, int problemId) {
+       this.selector = selector;
+       this.parameters = (args == null || args.length == 0) ? NoParameters : args;
+       this.problemId = problemId;
+}
+public ProblemMethodBinding(char[] selector, TypeBinding[] args, ReferenceBinding declaringClass, int problemId) {
+       this.selector = selector;
+       this.parameters = (args == null || args.length == 0) ? NoParameters : args;
+       this.declaringClass = declaringClass;
+       this.problemId = problemId;
+}
+public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBinding[] args, int problemId) {
+       this(selector, args, problemId);
+       this.closestMatch = closestMatch;
+       if (closestMatch != null) this.declaringClass = closestMatch.declaringClass;
+}
+/* API
+* Answer the problem id associated with the receiver.
+* NoError if the receiver is a valid binding.
+*/
+
+public final int problemId() {
+       return problemId;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemPackageBinding.java
new file mode 100644 (file)
index 0000000..c2b2367
--- /dev/null
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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;
+
+public class ProblemPackageBinding extends PackageBinding {
+       private int problemId;
+// NOTE: must only answer the subset of the name related to the problem
+
+ProblemPackageBinding(char[][] compoundName, int problemId) {
+       this.compoundName = compoundName;
+       this.problemId = problemId;
+}
+ProblemPackageBinding(char[] name, int problemId) {
+       this(new char[][] {name}, problemId);
+}
+/* API
+* Answer the problem id associated with the receiver.
+* NoError if the receiver is a valid binding.
+*/
+
+public final int problemId() {
+       return problemId;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
new file mode 100644 (file)
index 0000000..b34f200
--- /dev/null
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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;
+
+public interface ProblemReasons {
+       final int NoError = 0;
+       final int NotFound = 1;
+       final int NotVisible = 2;
+       final int Ambiguous = 3;
+       final int InternalNameProvided = 4; // used if an internal name is used in source
+       final int InheritedNameHidesEnclosingName = 5;
+       final int NonStaticReferenceInConstructorInvocation = 6;
+       final int NonStaticReferenceInStaticContext = 7;
+       final int ReceiverTypeNotVisible = 8;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
new file mode 100644 (file)
index 0000000..7225ba7
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+public class ProblemReferenceBinding extends ReferenceBinding {
+       public ReferenceBinding original;
+       private int problemId;
+// 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[] name, int problemId) {
+       this(new char[][] {name}, null, problemId);
+}
+
+public ProblemReferenceBinding(char[][] compoundName, ReferenceBinding original, int problemId) {
+       this.compoundName = compoundName;
+       this.original = original;
+       this.problemId = problemId;
+}
+public ProblemReferenceBinding(char[] name, ReferenceBinding original, int problemId) {
+       this(new char[][] {name}, original, problemId);
+}
+/* API
+* Answer the problem id associated with the receiver.
+* NoError if the receiver is a valid binding.
+*/
+
+public final int problemId() {
+       return problemId;
+}
+
+/**
+ * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#shortReadableName()
+ */
+public char[] shortReadableName() {
+       return readableName();
+}
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
new file mode 100644 (file)
index 0000000..6cda282
--- /dev/null
@@ -0,0 +1,589 @@
+/*******************************************************************************
+ * 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.env.IDependent;
+
+/*
+Not all fields defined by this type (& its subclasses) are initialized when it is created.
+Some are initialized only when needed.
+
+Accessors have been provided for some public fields so all TypeBindings have the same API...
+but access public fields directly whenever possible.
+Non-public fields have accessors which should be used everywhere you expect the field to be initialized.
+
+null is NOT a valid value for a non-public field... it just means the field is not initialized.
+*/
+
+abstract public class ReferenceBinding extends TypeBinding implements IDependent {
+       public char[][] compoundName;
+       public char[] sourceName;
+       public int modifiers;
+       public PackageBinding fPackage;
+
+       char[] fileName;
+       char[] constantPoolName;
+       char[] signature;
+
+public FieldBinding[] availableFields() {
+       return fields();
+}
+
+public MethodBinding[] availableMethods() {
+       return methods();
+}      
+/* Answer true if the receiver can be instantiated
+*/
+
+public boolean canBeInstantiated() {
+       return !(isAbstract() || isInterface());
+}
+/* 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 == fPackage;
+}
+/* Answer true if the receiver is visible to the receiverType and the invocationType.
+*/
+
+public final boolean canBeSeenBy(ReferenceBinding receiverType, SourceTypeBinding invocationType) {
+       if (isPublic()) return true;
+
+       if (invocationType == this && invocationType == receiverType) return true;
+
+       if (isProtected()) {
+
+               // answer true if the invocationType is the declaringClass or they are in the same package
+               // OR the invocationType is a subclass of the declaringClass
+               //    AND the invocationType is the invocationType or its subclass
+               //    OR the type is a static method accessed directly through a type
+               //    OR previous assertions are true for one of the enclosing type
+               if (invocationType == this) return true;
+               if (invocationType.fPackage == fPackage) return true;
+
+               ReferenceBinding currentType = invocationType;
+               ReferenceBinding declaringClass = enclosingType(); // protected types always have an enclosing one
+               if (declaringClass == null) return false; // could be null if incorrect top-level protected type
+               //int depth = 0;
+               do {
+                       if (declaringClass == invocationType) return true;
+                       if (declaringClass.isSuperclassOf(currentType)) return true;
+                       //depth++;
+                       currentType = currentType.enclosingType();
+               } while (currentType != null);
+               return false;
+       }
+
+       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;
+               
+               if (invocationType != this) {
+                       ReferenceBinding outerInvocationType = invocationType;
+                       ReferenceBinding temp = outerInvocationType.enclosingType();
+                       while (temp != null) {
+                               outerInvocationType = temp;
+                               temp = temp.enclosingType();
+                       }
+
+                       ReferenceBinding outerDeclaringClass = this;
+                       temp = outerDeclaringClass.enclosingType();
+                       while (temp != null) {
+                               outerDeclaringClass = temp;
+                               temp = temp.enclosingType();
+                       }
+                       if (outerInvocationType != outerDeclaringClass) return false;
+               }
+               return true;
+       }
+
+       // isDefault()
+       if (invocationType.fPackage != fPackage) return false;
+
+       ReferenceBinding type = receiverType;
+       ReferenceBinding declaringClass = enclosingType() == null ? this : enclosingType();
+       do {
+               if (declaringClass == type) return true;
+               if (fPackage != type.fPackage) return false;
+       } while ((type = type.superclass()) != null);
+       return false;
+}
+/* 
+ * Answer true if the receiver is visible to the type provided by the scope.
+ */
+
+public final boolean canBeSeenBy(Scope scope) {
+       
+       if (isPublic()) return true;
+
+       if (scope.kind == Scope.COMPILATION_UNIT_SCOPE){
+               return this.canBeSeenBy(((CompilationUnitScope)scope).fPackage);
+       }
+       
+       SourceTypeBinding invocationType = scope.enclosingSourceType();
+       if (invocationType == this) return true;
+
+       if (isProtected()) {
+               // answer true if the invocationType is the declaringClass or they are in the same package
+               // OR the invocationType is a subclass of the declaringClass
+               //    AND the invocationType is the invocationType or its subclass
+               //    OR the type is a static method accessed directly through a type
+               //    OR previous assertions are true for one of the enclosing type
+               if (invocationType.fPackage == fPackage) return true;
+
+               ReferenceBinding currentType = invocationType;
+               ReferenceBinding declaringClass = enclosingType(); // protected types always have an enclosing one
+               if (declaringClass == null) return false; // could be null if incorrect top-level protected type
+               // int depth = 0;
+               do {
+                       if (declaringClass == invocationType) return true;
+                       if (declaringClass.isSuperclassOf(currentType)) return true;
+                       // depth++;
+                       currentType = currentType.enclosingType();
+               } while (currentType != null);
+               return false;
+       }
+       if (isPrivate()) {
+               // answer true if the receiver and the invocationType have a common enclosingType
+               // already know they are not the identical type
+               ReferenceBinding outerInvocationType = invocationType;
+               ReferenceBinding temp = outerInvocationType.enclosingType();
+               while (temp != null) {
+                       outerInvocationType = temp;
+                       temp = temp.enclosingType();
+               }
+
+               ReferenceBinding outerDeclaringClass = this;
+               temp = outerDeclaringClass.enclosingType();
+               while (temp != null) {
+                       outerDeclaringClass = temp;
+                       temp = temp.enclosingType();
+               }
+               return outerInvocationType == outerDeclaringClass;
+       }
+
+       // isDefault()
+       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;
+       }
+
+       // 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;
+       }
+}
+/* Answer the receiver's constant pool name.
+*
+* NOTE: This method should only be used during/after code gen.
+*/
+
+public char[] constantPoolName() /* java/lang/Object */ {
+       if (constantPoolName != null)   return constantPoolName;
+       return constantPoolName = CharOperation.concatWith(compoundName, '/');
+}
+String debugName() {
+       return (compoundName != null) ? new String(readableName()) : "UNNAMED TYPE"; //$NON-NLS-1$
+}
+public final int depth() {
+       int depth = 0;
+       ReferenceBinding current = this;
+       while ((current = current.enclosingType()) != null)
+               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)
+               current = current.enclosingType();
+       return current;
+}
+public int fieldCount() {
+       return fields().length;
+}
+public FieldBinding[] fields() {
+       return NoFields;
+}
+public final int getAccessFlags() {
+       return modifiers & AccJustFlag;
+}
+public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
+       return null;
+}
+public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes) {
+       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" 
+ */
+
+public char[] getFileName() {
+       return fileName;
+}
+public ReferenceBinding getMemberType(char[] typeName) {
+       ReferenceBinding[] memberTypes = memberTypes();
+       for (int i = memberTypes.length; --i >= 0;)
+               if (CharOperation.equals(memberTypes[i].sourceName, typeName))
+                       return memberTypes[i];
+       return null;
+}
+public MethodBinding[] getMethods(char[] selector) {
+       return NoMethods;
+}
+public PackageBinding getPackage() {
+       return fPackage;
+}
+public boolean hasMemberTypes() {
+    return false;
+}
+/* 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;
+
+       ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+       int lastPosition = -1;
+       ReferenceBinding currentType = this;
+       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 (searchHierarchy && (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]) == anInterface)
+                               return true;
+
+                       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 false;
+}
+// Internal method... assume its only sent to classes NOT interfaces
+
+boolean implementsMethod(MethodBinding method) {
+       ReferenceBinding type = this;
+       while (type != null) {
+               MethodBinding[] methods = type.getMethods(method.selector);
+               for (int i = methods.length; --i >= 0;)
+                       if (methods[i].areParametersEqual(method))
+                               return true;
+               type = type.superclass();
+       }
+       return false;
+}
+/* Answer true if the receiver is an abstract type
+*/
+
+public final boolean isAbstract() {
+       return (modifiers & AccAbstract) != 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;
+}
+/* Answer true if the receiver type can be assigned to the argument type (right)
+*/
+       
+public boolean isCompatibleWith(TypeBinding right) {
+       if (right == this)
+               return true;
+       if (right.id == T_Object)
+               return true;
+       if (!(right instanceof ReferenceBinding))
+               return false;
+
+       ReferenceBinding referenceBinding = (ReferenceBinding) right;
+       if (referenceBinding.isInterface())
+               return implementsInterface(referenceBinding, true);
+       if (isInterface())  // Explicit conversion from an interface to a class is not allowed
+               return false;
+       return referenceBinding.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;
+}
+/* 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;
+}
+/* Answer true if the receiver has private visibility
+*/
+
+public final boolean isPrivate() {
+       return (modifiers & AccPrivate) != 0;
+}
+/* Answer true if the receiver has private visibility and is used locally
+*/
+
+public final boolean isPrivateUsed() {
+       return (modifiers & AccPrivateUsed) != 0;
+}
+/* Answer true if the receiver has protected visibility
+*/
+
+public final boolean isProtected() {
+       return (modifiers & AccProtected) != 0;
+}
+/* Answer true if the receiver has public visibility
+*/
+
+public final boolean isPublic() {
+       return (modifiers & AccPublic) != 0;
+}
+/* Answer true if the receiver is a static member type (or toplevel)
+ */
+
+public final boolean isStatic() {
+       return (modifiers & (AccStatic | AccInterface)) != 0 ||
+                   (tagBits & IsNestedType) == 0;
+}
+/* Answer true if all float operations must adher to IEEE 754 float/double rules
+*/
+
+public final boolean isStrictfp() {
+       return (modifiers & AccStrictfp) != 0;
+}
+/* Answer true if the receiver is in the superclass hierarchy of aType
+*
+* NOTE: Object.isSuperclassOf(Object) -> false
+*/
+
+public boolean isSuperclassOf(ReferenceBinding type) {
+       do {
+               if (this == (type = type.superclass())) return true;
+       } while (type != null);
+
+       return false;
+}
+/* Answer true if the receiver is deprecated (or any of its enclosing types)
+*/
+
+public final boolean isViewedAsDeprecated() {
+       return (modifiers & AccDeprecated) != 0 ||
+               (modifiers & AccDeprecatedImplicitly) != 0;
+}
+public ReferenceBinding[] memberTypes() {
+       return NoMemberTypes;
+}
+public MethodBinding[] methods() {
+       return NoMethods;
+}
+/**
+* Answer the source name for the type.
+* In the case of member types, as the qualified name from its top level type.
+* For example, for a member type N defined inside M & A: "A.M.N".
+*/
+
+public char[] qualifiedSourceName() {
+       if (isMemberType())
+               return CharOperation.concat(enclosingType().qualifiedSourceName(), sourceName(), '.');
+       return sourceName();
+}
+
+public char[] readableName() /*java.lang.Object*/ {
+       if (isMemberType())
+               return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+       return CharOperation.concatWith(compoundName, '.');
+}
+
+public char[] shortReadableName() /*Object*/ {
+       if (isMemberType())
+               return CharOperation.concat(enclosingType().shortReadableName(), sourceName, '.');
+       return sourceName;
+}
+
+/* Answer the receiver's signature.
+*
+* NOTE: This method should only be used during/after code gen.
+*/
+
+public char[] signature() /* Ljava/lang/Object; */ {
+       if (signature != null)
+               return signature;
+
+       return signature = CharOperation.concat('L', constantPoolName(), ';');
+}
+public char[] sourceName() {
+       return sourceName;
+}
+public ReferenceBinding superclass() {
+       return null;
+}
+public ReferenceBinding[] superInterfaces() {
+       return NoSuperInterfaces;
+}
+public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
+       if (isStatic()) return null;
+
+       ReferenceBinding enclosingType = enclosingType();
+       if (enclosingType == null)
+               return null;
+       return new ReferenceBinding[] {enclosingType};
+}
+public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
+       return null;            // is null if no enclosing instances are required
+}
+MethodBinding[] unResolvedMethods() { // for the MethodVerifier so it doesn't resolve types
+       return methods();
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/Scope.java
new file mode 100644 (file)
index 0000000..bfbb0b5
--- /dev/null
@@ -0,0 +1,2000 @@
+/*******************************************************************************
+ * 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.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
+import org.eclipse.jdt.internal.compiler.util.ObjectVector;
+
+public abstract class Scope
+       implements BaseTypes, BindingIds, CompilerModifiers, ProblemReasons, TagBits, TypeConstants, TypeIds {
+
+       public final static int BLOCK_SCOPE = 1;
+       public final static int METHOD_SCOPE = 2;
+       public final static int CLASS_SCOPE = 3;
+       public final static int COMPILATION_UNIT_SCOPE = 4;
+
+       public int kind;
+       public Scope parent;
+
+       protected Scope(int kind, Scope parent) {
+               this.kind = kind;
+               this.parent = parent;
+       }
+
+       /* Answer an int describing the relationship between the given types.
+       *
+       *               NotRelated 
+       *               EqualOrMoreSpecific : left is compatible with right
+       *               MoreGeneric : right is compatible with left
+       */
+       public static int compareTypes(TypeBinding left, TypeBinding right) {
+               if (left.isCompatibleWith(right))
+                       return EqualOrMoreSpecific;
+               if (right.isCompatibleWith(left))
+                       return MoreGeneric;
+               return NotRelated;
+       }
+
+       // Internal use only
+       protected final boolean areParametersAssignable(TypeBinding[] parameters, TypeBinding[] arguments) {
+               if (parameters == arguments)
+                       return true;
+
+               int length = parameters.length;
+               if (length != arguments.length)
+                       return false;
+
+               for (int i = 0; i < length; i++)
+                       if (parameters[i] != arguments[i])
+                               if (!arguments[i].isCompatibleWith(parameters[i]))
+                                       return false;
+               return true;
+       }
+       
+       public final ClassScope classScope() {
+               Scope scope = this;
+               do {
+                       if (scope instanceof ClassScope)
+                               return (ClassScope) scope;
+                       scope = scope.parent;
+               } while (scope != null);
+               return null;
+       }       
+
+       /* Answer an int describing the relationship between the given type and unchecked exceptions.
+       *
+       *       NotRelated 
+       *       EqualOrMoreSpecific : type is known for sure to be an unchecked exception type
+       *       MoreGeneric : type is a supertype of an actual unchecked exception type
+       */
+       public int compareUncheckedException(ReferenceBinding type) {
+               int comparison = compareTypes(type, getJavaLangRuntimeException());
+               if (comparison != 0) return comparison;
+               return compareTypes(type, getJavaLangError());
+       }
+
+       public final CompilationUnitScope compilationUnitScope() {
+               Scope lastScope = null;
+               Scope scope = this;
+               do {
+                       lastScope = scope;
+                       scope = scope.parent;
+               } while (scope != null);
+               return (CompilationUnitScope) lastScope;
+       }
+
+       public ArrayBinding createArray(TypeBinding type, int dimension) {
+               if (!type.isValidBinding())
+                       return new ArrayBinding(type, dimension);
+               return environment().createArrayType(type, dimension);
+       }
+
+       public final ClassScope enclosingClassScope() {
+               Scope scope = this;
+               while ((scope = scope.parent) != null) {
+                       if (scope instanceof ClassScope) return (ClassScope)scope;
+               }
+               return null; // may answer null if no type around
+       }
+
+       public final MethodScope enclosingMethodScope() {
+               Scope scope = this;
+               while ((scope = scope.parent) != null) {
+                       if (scope instanceof MethodScope) return (MethodScope)scope;
+               }
+               return null; // may answer null if no method around
+       }
+
+       /* Answer the receiver's enclosing source type.
+       */
+       public final SourceTypeBinding enclosingSourceType() {
+               Scope scope = this;
+               do {
+                       if (scope instanceof ClassScope)
+                               return ((ClassScope) scope).referenceContext.binding;
+                       scope = scope.parent;
+               } while (scope != null);
+               return null;
+       }
+       public final LookupEnvironment environment() {
+               Scope scope, unitScope = this;
+               while ((scope = unitScope.parent) != null)
+                       unitScope = 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, 
+               char[] selector,
+               TypeBinding[] argumentTypes,
+               InvocationSite invocationSite,
+               ReferenceBinding classHierarchyStart,
+               MethodBinding matchingMethod,
+               ObjectVector found) {
+
+               int startFoundSize = found.size;
+               ReferenceBinding currentType = classHierarchyStart;
+               while (currentType != null) {
+                       matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
+                       currentType = currentType.superclass();
+               }
+               int foundSize = found.size;
+               if (foundSize == startFoundSize) {
+                       if (matchingMethod != null) compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+                       return matchingMethod; // maybe null
+               }
+               MethodBinding[] candidates = new MethodBinding[foundSize - startFoundSize];
+               int candidatesCount = 0;
+               // argument type compatibility check
+               for (int i = startFoundSize; i < foundSize; i++) {
+                       MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+                       if (areParametersAssignable(methodBinding.parameters, argumentTypes))
+                               candidates[candidatesCount++] = methodBinding;
+               }
+               if (candidatesCount == 1) {
+                       compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+                       return candidates[0]; 
+               }
+               if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
+                       int argLength = argumentTypes.length;
+                       nextMethod : for (int i = 0; i < foundSize; i++) {
+                               MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+                               TypeBinding[] params = methodBinding.parameters;
+                               int paramLength = params.length;
+                               nextArg: for (int a = 0; a < argLength; a++) {
+                                       TypeBinding arg = argumentTypes[a];
+                                       for (int p = 0; p < paramLength; p++)
+                                               if (params[p] == arg)
+                                                       continue nextArg;
+                                       continue nextMethod;
+                               }
+                               return methodBinding;
+                       }
+                       return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
+               }
+               // no need to check for visibility - interface methods are public
+               return mostSpecificInterfaceMethodBinding(candidates, candidatesCount);
+       }
+
+       // Internal use only
+       public ReferenceBinding findDirectMemberType(char[] typeName, ReferenceBinding enclosingType) {
+               if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
+                       return null; // know it has no member types (nor inherited member types)
+
+               SourceTypeBinding enclosingSourceType = enclosingSourceType();
+               compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
+               ReferenceBinding memberType = enclosingType.getMemberType(typeName);
+               if (memberType != null) {
+                       compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+                       if (enclosingSourceType == null
+                                       ? memberType.canBeSeenBy(getCurrentPackage())
+                                       : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
+                               return memberType;
+                       return new ProblemReferenceBinding(typeName, memberType, NotVisible);
+               }
+               return null;
+       }
+
+       // Internal use only
+       public MethodBinding findExactMethod(
+               ReferenceBinding receiverType,
+               char[] selector,
+               TypeBinding[] argumentTypes,
+               InvocationSite invocationSite) {
+
+               faultInReceiverType(receiverType);
+               compilationUnitScope().recordTypeReference(receiverType);
+               compilationUnitScope().recordTypeReferences(argumentTypes);
+               MethodBinding exactMethod = receiverType.getExactMethod(selector, argumentTypes);
+               if (exactMethod != null) {
+                       compilationUnitScope().recordTypeReferences(exactMethod.thrownExceptions);
+                       if (receiverType.isInterface() || exactMethod.canBeSeenBy(receiverType, invocationSite, this))
+                               return exactMethod;
+               }
+               return null;
+       }
+
+       // Internal use only
+       /*      Answer the field binding that corresponds to fieldName.
+               Start the lookup at the receiverType.
+               InvocationSite implements
+                       isSuperAccess(); this is used to determine if the discovered field is visible.
+               Only fields defined by the receiverType or its supertypes are answered;
+               a field of an enclosing type will not be found using this API.
+       
+               If no visible field is discovered, null is answered.
+       */
+       public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite, boolean needResolve) {
+               if (receiverType.isBaseType()) return null;
+               if (receiverType.isArrayType()) {
+                       TypeBinding leafType = receiverType.leafComponentType();
+                       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;
+                       return new ProblemFieldBinding(field /* closest match*/, field.declaringClass, fieldName, NotVisible);
+               }
+               // collect all superinterfaces of receiverType until the field is found in a supertype
+               ReferenceBinding[][] interfacesToVisit = null;
+               int lastPosition = -1;
+               FieldBinding visibleField = null;
+               boolean keepLooking = true;
+               boolean notVisible = false;
+               // we could hold onto the not visible field for extra error reporting
+               while (keepLooking) {
+                       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);
+                               interfacesToVisit[lastPosition] = itsInterfaces;
+                       }
+                       if ((currentType = currentType.superclass()) == null)
+                               break;
+
+                       if ((field = currentType.getField(fieldName, needResolve)) != null) {
+                               keepLooking = false;
+                               if (field.canBeSeenBy(receiverType, invocationSite, this)) {
+                                       if (visibleField == null)
+                                               visibleField = field;
+                                       else
+                                               return new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
+                               } else {
+                                       notVisible = true;
+                               }
+                       }
+               }
+
+               // walk all visible interfaces to find ambiguous references
+               if (interfacesToVisit != null) {
+                       ProblemFieldBinding ambiguous = null;
+                       done : 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 ((field = anInterface.getField(fieldName, true /*resolve*/)) != null) {
+                                                       if (visibleField == null) {
+                                                               visibleField = field;
+                                                       } else {
+                                                               ambiguous = new ProblemFieldBinding(visibleField /* closest match*/, visibleField.declaringClass, fieldName, Ambiguous);
+                                                               break done;
+                                                       }
+                                               } else {
+                                                       ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
+                                                       if (itsInterfaces != NoSuperInterfaces) {
+                                                               if (++lastPosition == interfacesToVisit.length)
+                                                                       System.arraycopy(
+                                                                               interfacesToVisit,
+                                                                               0,
+                                                                               interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
+                                                                               0,
+                                                                               lastPosition);
+                                                               interfacesToVisit[lastPosition] = itsInterfaces;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       // bit reinitialization
+                       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 (ambiguous != null)
+                               return ambiguous;
+               }
+
+               if (visibleField != null)
+                       return visibleField;
+               if (notVisible)
+                       return new ProblemFieldBinding(currentType, fieldName, NotVisible);
+               return null;
+       }
+
+       // Internal use only
+       public ReferenceBinding findMemberType(char[] typeName, ReferenceBinding enclosingType) {
+               if ((enclosingType.tagBits & HasNoMemberTypes) != 0)
+                       return null; // know it has no member types (nor inherited member types)
+
+               SourceTypeBinding enclosingSourceType = enclosingSourceType();
+               PackageBinding currentPackage = getCurrentPackage();
+               compilationUnitScope().recordReference(enclosingType.compoundName, typeName);
+               ReferenceBinding memberType = enclosingType.getMemberType(typeName);
+               if (memberType != null) {
+                       compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+                       if (enclosingSourceType == null
+                                       ? memberType.canBeSeenBy(currentPackage)
+                                       : memberType.canBeSeenBy(enclosingType, enclosingSourceType))
+                               return memberType;
+                       return new ProblemReferenceBinding(typeName, memberType, NotVisible);
+               }
+
+               // collect all superinterfaces of receiverType until the memberType is found in a supertype
+               ReferenceBinding currentType = enclosingType;
+               ReferenceBinding[][] interfacesToVisit = null;
+               int lastPosition = -1;
+               ReferenceBinding visibleMemberType = null;
+               boolean keepLooking = true;
+               ReferenceBinding notVisible = null;
+               // we could hold onto the not visible field for extra error reporting
+               while (keepLooking) {
+                       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);
+                               interfacesToVisit[lastPosition] = itsInterfaces;
+                       }
+                       if ((currentType = currentType.superclass()) == null)
+                               break;
+
+                       compilationUnitScope().recordReference(currentType.compoundName, typeName);
+                       if ((memberType = currentType.getMemberType(typeName)) != null) {
+                               compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+                               keepLooking = false;
+                               if (enclosingSourceType == null
+                                       ? memberType.canBeSeenBy(currentPackage)
+                                       : memberType.canBeSeenBy(enclosingType, enclosingSourceType)) {
+                                               if (visibleMemberType == null)
+                                                       visibleMemberType = memberType;
+                                               else
+                                                       return new ProblemReferenceBinding(typeName, Ambiguous);
+                               } else {
+                                       notVisible = memberType;
+                               }
+                       }
+               }
+               // walk all visible interfaces to find ambiguous references
+               if (interfacesToVisit != null) {
+                       ProblemReferenceBinding ambiguous = null;
+                       done : 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;
+                                               compilationUnitScope().recordReference(anInterface.compoundName, typeName);
+                                               if ((memberType = anInterface.getMemberType(typeName)) != null) {
+                                                       compilationUnitScope().recordTypeReference(memberType); // to record supertypes
+                                                       if (visibleMemberType == null) {
+                                                               visibleMemberType = memberType;
+                                                       } else {
+                                                               ambiguous = new ProblemReferenceBinding(typeName, Ambiguous);
+                                                               break done;
+                                                       }
+                                               } else {
+                                                       ReferenceBinding[] itsInterfaces = anInterface.superInterfaces();
+                                                       if (itsInterfaces != NoSuperInterfaces) {
+                                                               if (++lastPosition == interfacesToVisit.length)
+                                                                       System.arraycopy(
+                                                                               interfacesToVisit,
+                                                                               0,
+                                                                               interfacesToVisit = new ReferenceBinding[lastPosition * 2][],
+                                                                               0,
+                                                                               lastPosition);
+                                                               interfacesToVisit[lastPosition] = itsInterfaces;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       // bit reinitialization
+                       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 (ambiguous != null)
+                               return ambiguous;
+               }
+               if (visibleMemberType != null)
+                       return visibleMemberType;
+               if (notVisible != null)
+                       return new ProblemReferenceBinding(typeName, notVisible, NotVisible);
+               return null;
+       }
+
+       // Internal use only
+       public MethodBinding findMethod(
+               ReferenceBinding receiverType,
+               char[] selector,
+               TypeBinding[] argumentTypes,
+               InvocationSite invocationSite) {
+
+               ReferenceBinding currentType = receiverType;
+               MethodBinding matchingMethod = null;
+               ObjectVector found = new ObjectVector(); //TODO should rewrite to remove #matchingMethod since found is allocated anyway
+
+               faultInReceiverType(receiverType);
+               compilationUnitScope().recordTypeReference(receiverType);
+               compilationUnitScope().recordTypeReferences(argumentTypes);
+
+               if (currentType.isInterface()) {
+                       MethodBinding[] currentMethods = currentType.getMethods(selector);
+                       int currentLength = currentMethods.length;
+                       if (currentLength == 1) {
+                               matchingMethod = currentMethods[0];
+                       } else if (currentLength > 1) {
+                               found.addAll(currentMethods);
+                       }
+                       matchingMethod = findMethodInSuperInterfaces(currentType, selector, found, matchingMethod);
+                       currentType = getJavaLangObject();
+               }
+
+               boolean isCompliant14 = compilationUnitScope().environment.options.complianceLevel >= ClassFileConstants.JDK1_4;
+               // superclass lookup
+               ReferenceBinding classHierarchyStart = currentType;
+               while (currentType != null) {
+                       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++){
+                                       MethodBinding currentMethod = currentMethods[i];
+                                       // 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)){
+                                                       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)){
+                                                               currentLength--;
+                                                               currentMethods[i] = null;
+                                                               continue nextMethod;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       if (currentLength == 1 && matchingMethod == null && found.size == 0) {
+                               matchingMethod = currentMethods[0];
+                       } else if (currentLength > 0) {
+                               if (matchingMethod != null) {
+                                       found.add(matchingMethod);
+                                       matchingMethod = null;
+                               }
+                               // append currentMethods, filtering out null entries
+                               int maxMethod = currentMethods.length;
+                               if (maxMethod == currentLength) { // no method was eliminated for 1.4 compliance (see above)
+                                       found.addAll(currentMethods);
+                               } else {
+                                       for (int i = 0, max = currentMethods.length; i < max; i++) {
+                                               MethodBinding currentMethod = currentMethods[i];
+                                               if (currentMethod != null) found.add(currentMethod);
+                                       }
+                               }
+                       }
+                       currentType = currentType.superclass();
+               }
+
+               // if found several candidates, then eliminate those not matching argument types
+               int foundSize = found.size;
+               MethodBinding[] candidates = null;
+               int candidatesCount = 0;
+               boolean checkedMatchingMethod = false; // is matchingMethod meeting argument expectation ?
+               if (foundSize > 0) {
+                       // argument type compatibility check
+                       for (int i = 0; i < foundSize; i++) {
+                               MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+                               if (areParametersAssignable(methodBinding.parameters, argumentTypes)) {
+                                       switch (candidatesCount) {
+                                               case 0: 
+                                                       matchingMethod = methodBinding; // if only one match, reuse matchingMethod
+                                                       checkedMatchingMethod = true; // matchingMethod is known to exist and match params here
+                                                       break;
+                                               case 1:
+                                                       candidates = new MethodBinding[foundSize]; // only lazily created if more than one match
+                                                       candidates[0] = matchingMethod; // copy back
+                                                       matchingMethod = null;
+                                                       // fall through
+                                               default:
+                                                       candidates[candidatesCount] = methodBinding;
+                                       }
+                                       candidatesCount++;
+                               }
+                       }
+               }
+               // if only one matching method left (either from start or due to elimination of rivals), then match is in matchingMethod
+               if (matchingMethod != null) {
+                       if (checkedMatchingMethod || areParametersAssignable(matchingMethod.parameters, argumentTypes)) {
+                               // (if no default abstract) must explicitly look for one instead, which could be a better match
+                               if (!matchingMethod.canBeSeenBy(receiverType, invocationSite, this)) {
+                                       // ignore matching method (to be consistent with multiple matches, none visible (matching method is then null)
+                                       MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, null, found);                                             
+                                       if (interfaceMethod != null) return interfaceMethod;
+                                       compilationUnitScope().recordTypeReferences(matchingMethod.thrownExceptions);
+                                       return matchingMethod;
+                               }
+                       } 
+                       return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+               }
+
+               // no match was found, try to find a close match when the parameter order is wrong or missing some parameters
+               if (candidatesCount == 0) {
+                       MethodBinding interfaceMethod =
+                               findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+                       if (interfaceMethod != null) return interfaceMethod;
+
+                       int argLength = argumentTypes.length;
+                       foundSize = found.size;
+                       nextMethod : for (int i = 0; i < foundSize; i++) {
+                               MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+                               TypeBinding[] params = methodBinding.parameters;
+                               int paramLength = params.length;
+                               nextArg: for (int a = 0; a < argLength; a++) {
+                                       TypeBinding arg = argumentTypes[a];
+                                       for (int p = 0; p < paramLength; p++)
+                                               if (params[p] == arg)
+                                                       continue nextArg;
+                                       continue nextMethod;
+                               }
+                               return methodBinding;
+                       }
+                       return (MethodBinding) found.elementAt(0); // no good match so just use the first one found
+               }
+
+               // tiebreak using visibility check
+               int visiblesCount = 0;
+               for (int i = 0; i < candidatesCount; i++) {
+                       MethodBinding methodBinding = candidates[i];
+                       if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
+                               if (visiblesCount != i) {
+                                       candidates[i] = null;
+                                       candidates[visiblesCount] = methodBinding;
+                               }
+                               visiblesCount++;
+                       }
+               }
+               if (visiblesCount == 1) {
+                       compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+                       return candidates[0];
+               }
+               if (visiblesCount == 0) {
+                       MethodBinding interfaceMethod =
+                               findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+                       if (interfaceMethod != null) return interfaceMethod;
+                       return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, NotVisible);
+               }
+               if (isCompliant14)
+                       return mostSpecificMethodBinding(candidates, visiblesCount);
+               return candidates[0].declaringClass.isClass()
+                       ? mostSpecificClassMethodBinding(candidates, visiblesCount)
+                       : mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
+       }
+       
+       // Internal use only
+       public MethodBinding findMethodForArray(
+               ArrayBinding receiverType,
+               char[] selector,
+               TypeBinding[] argumentTypes,
+               InvocationSite invocationSite) {
+
+               TypeBinding leafType = receiverType.leafComponentType();
+               if (leafType instanceof ReferenceBinding) {
+                       if (!((ReferenceBinding) leafType).canBeSeenBy(this))
+                               return new ProblemMethodBinding(selector, TypeConstants.NoParameters, (ReferenceBinding)leafType, ReceiverTypeNotVisible);
+               }
+
+               ReferenceBinding object = getJavaLangObject();
+               MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
+               if (methodBinding != null) {
+                       // handle the method clone() specially... cannot be protected or throw exceptions
+                       if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
+                               return new UpdatedMethodBinding(
+                                       environment().options.targetJDK >= ClassFileConstants.JDK1_4 ? (TypeBinding)receiverType : (TypeBinding)object, // remember its array type for codegen purpose on target>=1.4.0
+                                       (methodBinding.modifiers ^ AccProtected) | AccPublic,
+                                       CLONE,
+                                       methodBinding.returnType,
+                                       argumentTypes,
+                                       null,
+                                       object);
+                       if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
+                               return methodBinding;
+               }
+               // answers closest approximation, may not check argumentTypes or visibility
+               methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
+               if (methodBinding == null)
+                       return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+               if (methodBinding.isValidBinding()) {
+                       if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
+                               return new ProblemMethodBinding(
+                                       methodBinding,
+                                       selector,
+                                       argumentTypes,
+                                       NotFound);
+                       if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
+                               return new ProblemMethodBinding(
+                                       methodBinding,
+                                       selector,
+                                       methodBinding.parameters,
+                                       NotVisible);
+               }
+               return methodBinding;
+       }
+
+       public MethodBinding findMethodInSuperInterfaces(
+               ReferenceBinding currentType,
+               char[] selector,
+               ObjectVector found,
+               MethodBinding matchingMethod) {
+
+               ReferenceBinding[] itsInterfaces = currentType.superInterfaces();
+               if (itsInterfaces != NoSuperInterfaces) {
+                       ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+                       int lastPosition = -1;
+                       if (++lastPosition == interfacesToVisit.length)
+                               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++) {
+                                       currentType = interfaces[j];
+                                       if ((currentType.tagBits & InterfaceVisited) == 0) {
+                                               // if interface as not already been visited
+                                               currentType.tagBits |= InterfaceVisited;
+
+                                               MethodBinding[] currentMethods = currentType.getMethods(selector);
+                                               int currentLength = currentMethods.length;
+                                               if (currentLength == 1 && matchingMethod == null && found.size == 0) {
+                                                       matchingMethod = currentMethods[0];
+                                               } else if (currentLength > 0) {
+                                                       if (matchingMethod != null) {
+                                                               found.add(matchingMethod);
+                                                               matchingMethod = null;
+                                                       }
+                                                       found.addAll(currentMethods);
+                                               }
+                                               itsInterfaces = currentType.superInterfaces();
+                                               if (itsInterfaces != NoSuperInterfaces) {
+                                                       if (++lastPosition == interfacesToVisit.length)
+                                                               System.arraycopy(
+                                                                       interfacesToVisit, 0,
+                                                                       interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0,
+                                                                       lastPosition);
+                                                       interfacesToVisit[lastPosition] = itsInterfaces;
+                                               }
+                                       }
+                               }
+                       }
+
+                       // bit reinitialization
+                       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;
+                       }
+               }
+               return matchingMethod;
+       }
+
+       // Internal use only
+       public ReferenceBinding findType(
+               char[] typeName,
+               PackageBinding declarationPackage,
+               PackageBinding invocationPackage) {
+
+               compilationUnitScope().recordReference(declarationPackage.compoundName, typeName);
+               ReferenceBinding typeBinding = declarationPackage.getType(typeName);
+               if (typeBinding == null)
+                       return null;
+
+               if (typeBinding.isValidBinding()) {
+                       if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
+                               return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
+               }
+               return typeBinding;
+       }
+
+       public LocalVariableBinding findVariable(char[] variable) {
+
+               return null;
+       }
+       
+       public TypeBinding getBaseType(char[] name) {
+               // list should be optimized (with most often used first)
+               int length = name.length;
+               if (length > 2 && length < 8) {
+                       switch (name[0]) {
+                               case 'i' :
+                                       if (length == 3 && name[1] == 'n' && name[2] == 't')
+                                               return IntBinding;
+                                       break;
+                               case 'v' :
+                                       if (length == 4 && name[1] == 'o' && name[2] == 'i' && name[3] == 'd')
+                                               return VoidBinding;
+                                       break;
+                               case 'b' :
+                                       if (length == 7
+                                               && name[1] == 'o'
+                                               && name[2] == 'o'
+                                               && name[3] == 'l'
+                                               && name[4] == 'e'
+                                               && name[5] == 'a'
+                                               && name[6] == 'n')
+                                               return BooleanBinding;
+                                       if (length == 4 && name[1] == 'y' && name[2] == 't' && name[3] == 'e')
+                                               return ByteBinding;
+                                       break;
+                               case 'c' :
+                                       if (length == 4 && name[1] == 'h' && name[2] == 'a' && name[3] == 'r')
+                                               return CharBinding;
+                                       break;
+                               case 'd' :
+                                       if (length == 6
+                                               && name[1] == 'o'
+                                               && name[2] == 'u'
+                                               && name[3] == 'b'
+                                               && name[4] == 'l'
+                                               && name[5] == 'e')
+                                               return DoubleBinding;
+                                       break;
+                               case 'f' :
+                                       if (length == 5
+                                               && name[1] == 'l'
+                                               && name[2] == 'o'
+                                               && name[3] == 'a'
+                                               && name[4] == 't')
+                                               return FloatBinding;
+                                       break;
+                               case 'l' :
+                                       if (length == 4 && name[1] == 'o' && name[2] == 'n' && name[3] == 'g')
+                                               return LongBinding;
+                                       break;
+                               case 's' :
+                                       if (length == 5
+                                               && name[1] == 'h'
+                                               && name[2] == 'o'
+                                               && name[3] == 'r'
+                                               && name[4] == 't')
+                                               return ShortBinding;
+                       }
+               }
+               return null;
+       }
+
+       /* API
+     * 
+        *      Answer the binding that corresponds to the argument name.
+        *      flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
+        *      Only bindings corresponding to the mask can be answered.
+        *
+        *      For example, getBinding("foo", VARIABLE, site) will answer
+        *      the binding for the field or local named "foo" (or an error binding if none exists).
+        *      If a type named "foo" exists, it will not be detected (and an error binding will be answered)
+        *
+        *      The VARIABLE mask has precedence over the TYPE mask.
+        *
+        *      If the VARIABLE mask is not set, neither fields nor locals will be looked for.
+        *
+        *      InvocationSite implements:
+        *              isSuperAccess(); this is used to determine if the discovered field is visible.
+        *
+        *      Limitations: cannot request FIELD independently of LOCAL, or vice versa
+        */
+       public Binding getBinding(char[] name, int mask, InvocationSite invocationSite, boolean needResolve) {
+
+               try {
+                       Binding binding = null;
+                       FieldBinding problemField = null;
+                       if ((mask & VARIABLE) != 0) {
+                               boolean insideStaticContext = false;
+                               boolean insideConstructorCall = false;
+       
+                               FieldBinding foundField = null;
+                               // can be a problem field which is answered if a valid field is not found
+                               ProblemFieldBinding foundInsideProblem = null;
+                               // inside Constructor call or inside static context
+                               Scope scope = this;
+                               int depth = 0;
+                               int foundDepth = 0;
+                               ReferenceBinding foundActualReceiverType = null;
+                               done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+                                       switch (scope.kind) {
+                                               case METHOD_SCOPE :
+                                                       MethodScope methodScope = (MethodScope) scope;
+                                                       insideStaticContext |= methodScope.isStatic;
+                                                       insideConstructorCall |= methodScope.isConstructorCall;
+                                                       // Fall through... could duplicate the code below to save a cast - questionable optimization
+                                               case BLOCK_SCOPE :
+                                                       LocalVariableBinding variableBinding = scope.findVariable(name);
+                                                       // looks in this scope only
+                                                       if (variableBinding != null) {
+                                                               if (foundField != null && foundField.isValidBinding())
+                                                                       return new ProblemFieldBinding(
+                                                                               foundField, // closest match
+                                                                               foundField.declaringClass,
+                                                                               name,
+                                                                               InheritedNameHidesEnclosingName);
+                                                               if (depth > 0)
+                                                                       invocationSite.setDepth(depth);
+                                                               return variableBinding;
+                                                       }
+                                                       break;
+                                               case CLASS_SCOPE :
+                                                       ClassScope classScope = (ClassScope) scope;
+                                                       SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+                                                       FieldBinding fieldBinding =
+                                                               classScope.findField(enclosingType, name, invocationSite, needResolve);
+                                                       // Use next line instead if willing to enable protected access accross inner types
+                                                       // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
+                                                       if (fieldBinding != null) { // skip it if we did not find anything
+                                                               if (fieldBinding.problemId() == Ambiguous) {
+                                                                       if (foundField == null || foundField.problemId() == NotVisible)
+                                                                               // supercedes any potential InheritedNameHidesEnclosingName problem
+                                                                               return fieldBinding;
+                                                                       // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
+                                                                       return new ProblemFieldBinding(
+                                                                               foundField, // closest match
+                                                                               foundField.declaringClass,
+                                                                               name,
+                                                                               InheritedNameHidesEnclosingName);
+                                                               }
+       
+                                                               ProblemFieldBinding insideProblem = null;
+                                                               if (fieldBinding.isValidBinding()) {
+                                                                       if (!fieldBinding.isStatic()) {
+                                                                               if (insideConstructorCall) {
+                                                                                       insideProblem =
+                                                                                               new ProblemFieldBinding(
+                                                                                                       fieldBinding, // closest match
+                                                                                                       fieldBinding.declaringClass,
+                                                                                                       name,
+                                                                                                       NonStaticReferenceInConstructorInvocation);
+                                                                               } else if (insideStaticContext) {
+                                                                                       insideProblem =
+                                                                                               new ProblemFieldBinding(
+                                                                                                       fieldBinding, // closest match
+                                                                                                       fieldBinding.declaringClass,
+                                                                                                       name,
+                                                                                                       NonStaticReferenceInStaticContext);
+                                                                               }
+                                                                       }
+                                                                       if (enclosingType == fieldBinding.declaringClass
+                                                                               || environment().options.complianceLevel >= ClassFileConstants.JDK1_4){
+                                                                               // found a valid field in the 'immediate' scope (ie. not inherited)
+                                                                               // OR in 1.4 mode (inherited shadows enclosing)
+                                                                               if (foundField == null) {
+                                                                                       if (depth > 0){
+                                                                                               invocationSite.setDepth(depth);
+                                                                                               invocationSite.setActualReceiverType(enclosingType);
+                                                                                       }
+                                                                                       // return the fieldBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
+                                                                                       return insideProblem == null ? fieldBinding : insideProblem;
+                                                                               }
+                                                                               if (foundField.isValidBinding())
+                                                                                       // if a valid field was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
+                                                                                       if (foundField.declaringClass != fieldBinding.declaringClass)
+                                                                                               // ie. have we found the same field - do not trust field identity yet
+                                                                                               return new ProblemFieldBinding(
+                                                                                                       foundField, // closest match
+                                                                                                       foundField.declaringClass,
+                                                                                                       name,
+                                                                                                       InheritedNameHidesEnclosingName);
+                                                                       }
+                                                               }
+       
+                                                               if (foundField == null
+                                                                       || (foundField.problemId() == NotVisible
+                                                                               && fieldBinding.problemId() != NotVisible)) {
+                                                                       // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
+                                                                       foundDepth = depth;
+                                                                       foundActualReceiverType = enclosingType;
+                                                                       foundInsideProblem = insideProblem;
+                                                                       foundField = fieldBinding;
+                                                               }
+                                                       }
+                                                       depth++;
+                                                       insideStaticContext |= enclosingType.isStatic();
+                                                       // 1EX5I8Z - accessing outer fields within a constructor call is permitted
+                                                       // in order to do so, we change the flag as we exit from the type, not the method
+                                                       // itself, because the class scope is used to retrieve the fields.
+                                                       MethodScope enclosingMethodScope = scope.methodScope();
+                                                       insideConstructorCall =
+                                                               enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
+                                                       break;
+                                               case COMPILATION_UNIT_SCOPE :
+                                                       break done;
+                                       }
+                                       scope = scope.parent;
+                               }
+       
+                               if (foundInsideProblem != null)
+                                       return foundInsideProblem;
+                               if (foundField != null) {
+                                       if (foundField.isValidBinding()){
+                                               if (foundDepth > 0){
+                                                       invocationSite.setDepth(foundDepth);
+                                                       invocationSite.setActualReceiverType(foundActualReceiverType);
+                                               }
+                                               return foundField;
+                                       }
+                                       problemField = foundField;
+                               }
+                       }
+       
+                       // We did not find a local or instance variable.
+                       if ((mask & TYPE) != 0) {
+                               if ((binding = getBaseType(name)) != null)
+                                       return binding;
+                               binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
+                               if (binding.isValidBinding() || mask == TYPE)
+                                       return binding;
+                               // answer the problem type binding if we are only looking for a type
+                       } else if ((mask & PACKAGE) != 0) {
+                               compilationUnitScope().recordSimpleReference(name);
+                               if ((binding = environment().getTopLevelPackage(name)) != null)
+                                       return binding;
+                       }
+                       if (problemField != null) return problemField;
+                       return new ProblemBinding(name, enclosingSourceType(), NotFound);
+
+               } catch (AbortCompilation e) {
+                       e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
+                       throw e;
+               }
+       }
+
+       public MethodBinding getConstructor(ReferenceBinding receiverType, TypeBinding[] argumentTypes, InvocationSite invocationSite) {
+               try {
+                       faultInReceiverType(receiverType);
+                       compilationUnitScope().recordTypeReference(receiverType);
+                       compilationUnitScope().recordTypeReferences(argumentTypes);
+                       MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
+                       if (methodBinding != null && methodBinding.canBeSeenBy(invocationSite, this))
+                               return methodBinding;
+                       MethodBinding[] methods = receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
+                       if (methods == NoMethods)
+                               return new ProblemMethodBinding(
+                                       ConstructorDeclaration.ConstantPoolName,
+                                       argumentTypes,
+                                       NotFound);
+       
+                       MethodBinding[] compatible = new MethodBinding[methods.length];
+                       int compatibleIndex = 0;
+                       for (int i = 0, length = methods.length; i < length; i++)
+                               if (areParametersAssignable(methods[i].parameters, argumentTypes))
+                                       compatible[compatibleIndex++] = methods[i];
+                       if (compatibleIndex == 0)
+                               return new ProblemMethodBinding(
+                                       ConstructorDeclaration.ConstantPoolName,
+                                       argumentTypes,
+                                       NotFound);
+                       // need a more descriptive error... cannot convert from X to Y
+       
+                       MethodBinding[] visible = new MethodBinding[compatibleIndex];
+                       int visibleIndex = 0;
+                       for (int i = 0; i < compatibleIndex; i++) {
+                               MethodBinding method = compatible[i];
+                               if (method.canBeSeenBy(invocationSite, this))
+                                       visible[visibleIndex++] = method;
+                       }
+                       if (visibleIndex == 1) return visible[0];
+                       if (visibleIndex == 0)
+                               return new ProblemMethodBinding(
+                                       compatible[0],
+                                       ConstructorDeclaration.ConstantPoolName,
+                                       compatible[0].parameters,
+                                       NotVisible);
+                       return mostSpecificClassMethodBinding(visible, visibleIndex);
+               } catch (AbortCompilation e) {
+                       e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
+                       throw e;
+               }
+       }
+
+       public final PackageBinding getCurrentPackage() {
+               Scope scope, unitScope = this;
+               while ((scope = unitScope.parent) != null)
+                       unitScope = scope;
+               return ((CompilationUnitScope) unitScope).fPackage;
+       }
+
+       /**
+        * Returns the modifiers of the innermost enclosing declaration.
+        * @return modifiers
+        */
+       public int getDeclarationModifiers(){
+               switch(this.kind){
+                       case Scope.BLOCK_SCOPE :
+                       case Scope.METHOD_SCOPE :
+                               MethodScope methodScope = methodScope();
+                               if (!methodScope.isInsideInitializer()){
+                                       // check method modifiers to see if deprecated
+                                       MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
+                                       if (context != null) {
+                                               return context.modifiers;
+                                       }
+                               } else {
+                                       SourceTypeBinding type = ((BlockScope)this).referenceType().binding;
+
+                                       // inside field declaration ? check field modifier to see if deprecated
+                                       if (methodScope.initializedField != null) {
+                                               return methodScope.initializedField.modifiers;
+                                       }
+                                       if (type != null) {
+                                               return type.modifiers;
+                                       }
+                               }
+                               break;
+                       case Scope.CLASS_SCOPE :
+                               ReferenceBinding context = ((ClassScope)this).referenceType().binding;
+                               if (context != null) {
+                                       return context.modifiers;
+                               }
+                               break;
+               }
+               return -1;
+       }
+
+       public FieldBinding getField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
+               try {
+                       FieldBinding field = findField(receiverType, fieldName, invocationSite, true /*resolve*/);
+                       if (field != null) return field;
+       
+                       return new ProblemFieldBinding(
+                               receiverType instanceof ReferenceBinding ? (ReferenceBinding) receiverType : null,
+                               fieldName,
+                               NotFound);
+               } catch (AbortCompilation e) {
+                       e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
+                       throw e;
+               }
+       }
+
+       /* API
+        *      
+        *      Answer the method binding that corresponds to selector, argumentTypes.
+        *      Start the lookup at the enclosing type of the receiver.
+        *      InvocationSite implements 
+        *              isSuperAccess(); this is used to determine if the discovered method is visible.
+        *              setDepth(int); this is used to record the depth of the discovered method
+        *                      relative to the enclosing type of the receiver. (If the method is defined
+        *                      in the enclosing type of the receiver, the depth is 0; in the next enclosing
+        *                      type, the depth is 1; and so on
+        * 
+        *      If no visible method is discovered, an error binding is answered.
+        */
+       public MethodBinding getImplicitMethod(
+               char[] selector,
+               TypeBinding[] argumentTypes,
+               InvocationSite invocationSite) {
+
+               boolean insideStaticContext = false;
+               boolean insideConstructorCall = false;
+               MethodBinding foundMethod = null;
+               ProblemMethodBinding foundFuzzyProblem = null;
+               // the weird method lookup case (matches method name in scope, then arg types, then visibility)
+               ProblemMethodBinding foundInsideProblem = null;
+               // inside Constructor call or inside static context
+               Scope scope = this;
+               int depth = 0;
+               done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+                       switch (scope.kind) {
+                               case METHOD_SCOPE :
+                                       MethodScope methodScope = (MethodScope) scope;
+                                       insideStaticContext |= methodScope.isStatic;
+                                       insideConstructorCall |= methodScope.isConstructorCall;
+                                       break;
+                               case CLASS_SCOPE :
+                                       ClassScope classScope = (ClassScope) scope;
+                                       SourceTypeBinding receiverType = classScope.referenceContext.binding;
+                                       boolean isExactMatch = true;
+                                       // retrieve an exact visible match (if possible)
+                                       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);
+                                       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);
+                                       }
+                                       if (methodBinding != null) { // skip it if we did not find anything
+                                               if (methodBinding.problemId() == Ambiguous) {
+                                                       if (foundMethod == null || foundMethod.problemId() == NotVisible) {
+                                                               // supercedes any potential InheritedNameHidesEnclosingName problem
+                                                               return methodBinding;
+                                                       }
+                                                       // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
+                                                       return new ProblemMethodBinding(
+                                                               methodBinding, // closest match
+                                                               selector,
+                                                               argumentTypes,
+                                                               InheritedNameHidesEnclosingName);
+                                               }
+                                               ProblemMethodBinding fuzzyProblem = null;
+                                               ProblemMethodBinding insideProblem = null;
+                                               if (methodBinding.isValidBinding()) {
+                                                       if (!isExactMatch) {
+                                                               if (!areParametersAssignable(methodBinding.parameters, argumentTypes)) {
+                                                                       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);
+                                                               }
+                                                       }
+                                                       if (fuzzyProblem == null && !methodBinding.isStatic()) {
+                                                               if (insideConstructorCall) {
+                                                                       insideProblem =
+                                                                               new ProblemMethodBinding(
+                                                                                       methodBinding, // closest match
+                                                                                       methodBinding.selector,
+                                                                                       methodBinding.parameters,
+                                                                                       NonStaticReferenceInConstructorInvocation);
+                                                               } else if (insideStaticContext) {
+                                                                       insideProblem =
+                                                                               new ProblemMethodBinding(
+                                                                                       methodBinding, // closest match
+                                                                                       methodBinding.selector,
+                                                                                       methodBinding.parameters,
+                                                                                       NonStaticReferenceInStaticContext);
+                                                               }
+                                                       }
+                                                       
+                                                       if (receiverType == methodBinding.declaringClass
+                                                               || (receiverType.getMethods(selector)) != NoMethods
+                                                               || ((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)
+                                                               if (foundMethod == null) {
+                                                                       if (depth > 0){
+                                                                               invocationSite.setDepth(depth);
+                                                                               invocationSite.setActualReceiverType(receiverType);
+                                                                       }
+                                                                       // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
+                                                                       if (fuzzyProblem != null)
+                                                                               return fuzzyProblem;
+                                                                       if (insideProblem != null)
+                                                                               return insideProblem;
+                                                                       return methodBinding;
+                                                               }
+                                                               // if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
+                                                               // NOTE: Unlike fields, a non visible method hides a visible method
+                                                               if (foundMethod.declaringClass != methodBinding.declaringClass)
+                                                                       // ie. have we found the same method - do not trust field identity yet
+                                                                       return new ProblemMethodBinding(
+                                                                               methodBinding, // closest match
+                                                                               methodBinding.selector,
+                                                                               methodBinding.parameters,
+                                                                               InheritedNameHidesEnclosingName);
+                                                       }
+                                               }
+
+                                               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){
+                                                               invocationSite.setDepth(depth);
+                                                               invocationSite.setActualReceiverType(receiverType);
+                                                       }
+                                                       foundFuzzyProblem = fuzzyProblem;
+                                                       foundInsideProblem = insideProblem;
+                                                       if (fuzzyProblem == null)
+                                                               foundMethod = methodBinding; // only keep it if no error was found
+                                               }
+                                       }
+                                       depth++;
+                                       insideStaticContext |= receiverType.isStatic();
+                                       // 1EX5I8Z - accessing outer fields within a constructor call is permitted
+                                       // in order to do so, we change the flag as we exit from the type, not the method
+                                       // itself, because the class scope is used to retrieve the fields.
+                                       MethodScope enclosingMethodScope = scope.methodScope();
+                                       insideConstructorCall =
+                                               enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
+                                       break;
+                               case COMPILATION_UNIT_SCOPE :
+                                       break done;
+                       }
+                       scope = scope.parent;
+               }
+
+               if (foundFuzzyProblem != null)
+                       return foundFuzzyProblem;
+               if (foundInsideProblem != null)
+                       return foundInsideProblem;
+               if (foundMethod != null)
+                       return foundMethod;
+               return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+       }
+
+       public final ReferenceBinding getJavaIoSerializable() {
+               compilationUnitScope().recordQualifiedReference(JAVA_IO_SERIALIZABLE);
+               ReferenceBinding type = environment().getType(JAVA_IO_SERIALIZABLE);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_IO_SERIALIZABLE, 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);
+               if (type != null) return type;
+               problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
+               return null; // will not get here since the above error aborts the compilation
+       }
+
+       public final ReferenceBinding getJavaLangClass() {
+               compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLASS);
+               ReferenceBinding type = environment().getType(JAVA_LANG_CLASS);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_LANG_CLASS, referenceCompilationUnit());
+               return null; // will not get here since the above error aborts the compilation
+       }
+
+       public final ReferenceBinding getJavaLangCloneable() {
+               compilationUnitScope().recordQualifiedReference(JAVA_LANG_CLONEABLE);
+               ReferenceBinding type = environment().getType(JAVA_LANG_CLONEABLE);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_LANG_CLONEABLE, 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);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_LANG_ERROR, 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);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
+               return null; // will not get here since the above error aborts the compilation
+       }
+
+       public final ReferenceBinding getJavaLangRuntimeException() {
+               compilationUnitScope().recordQualifiedReference(JAVA_LANG_RUNTIMEEXCEPTION);
+               ReferenceBinding type = environment().getType(JAVA_LANG_RUNTIMEEXCEPTION);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_LANG_RUNTIMEEXCEPTION, referenceCompilationUnit());
+               return null; // will not get here since the above error aborts the compilation
+       }
+
+       public final ReferenceBinding getJavaLangString() {
+               compilationUnitScope().recordQualifiedReference(JAVA_LANG_STRING);
+               ReferenceBinding type = environment().getType(JAVA_LANG_STRING);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_LANG_STRING, referenceCompilationUnit());
+               return null; // will not get here since the above error aborts the compilation
+       }
+
+       public final ReferenceBinding getJavaLangThrowable() {
+               compilationUnitScope().recordQualifiedReference(JAVA_LANG_THROWABLE);
+               ReferenceBinding type = environment().getType(JAVA_LANG_THROWABLE);
+               if (type != null) return type;
+       
+               problemReporter().isClassPathCorrect(JAVA_LANG_THROWABLE, 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.
+       */
+       public final ReferenceBinding getMemberType(char[] typeName, ReferenceBinding enclosingType) {
+               ReferenceBinding memberType = findMemberType(typeName, enclosingType);
+               if (memberType != null) return memberType;
+               return new ProblemReferenceBinding(typeName, NotFound);
+       }
+
+       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);
+       
+                       ReferenceBinding currentType = (ReferenceBinding) receiverType;
+                       if (!currentType.canBeSeenBy(this))
+                               return new ProblemMethodBinding(selector, argumentTypes, ReceiverTypeNotVisible);
+       
+                       // retrieve an exact visible match (if possible)
+                       MethodBinding methodBinding = findExactMethod(currentType, selector, argumentTypes, invocationSite);
+                       if (methodBinding != null) return methodBinding;
+       
+                       // answers closest approximation, may not check argumentTypes or visibility
+                       methodBinding = findMethod(currentType, selector, argumentTypes, invocationSite);
+                       if (methodBinding == null)
+                               return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+                       if (methodBinding.isValidBinding()) {
+                               if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
+                                       return new ProblemMethodBinding(
+                                               methodBinding,
+                                               selector,
+                                               argumentTypes,
+                                               NotFound);
+                               if (!methodBinding.canBeSeenBy(currentType, invocationSite, this))
+                                       return new ProblemMethodBinding(
+                                               methodBinding,
+                                               selector,
+                                               methodBinding.parameters,
+                                               NotVisible);
+                       }
+                       return methodBinding;
+                       
+               } catch (AbortCompilation e) {
+                       e.updateContext(invocationSite, referenceCompilationUnit().compilationResult);
+                       throw e;
+               }
+       }
+
+       /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
+       * The name provided is a simple source name (e.g., "Object" , "Point", ...)
+       */
+       // The return type of this method could be ReferenceBinding if we did not answer base types.
+       // NOTE: We could support looking for Base Types last in the search, however any code using
+       // this feature would be extraordinarily slow.  Therefore we don't do this
+       public final TypeBinding getType(char[] name) {
+               // Would like to remove this test and require senders to specially handle base types
+               TypeBinding binding = getBaseType(name);
+               if (binding != null) return binding;
+               return (ReferenceBinding) getTypeOrPackage(name, TYPE);
+       }
+
+       /* Answer the type binding corresponding to the compoundName.
+       *
+       * NOTE: If a problem binding is returned, senders should extract the compound name
+       * from the binding & not assume the problem applies to the entire compoundName.
+       */
+       public final TypeBinding getType(char[][] compoundName) {
+               int typeNameLength = compoundName.length;
+               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);
+               Binding binding =
+                       getTypeOrPackage(compoundName[0], typeNameLength == 1 ? TYPE : TYPE | PACKAGE);
+               if (binding == null)
+                       return new ProblemReferenceBinding(compoundName[0], NotFound);
+               if (!binding.isValidBinding())
+                       return (ReferenceBinding) binding;
+
+               int currentIndex = 1;
+               boolean checkVisibility = false;
+               if (binding instanceof PackageBinding) {
+                       PackageBinding packageBinding = (PackageBinding) binding;
+                       while (currentIndex < typeNameLength) {
+                               binding = packageBinding.getTypeOrPackage(compoundName[currentIndex++]); // does not check visibility
+                               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))
+                                       break;
+                               packageBinding = (PackageBinding) binding;
+                       }
+                       if (binding instanceof PackageBinding)
+                               return new ProblemReferenceBinding(
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       NotFound);
+                       checkVisibility = true;
+               }
+
+               // binding is now a ReferenceBinding
+               ReferenceBinding typeBinding = (ReferenceBinding) binding;
+               compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
+               if (checkVisibility) // handles the fall through case
+                       if (!typeBinding.canBeSeenBy(this))
+                               return new ProblemReferenceBinding(
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       typeBinding,
+                                       NotVisible);
+
+               while (currentIndex < typeNameLength) {
+                       typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
+                       if (!typeBinding.isValidBinding()) {
+                               if (typeBinding instanceof ProblemReferenceBinding) {
+                                       ProblemReferenceBinding problemBinding = (ProblemReferenceBinding) typeBinding;
+                                       return new ProblemReferenceBinding(
+                                               CharOperation.subarray(compoundName, 0, currentIndex),
+                                               problemBinding.original,
+                                               typeBinding.problemId());
+                               }
+                               return new ProblemReferenceBinding(
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       typeBinding.problemId());
+                       }
+               }
+               return typeBinding;
+       }
+
+       /* Internal use only 
+       */
+       final Binding getTypeOrPackage(char[] name, int mask) {
+               Scope scope = this;
+               ReferenceBinding foundType = null;
+               if ((mask & TYPE) == 0) {
+                       Scope next = scope;
+                       while ((next = scope.parent) != null)
+                               scope = next;
+               } else {
+                       done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+                               switch (scope.kind) {
+                                       case METHOD_SCOPE :
+                                       case BLOCK_SCOPE :
+                                               ReferenceBinding localType = ((BlockScope) scope).findLocalType(name); // looks in this scope only
+                                               if (localType != null) {
+                                                       if (foundType != null && foundType != localType)
+                                                               return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+                                                       return localType;
+                                               }
+                                               break;
+                                       case CLASS_SCOPE :
+                                               SourceTypeBinding sourceType = ((ClassScope) scope).referenceContext.binding;
+                                               // 6.5.5.1 - simple name favors member type over top-level type in same unit
+                                               ReferenceBinding memberType = findMemberType(name, sourceType);
+                                               if (memberType != null) { // skip it if we did not find anything
+                                                       if (memberType.problemId() == Ambiguous) {
+                                                               if (foundType == null || foundType.problemId() == NotVisible)
+                                                                       // supercedes any potential InheritedNameHidesEnclosingName problem
+                                                                       return memberType;
+                                                               // make the user qualify the type, likely wants the first inherited type
+                                                               return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+                                                       }
+                                                       if (memberType.isValidBinding()) {
+                                                               if (sourceType == memberType.enclosingType()
+                                                                               || environment().options.complianceLevel >= ClassFileConstants.JDK1_4) {
+                                                                       // found a valid type in the 'immediate' scope (ie. not inherited)
+                                                                       // OR in 1.4 mode (inherited shadows enclosing)
+                                                                       if (foundType == null)
+                                                                               return memberType; 
+                                                                       if (foundType.isValidBinding())
+                                                                               // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
+                                                                               if (foundType != memberType)
+                                                                                       return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+                                                               }
+                                                       }
+                                                       if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
+                                                               // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
+                                                               foundType = memberType;
+                                               }
+                                               if (CharOperation.equals(sourceType.sourceName, name)) {
+                                                       if (foundType != null && foundType != sourceType && foundType.problemId() != NotVisible)
+                                                               return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+                                                       return sourceType;
+                                               }
+                                               break;
+                                       case COMPILATION_UNIT_SCOPE :
+                                               break done;
+                               }
+                               scope = scope.parent;
+                       }
+                       if (foundType != null && foundType.problemId() != NotVisible)
+                               return foundType;
+               }
+
+               // at this point the scope is a compilation unit scope
+               CompilationUnitScope unitScope = (CompilationUnitScope) scope;
+               PackageBinding currentPackage = unitScope.fPackage; 
+               // ask for the imports + name
+               if ((mask & TYPE) != 0) {
+                       // check single type imports.
+
+                       ImportBinding[] imports = unitScope.imports;
+                       if (imports != null) {
+                               HashtableOfObject typeImports = unitScope.resolvedSingeTypeImports;
+                               if (typeImports != null) {
+                                       ImportBinding typeImport = (ImportBinding) typeImports.get(name);
+                                       if (typeImport != null) {
+                                               ImportReference importReference = typeImport.reference;
+                                               if (importReference != null) importReference.used = true;
+                                               return typeImport.resolvedImport; // already know its visible
+                                       }
+                               } else {
+                                       // walk all the imports since resolvedSingeTypeImports is not yet initialized
+                                       for (int i = 0, length = imports.length; i < length; i++) {
+                                               ImportBinding typeImport = imports[i];
+                                               if (!typeImport.onDemand) {
+                                                       if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name)) {
+                                                               if (unitScope.resolveSingleTypeImport(typeImport) != null) {
+                                                                       ImportReference importReference = typeImport.reference;
+                                                                       if (importReference != null) importReference.used = true;
+                                                                       return typeImport.resolvedImport; // already know its visible
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       // check if the name is in the current package, skip it if its a sub-package
+                       unitScope.recordReference(currentPackage.compoundName, name);
+                       Binding binding = currentPackage.getTypeOrPackage(name);
+                       if (binding instanceof ReferenceBinding) return binding; // type is always visible to its own package
+
+                       // check on demand imports
+                       if (imports != null) {
+                               boolean foundInImport = false;
+                               ReferenceBinding type = null;
+                               for (int i = 0, length = imports.length; i < length; i++) {
+                                       ImportBinding someImport = imports[i];
+                                       if (someImport.onDemand) {
+                                               Binding resolvedImport = someImport.resolvedImport;
+                                               ReferenceBinding temp = resolvedImport instanceof PackageBinding
+                                                       ? findType(name, (PackageBinding) resolvedImport, currentPackage)
+                                                       : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
+                                               if (temp != null) {
+                                                       if (temp.isValidBinding()) {
+                                                               ImportReference importReference = someImport.reference;
+                                                               if (importReference != null) importReference.used = true;
+                                                               if (foundInImport)
+                                                                       // Answer error binding -- import on demand conflict; name found in two import on demand packages.
+                                                                       return new ProblemReferenceBinding(name, Ambiguous);
+                                                               type = temp;
+                                                               foundInImport = true;
+                                                       } else if (foundType == null) {
+                                                               foundType = temp;
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (type != null) return type;
+                       }
+               }
+
+               unitScope.recordSimpleReference(name);
+               if ((mask & PACKAGE) != 0) {
+                       PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
+                       if (packageBinding != null) return packageBinding;
+               }
+
+               // Answer error binding -- could not find name
+               if (foundType != null) return foundType; // problem type from above
+               return new ProblemReferenceBinding(name, NotFound);
+       }
+
+       // Added for code assist... NOT Public API
+       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);
+               if (!binding.isValidBinding()) return binding;
+
+               int currentIndex = 1;
+               boolean checkVisibility = false;
+               if (binding instanceof PackageBinding) {
+                       PackageBinding packageBinding = (PackageBinding) binding;
+
+                       while (currentIndex < nameLength) {
+                               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))
+                                       break;
+                               packageBinding = (PackageBinding) binding;
+                       }
+                       if (binding instanceof PackageBinding) return binding;
+                       checkVisibility = true;
+               }
+               // binding is now a ReferenceBinding
+               ReferenceBinding typeBinding = (ReferenceBinding) binding;
+               if (checkVisibility) // handles the fall through case
+                       if (!typeBinding.canBeSeenBy(this))
+                               return new ProblemReferenceBinding(
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       typeBinding,
+                                       NotVisible);
+
+               while (currentIndex < nameLength) {
+                       typeBinding = getMemberType(compoundName[currentIndex++], typeBinding);
+                       // checks visibility
+                       if (!typeBinding.isValidBinding())
+                               return new ProblemReferenceBinding(
+                                       CharOperation.subarray(compoundName, 0, currentIndex),
+                                       typeBinding.problemId());
+               }
+               return typeBinding;
+       }
+
+       /* Answer true if the scope is nested inside a given field declaration.
+     * Note: it works as long as the scope.fieldDeclarationIndex is reflecting the field being traversed 
+     * e.g. during name resolution.
+       */
+       public final boolean isDefinedInField(FieldBinding field) {
+               Scope scope = this;
+               do {
+                       if (scope instanceof MethodScope) {
+                               MethodScope methodScope = (MethodScope) scope;
+                               if (methodScope.initializedField == field) return true;
+                       }
+                       scope = scope.parent;
+               } while (scope != null);
+               return false;
+       }
+
+       /* Answer true if the scope is nested inside a given method declaration
+       */
+       public final boolean isDefinedInMethod(MethodBinding method) {
+               Scope scope = this;
+               do {
+                       if (scope instanceof MethodScope) {
+                               ReferenceContext refContext = ((MethodScope) scope).referenceContext;
+                               if (refContext instanceof AbstractMethodDeclaration
+                                               && ((AbstractMethodDeclaration)refContext).binding == method) {
+                                       return true;
+                               }
+                       }
+                       scope = scope.parent;
+               } while (scope != null);
+               return false;
+       }
+
+       /* Answer whether the type is defined in the same compilation unit as the receiver
+       */
+       public final boolean isDefinedInSameUnit(ReferenceBinding type) {
+               // find the outer most enclosing type
+               ReferenceBinding enclosingType = type;
+               while ((type = enclosingType.enclosingType()) != null)
+                       enclosingType = type;
+
+               // find the compilation unit scope
+               Scope scope, unitScope = this;
+               while ((scope = unitScope.parent) != null)
+                       unitScope = scope;
+
+               // test that the enclosingType is not part of the compilation unit
+               SourceTypeBinding[] topLevelTypes =
+                       ((CompilationUnitScope) unitScope).topLevelTypes;
+               for (int i = topLevelTypes.length; --i >= 0;)
+                       if (topLevelTypes[i] == enclosingType)
+                               return true;
+               return false;
+       }
+               
+       /* Answer true if the scope is nested inside a given type declaration
+       */
+       public final boolean isDefinedInType(ReferenceBinding type) {
+               Scope scope = this;
+               do {
+                       if (scope instanceof ClassScope)
+                               if (((ClassScope) scope).referenceContext.binding == type){
+                                       return true;
+                               }
+                       scope = scope.parent;
+               } while (scope != null);
+               return false;
+       }
+
+       public boolean isInsideDeprecatedCode(){
+               switch(this.kind){
+                       case Scope.BLOCK_SCOPE :
+                       case Scope.METHOD_SCOPE :
+                               MethodScope methodScope = methodScope();
+                               if (!methodScope.isInsideInitializer()){
+                                       // check method modifiers to see if deprecated
+                                       MethodBinding context = ((AbstractMethodDeclaration)methodScope.referenceContext).binding;
+                                       if (context != null && 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()) {
+                                               return true;
+                                       }
+                                       if (type != null && type.isViewedAsDeprecated()) {
+                                               return true;
+                                       }
+                               }
+                               break;
+                       case Scope.CLASS_SCOPE :
+                               ReferenceBinding context = ((ClassScope)this).referenceType().binding;
+                               if (context != null && context.isViewedAsDeprecated()) {
+                                       return true;
+                               }
+                               break;
+               }
+               return false;
+       }
+       
+       public final MethodScope methodScope() {
+               Scope scope = this;
+               do {
+                       if (scope instanceof MethodScope)
+                               return (MethodScope) scope;
+                       scope = scope.parent;
+               } while (scope != null);
+               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
+       * superclass and so on. We want to find the one which matches best.
+       *
+       * Since the receiver type is a class, we know each method's declaring class is
+       * either the receiver type or one of its superclasses. It is an error if the best match
+       * 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;
+               MethodBinding previous = null;
+
+               nextVisible : for (int i = 0; i < visibleSize; i++) {
+                       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
+                       for (int j = 0; j < visibleSize; j++) {
+                               if (i == j) continue;
+                               MethodBinding next = visible[j];
+                               if (!areParametersAssignable(next.parameters, method.parameters))
+                                       continue nextVisible;
+                       }
+                       compilationUnitScope().recordTypeReferences(method.thrownExceptions);
+                       return method;
+               }
+               return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+       }
+
+       // 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
+       * but unrelated superinterfaces may define the same method in acceptable but
+       * not identical ways... we just take the best match that we find since any class which
+       * implements the receiver interface MUST implement all signatures for the method...
+       * in which case the best match is correct.
+       *
+       * NOTE: This is different than javac... in the following example, the message send of
+       * bar(X) in class Y is supposed to be ambiguous. But any class which implements the
+       * interface I MUST implement both signatures for bar. If this class was the receiver of
+       * the message send instead of the interface I, then no problem would be reported.
+       *
+       interface I1 {
+               void bar(J j);
+       }
+       interface I2 {
+       //      void bar(J j);
+               void bar(Object o);
+       }
+       interface I extends I1, I2 {}
+       interface J {}
+       
+       class X implements J {}
+       
+       class Y extends X {
+               public void foo(I i, X x) { i.bar(x); }
+       }
+       */
+       protected final MethodBinding mostSpecificInterfaceMethodBinding(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;
+                       }
+                       compilationUnitScope().recordTypeReferences(method.thrownExceptions);
+                       return method;
+               }
+               return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+       }
+
+       
+       // 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;
+                       }
+                       compilationUnitScope().recordTypeReferences(method.thrownExceptions);
+                       return method;
+               }
+               return new ProblemMethodBinding(visible[0].selector, visible[0].parameters, Ambiguous);
+       }
+
+       public final ClassScope outerMostClassScope() {
+               ClassScope lastClassScope = null;
+               Scope scope = this;
+               do {
+                       if (scope instanceof ClassScope)
+                               lastClassScope = (ClassScope) scope;
+                       scope = scope.parent;
+               } while (scope != null);
+               return lastClassScope; // may answer null if no class around
+       }
+
+       public final MethodScope outerMostMethodScope() {
+               MethodScope lastMethodScope = null;
+               Scope scope = this;
+               do {
+                       if (scope instanceof MethodScope)
+                               lastMethodScope = (MethodScope) scope;
+                       scope = scope.parent;
+               } while (scope != null);
+               return lastMethodScope; // may answer null if no method around
+       }
+
+       public abstract ProblemReporter problemReporter();
+
+       public final CompilationUnitDeclaration referenceCompilationUnit() {
+               Scope scope, unitScope = this;
+               while ((scope = unitScope.parent) != null)
+                       unitScope = scope;
+               return ((CompilationUnitScope) unitScope).referenceContext;
+       }
+       // start position in this scope - for ordering scopes vs. variables
+       int startIndex() {
+               return 0;
+       }
+       
+       /**
+        * Returns the immediately enclosing switchCase statement (carried by closest blockScope),
+        */
+       public CaseStatement switchCase() {
+               Scope scope = this;
+               do {
+                       if (scope instanceof BlockScope)
+                               return ((BlockScope) scope).switchCase;
+                       scope = scope.parent;
+               } while (scope != null);
+               return null;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
new file mode 100644 (file)
index 0000000..e791f1e
--- /dev/null
@@ -0,0 +1,1068 @@
+/*******************************************************************************
+ * 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.Enumeration;
+import java.util.Hashtable;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.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.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;
+       public ReferenceBinding[] superInterfaces;
+       public FieldBinding[] fields;
+       public MethodBinding[] methods;
+       public ReferenceBinding[] memberTypes;
+
+       public ClassScope scope;
+
+       // Synthetics are separated into 4 categories: methods, super methods, fields, class literals and changed declaring type bindings
+       public final static int METHOD_EMUL = 0;
+       public final static int FIELD_EMUL = 1;
+       public final static int CLASS_LITERAL_EMUL = 2;
+       public final static int RECEIVER_TYPE_EMUL = 3;
+       
+       Hashtable[] synthetics;
+       
+public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
+       this.compoundName = compoundName;
+       this.fPackage = fPackage;
+       this.fileName = scope.referenceCompilationUnit().getFileName();
+       this.modifiers = scope.referenceContext.modifiers;
+       this.sourceName = scope.referenceContext.name;
+       this.scope = scope;
+
+       // expect the fields & methods to be initialized correctly later
+       this.fields = NoFields;
+       this.methods = NoMethods;
+
+       computeId();
+}
+private void addDefaultAbstractMethod(MethodBinding abstractMethod) {
+       MethodBinding defaultAbstract = new MethodBinding(
+               abstractMethod.modifiers | AccDefaultAbstract,
+               abstractMethod.selector,
+               abstractMethod.returnType,
+               abstractMethod.parameters,
+               abstractMethod.thrownExceptions,
+               this);
+
+       MethodBinding[] temp = new MethodBinding[methods.length + 1];
+       System.arraycopy(methods, 0, temp, 0, methods.length);
+       temp[methods.length] = defaultAbstract;
+       methods = temp;
+}
+public void addDefaultAbstractMethods() {
+       if ((tagBits & KnowsDefaultAbstractMethods) != 0) return;
+
+       tagBits |= KnowsDefaultAbstractMethods;
+
+       if (isClass() && isAbstract()) {
+               if (fPackage.environment.options.targetJDK >= ClassFileConstants.JDK1_2) return; // no longer added for post 1.2 targets
+
+               ReferenceBinding[][] interfacesToVisit = new ReferenceBinding[5][];
+               int lastPosition = 0;
+               interfacesToVisit[lastPosition] = superInterfaces();
+
+               for (int i = 0; i <= lastPosition; i++) {
+                       ReferenceBinding[] interfaces = interfacesToVisit[i];
+                       for (int j = 0, length = interfaces.length; j < length; j++) {
+                               ReferenceBinding superType = interfaces[j];
+                               if (superType.isValidBinding()) {
+                                       MethodBinding[] superMethods = superType.methods();
+                                       for (int m = superMethods.length; --m >= 0;) {
+                                               MethodBinding method = superMethods[m];
+                                               if (!implementsMethod(method))
+                                                       addDefaultAbstractMethod(method);
+                                       }
+
+                                       ReferenceBinding[] itsInterfaces = superType.superInterfaces();
+                                       if (itsInterfaces != NoSuperInterfaces) {
+                                               if (++lastPosition == interfacesToVisit.length)
+                                                       System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[lastPosition * 2][], 0, lastPosition);
+                                               interfacesToVisit[lastPosition] = itsInterfaces;
+                                       }
+                               }
+                       }
+               }
+       }
+}
+/* Add a new synthetic field for <actualOuterLocalVariable>.
+*      Answer the new field or the existing field if one already existed.
+*/
+
+public FieldBinding addSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
+       if (synthetics == null) {
+               synthetics = new Hashtable[4];
+       }
+       if (synthetics[FIELD_EMUL] == null) {
+               synthetics[FIELD_EMUL] = new Hashtable(5);
+       }
+       
+       FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
+       if (synthField == null) {
+               synthField = new SyntheticFieldBinding(
+                       CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name), 
+                       actualOuterLocalVariable.type, 
+                       AccPrivate | AccFinal | AccSynthetic, 
+                       this, 
+                       Constant.NotAConstant,
+                       synthetics[FIELD_EMUL].size());
+               synthetics[FIELD_EMUL].put(actualOuterLocalVariable, synthField);
+       }
+
+       // ensure there is not already such a field defined by the user
+       boolean needRecheck;
+       int index = 1;
+       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(
+                                               SyntheticArgumentBinding.OuterLocalPrefix,
+                                               actualOuterLocalVariable.name,
+                                               ("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
+                                       needRecheck = true;
+                                       break;
+                               }
+                       }
+               }
+       } while (needRecheck);
+       return synthField;
+}
+/* Add a new synthetic field for <enclosingType>.
+*      Answer the new field or the existing field if one already existed.
+*/
+
+public FieldBinding addSyntheticField(ReferenceBinding enclosingType) {
+
+       if (synthetics == null) {
+               synthetics = new Hashtable[4];
+       }
+       if (synthetics[FIELD_EMUL] == null) {
+               synthetics[FIELD_EMUL] = new Hashtable(5);
+       }
+
+       FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get(enclosingType);
+       if (synthField == null) {
+               synthField = new SyntheticFieldBinding(
+                       CharOperation.concat(
+                               SyntheticArgumentBinding.EnclosingInstancePrefix,
+                               String.valueOf(enclosingType.depth()).toCharArray()),
+                       enclosingType,
+                       AccDefault | AccFinal | AccSynthetic,
+                       this,
+                       Constant.NotAConstant,
+                       synthetics[FIELD_EMUL].size());
+               synthetics[FIELD_EMUL].put(enclosingType, synthField);
+       }
+       // ensure there is not already such a field defined by the user
+       FieldBinding existingField;
+       if ((existingField = this.getField(synthField.name, 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) {
+                               scope.problemReporter().duplicateFieldInType(this, fieldDecl);
+                               break;
+                       }
+               }
+       }               
+       return synthField;
+}
+/* Add a new synthetic field for a class literal access.
+*      Answer the new field or the existing field if one already existed.
+*/
+
+public FieldBinding addSyntheticField(TypeBinding targetType, BlockScope blockScope) {
+
+       if (synthetics == null) {
+               synthetics = new Hashtable[4];
+       }
+       if (synthetics[CLASS_LITERAL_EMUL] == null) {
+               synthetics[CLASS_LITERAL_EMUL] = new Hashtable(5);
+       }
+
+       // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
+       FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL_EMUL].get(targetType);
+       if (synthField == null) {
+               synthField = new SyntheticFieldBinding(
+                       ("class$" + synthetics[CLASS_LITERAL_EMUL].size()).toCharArray(), //$NON-NLS-1$
+                       blockScope.getJavaLangClass(),
+                       AccDefault | AccStatic | AccSynthetic,
+                       this,
+                       Constant.NotAConstant,
+                       synthetics[CLASS_LITERAL_EMUL].size());
+               synthetics[CLASS_LITERAL_EMUL].put(targetType, synthField);
+       }
+       // ensure there is not already such a field defined by the user
+       FieldBinding existingField;
+       if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
+               TypeDeclaration typeDecl = blockScope.referenceType();
+               for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
+                       FieldDeclaration fieldDecl = typeDecl.fields[i];
+                       if (fieldDecl.binding == existingField) {
+                               blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
+                               break;
+                       }
+               }
+       }               
+       return synthField;
+}
+
+/* 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) {
+
+       if (synthetics == null) {
+               synthetics = new Hashtable[4];
+       }
+       if (synthetics[FIELD_EMUL] == null) {
+               synthetics[FIELD_EMUL] = new Hashtable(5);
+       }
+
+       FieldBinding synthField = (FieldBinding) synthetics[FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
+       if (synthField == null) {
+               synthField = new SyntheticFieldBinding(
+                       "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
+                       BooleanBinding,
+                       AccDefault | AccStatic | AccSynthetic | AccFinal,
+                       this,
+                       Constant.NotAConstant,
+                       synthetics[FIELD_EMUL].size());
+               synthetics[FIELD_EMUL].put("assertionEmulation", synthField); //$NON-NLS-1$
+       }
+       // ensure there is not already such a field defined by the user
+       // ensure there is not already such a field defined by the user
+       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(
+                                               "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
+                                               ("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
+                                       needRecheck = true;
+                                       break;
+                               }
+                       }
+               }
+       } while (needRecheck);
+       return synthField;
+}
+
+/* Add a new synthetic access method for read/write access to <targetField>.
+       Answer the new method or the existing method if one already existed.
+*/
+
+public SyntheticAccessMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
+
+       if (synthetics == null) {
+               synthetics = new Hashtable[4];
+       }
+       if (synthetics[METHOD_EMUL] == null) {
+               synthetics[METHOD_EMUL] = new Hashtable(5);
+       }
+
+       SyntheticAccessMethodBinding accessMethod = null;
+       SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetField);
+       if (accessors == null) {
+               accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
+               synthetics[METHOD_EMUL].put(targetField, accessors = new SyntheticAccessMethodBinding[2]);
+               accessors[isReadAccess ? 0 : 1] = accessMethod;         
+       } else {
+               if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
+                       accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
+                       accessors[isReadAccess ? 0 : 1] = 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) {
+
+       if (synthetics == null) {
+               synthetics = new Hashtable[4];
+       }
+       if (synthetics[METHOD_EMUL] == null) {
+               synthetics[METHOD_EMUL] = new Hashtable(5);
+       }
+
+       SyntheticAccessMethodBinding accessMethod = null;
+       SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD_EMUL].get(targetMethod);
+       if (accessors == null) {
+               accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
+               synthetics[METHOD_EMUL].put(targetMethod, accessors = new SyntheticAccessMethodBinding[2]);
+               accessors[isSuperAccess ? 0 : 1] = accessMethod;                
+       } else {
+               if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
+                       accessMethod = new SyntheticAccessMethodBinding(targetMethod, isSuperAccess, this);
+                       accessors[isSuperAccess ? 0 : 1] = accessMethod;
+               }
+       }
+       return accessMethod;
+}
+
+public FieldBinding[] availableFields() {
+       return fields();
+}
+public MethodBinding[] availableMethods() {
+       return methods();
+}
+void faultInTypesForFieldsAndMethods() {
+       fields();
+       methods();
+
+       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
+
+public FieldBinding[] fields() {
+       
+       try {
+               int failed = 0;
+               for (int f = 0, max = fields.length; f < max; f++) {
+                       if (resolveTypeFor(fields[f]) == null) {
+                               fields[f] = null;
+                               failed++;
+                       }
+               }
+               if (failed > 0) {
+                       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++)
+                               if (fields[i] != null)
+                                       newFields[n++] = 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;
+}
+public MethodBinding[] getDefaultAbstractMethods() {
+       int count = 0;
+       for (int i = methods.length; --i >= 0;)
+               if (methods[i].isDefaultAbstract())
+                       count++;
+       if (count == 0) return NoMethods;
+
+       MethodBinding[] result = new MethodBinding[count];
+       count = 0;
+       for (int i = methods.length; --i >= 0;)
+               if (methods[i].isDefaultAbstract())
+                       result[count++] = methods[i];
+       return result;
+}
+// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
+
+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 == ConstructorDeclaration.ConstantPoolName && 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(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
+               nextConstructor : for (int c = constructors.length; --c >= 0;) {
+                       MethodBinding constructor = constructors[c];
+                       TypeBinding[] toMatch = constructor.parameters;
+                       if (toMatch.length == argCount) {
+                               for (int p = 0; p < argCount; p++)
+                                       if (toMatch[p] != argumentTypes[p])
+                                               continue nextConstructor;
+                               return constructor;
+                       }
+               }
+       }
+       return null;
+}
+// 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) {
+       int argCount = argumentTypes.length;
+       int selectorLength = selector.length;
+       boolean foundNothing = true;
+
+       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;
+                                       return 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;
+                               return method;
+                       }
+               }
+       }
+
+       if (foundNothing) {
+               if (isInterface()) {
+                        if (superInterfaces.length == 1)
+                               return superInterfaces[0].getExactMethod(selector, argumentTypes);
+               } else if (superclass != null) {
+                       return superclass.getExactMethod(selector, argumentTypes);
+               }
+       }
+       return null;
+}
+// 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];
+               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;
+                       }
+                       return null;
+               }
+       }
+       return null;
+}
+// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
+
+public MethodBinding[] getMethods(char[] selector) {
+       // handle forward references to potential default abstract methods
+       addDefaultAbstractMethods();
+
+       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;
+                       }
+                       return result;
+               }
+       } catch(AbortCompilation e){
+               // ensure null methods are removed
+               MethodBinding[] newMethods = null;
+               int count = 0;
+               for (int i = 0, max = methods.length; i < max; i++){
+                       MethodBinding method = methods[i];
+                       if (method == null && newMethods == null){
+                               System.arraycopy(methods, 0, newMethods = new MethodBinding[max], 0, i);
+                       } else if (newMethods != null && method != null) {
+                               newMethods[count++] = method;
+                       }
+               }
+               if (newMethods != null){
+                       System.arraycopy(newMethods, 0, methods = new MethodBinding[count], 0, count);
+               }                       
+               modifiers ^= AccUnresolved;
+               throw e;
+       }               
+       return NoMethods;
+}
+/* Answer the synthetic field for <actualOuterLocalVariable>
+*      or null if one does not exist.
+*/
+
+public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
+       
+       if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
+       return (FieldBinding) synthetics[FIELD_EMUL].get(actualOuterLocalVariable);
+}
+public ReferenceBinding[] memberTypes() {
+       return this.memberTypes;
+}
+public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
+
+       if (this.synthetics == null) {
+               this.synthetics = new Hashtable[4];
+       }
+       if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
+               this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
+       }
+
+       Hashtable fieldMap = (Hashtable) this.synthetics[RECEIVER_TYPE_EMUL].get(targetField);
+       if (fieldMap == null) {
+               fieldMap = new Hashtable(5);
+               this.synthetics[RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
+       }
+       FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
+       if (updatedField == null){
+               updatedField = new FieldBinding(targetField, newDeclaringClass);
+               fieldMap.put(newDeclaringClass, updatedField);
+       }
+       return updatedField;
+}
+
+public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
+
+       if (this.synthetics == null) {
+               this.synthetics = new Hashtable[4];
+       }
+       if (this.synthetics[RECEIVER_TYPE_EMUL] == null) {
+               this.synthetics[RECEIVER_TYPE_EMUL] = new Hashtable(5);
+       }
+
+
+       Hashtable methodMap = (Hashtable) synthetics[RECEIVER_TYPE_EMUL].get(targetMethod);
+       if (methodMap == null) {
+               methodMap = new Hashtable(5);
+               this.synthetics[RECEIVER_TYPE_EMUL].put(targetMethod, methodMap);
+       }
+       MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
+       if (updatedMethod == null){
+               updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
+               methodMap.put(newDeclaringClass, updatedMethod);
+       }
+       return updatedMethod;
+}
+public boolean hasMemberTypes() {
+    return this.memberTypes.length > 0;
+}
+// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
+public MethodBinding[] methods() {
+       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
+                               failed++;
+                       }
+               }
+       
+               for (int m = methods.length; --m >= 0;) {
+                       MethodBinding method = methods[m];
+                       if (method != null) {
+                               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) {
+                               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];
+                               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;
+       return methods;
+}
+private FieldBinding resolveTypeFor(FieldBinding field) {
+       if ((field.modifiers & AccUnresolved) == 0)
+               return field;
+
+       FieldDeclaration[] fieldDecls = scope.referenceContext.fields;
+       for (int f = 0, length = fieldDecls.length; f < length; f++) {
+               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;
+               }
+               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();
+       TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
+       if (exceptionTypes != null) {
+               int size = exceptionTypes.length;
+               method.thrownExceptions = new ReferenceBinding[size];
+               ReferenceBinding throwable = scope.getJavaLangThrowable();
+               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);
+                               continue;
+                       }
+                       if (throwable != resolvedExceptionType && !throwable.isSuperclassOf(resolvedExceptionType)) {
+                               methodDecl.scope.problemReporter().cannotThrowType(this, methodDecl, exceptionTypes[i], resolvedExceptionType);
+                               continue;
+                       }
+                       method.thrownExceptions[count++] = resolvedExceptionType;
+               }
+               if (count < size)
+                       System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
+       }
+
+       boolean foundArgProblem = false;
+       Argument[] arguments = methodDecl.arguments;
+       if (arguments != null) {
+               int size = arguments.length;
+               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]);
+                               foundArgProblem = true;
+                       } else if (method.parameters[i] == VoidBinding) {
+                               methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
+                               foundArgProblem = true;
+                       } else if (method.parameters[i].isArrayType() && ((ArrayBinding) method.parameters[i]).leafComponentType == VoidBinding) {
+                               methodDecl.scope.problemReporter().argumentTypeCannotBeVoidArray(this, methodDecl, arg);
+                               foundArgProblem = true;
+                       }
+               }
+       }
+
+       boolean foundReturnTypeProblem = false;
+       if (!method.isConstructor()) {
+               TypeReference returnType = ((MethodDeclaration) 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;
+                               foundReturnTypeProblem = true;
+                       } else if (method.returnType.isArrayType() && ((ArrayBinding) method.returnType).leafComponentType == VoidBinding) {
+                               methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray(this, (MethodDeclaration) methodDecl);
+                               method.returnType = null;
+                               foundReturnTypeProblem = true;
+                       }
+               }
+       }
+       if (foundArgProblem) {
+               methodDecl.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;
+       return method;
+}
+public final int sourceEnd() {
+       return scope.referenceContext.sourceEnd;
+}
+public final int sourceStart() {
+       return scope.referenceContext.sourceStart;
+}
+public ReferenceBinding superclass() {
+       return superclass;
+}
+public ReferenceBinding[] superInterfaces() {
+       return superInterfaces;
+}
+public SyntheticAccessMethodBinding[] syntheticAccessMethods() {
+       
+       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()) {
+
+               Object fieldOrMethod = fieldsOrMethods.nextElement();
+
+               if (fieldOrMethod instanceof MethodBinding) {
+
+                       SyntheticAccessMethodBinding[] methodAccessors = (SyntheticAccessMethodBinding[]) 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);
+                       if (methodAccessors[0] != null) 
+                               bindings[index++] = methodAccessors[0]; // super access 
+                       if (methodAccessors[1] != null) 
+                               bindings[index++] = methodAccessors[1]; // normal access
+
+               } else {
+
+                       SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) 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);
+                       if (fieldAccessors[0] != null) 
+                               bindings[index++] = fieldAccessors[0]; // read access
+                       if (fieldAccessors[1] != null) 
+                               bindings[index++] = fieldAccessors[1]; // write access
+               }
+       }
+
+       // sort them in according to their own indexes
+       int length;
+       SyntheticAccessMethodBinding[] sortedBindings = new SyntheticAccessMethodBinding[length = bindings.length];
+       for (int i = 0; i < length; i++){
+               SyntheticAccessMethodBinding binding = bindings[i];
+               sortedBindings[binding.index] = binding;
+       }
+       return sortedBindings;
+}
+/**
+ * Answer the collection of synthetic fields to append into the classfile
+ */
+public FieldBinding[] syntheticFields() {
+       
+       if (synthetics == null) return null;
+
+       int fieldSize = synthetics[FIELD_EMUL] == null ? 0 : synthetics[FIELD_EMUL].size();
+       int literalSize = synthetics[CLASS_LITERAL_EMUL] == null ? 0 :synthetics[CLASS_LITERAL_EMUL].size();
+       int totalSize = fieldSize + literalSize;
+       if (totalSize == 0) return null;
+       FieldBinding[] bindings = new FieldBinding[totalSize];
+
+       // add innerclass synthetics
+       if (synthetics[FIELD_EMUL] != null){
+               Enumeration elements = synthetics[FIELD_EMUL].elements();
+               for (int i = 0; i < fieldSize; i++) {
+                       SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
+                       bindings[synthBinding.index] = synthBinding;
+               }
+       }
+       // add class literal synthetics
+       if (synthetics[CLASS_LITERAL_EMUL] != null){
+               Enumeration elements = synthetics[CLASS_LITERAL_EMUL].elements();
+               for (int i = 0; i < literalSize; i++) {
+                       SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
+                       bindings[fieldSize+synthBinding.index] = synthBinding;
+               }
+       }
+       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$
+
+       if (superInterfaces != null) {
+               if (superInterfaces != NoSuperInterfaces) {
+                       s += "\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$
+                       }
+               }
+       } else {
+               s += "NULL SUPERINTERFACES"; //$NON-NLS-1$
+       }
+
+       if (enclosingType() != null) {
+               s += "\n\tenclosing type : "; //$NON-NLS-1$
+               s += enclosingType().debugName();
+       }
+
+       if (fields != null) {
+               if (fields != NoFields) {
+                       s += "\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$
+               }
+       } else {
+               s += "NULL FIELDS"; //$NON-NLS-1$
+       }
+
+       if (methods != null) {
+               if (methods != NoMethods) {
+                       s += "\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$
+               }
+       } else {
+               s += "NULL METHODS"; //$NON-NLS-1$
+       }
+
+       if (memberTypes != null) {
+               if (memberTypes != NoMemberTypes) {
+                       s += "\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$
+               }
+       } else {
+               s += "NULL MEMBER TYPES"; //$NON-NLS-1$
+       }
+
+       s += "\n\n\n"; //$NON-NLS-1$
+       return s;
+}
+void verifyMethods(MethodVerifier verifier) {
+       verifier.verify(this);
+
+       for (int i = memberTypes.length; --i >= 0;)
+                ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
+}
+
+/* Answer the synthetic field for <targetEnclosingType>
+*      or null if one does not exist.
+*/
+
+public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
+
+       if (synthetics == null || synthetics[FIELD_EMUL] == null) return null;
+       FieldBinding field = (FieldBinding) synthetics[FIELD_EMUL].get(targetEnclosingType);
+       if (field != null) return field;
+
+       // type compatibility : to handle cases such as
+       // class T { class M{}}
+       // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
+       if (!onlyExactMatch){
+               Enumeration accessFields = synthetics[FIELD_EMUL].elements();
+               while (accessFields.hasMoreElements()) {
+                       field = (FieldBinding) accessFields.nextElement();
+                       if (CharOperation.prefixEquals(SyntheticArgumentBinding.EnclosingInstancePrefix, field.name)
+                               && targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))
+                                       return field;
+               }
+       }
+       return null;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticAccessMethodBinding.java
new file mode 100644 (file)
index 0000000..0803da4
--- /dev/null
@@ -0,0 +1,288 @@
+/*******************************************************************************
+ * 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.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+
+public class SyntheticAccessMethodBinding 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 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 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) {
+
+               this.modifiers = AccDefault | AccStatic | AccSynthetic;
+               SourceTypeBinding declaringSourceType = (SourceTypeBinding) declaringClass;
+               SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
+               int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+               this.index = methodId;
+               this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
+               if (isReadAccess) {
+                       this.returnType = targetField.type;
+                       if (targetField.isStatic()) {
+                               this.parameters = NoParameters;
+                       } else {
+                               this.parameters = new TypeBinding[1];
+                               this.parameters[0] = declaringSourceType;
+                       }
+                       this.targetReadField = targetField;
+                       this.accessType = FieldReadAccess;
+               } else {
+                       this.returnType = VoidBinding;
+                       if (targetField.isStatic()) {
+                               this.parameters = new TypeBinding[1];
+                               this.parameters[0] = targetField.type;
+                       } else {
+                               this.parameters = new TypeBinding[2];
+                               this.parameters[0] = declaringSourceType;
+                               this.parameters[1] = targetField.type;
+                       }
+                       this.targetWriteField = targetField;
+                       this.accessType = FieldWriteAccess;
+               }
+               this.thrownExceptions = NoExceptions;
+               this.declaringClass = declaringSourceType;
+       
+               // check for method collision
+               boolean needRename;
+               do {
+                       check : {
+                               needRename = false;
+                               // check for collision with known methods
+                               MethodBinding[] methods = declaringSourceType.methods;
+                               for (int i = 0, length = methods.length; i < length; i++) {
+                                       if (CharOperation.equals(this.selector, methods[i].selector) && this.areParametersEqual(methods[i])) {
+                                               needRename = true;
+                                               break check;
+                                       }
+                               }
+                               // check for collision with synthetic accessors
+                               if (knownAccessMethods != null) {
+                                       for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
+                                               if (knownAccessMethods[i] == null) continue;
+                                               if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(methods[i])) {
+                                                       needRename = true;
+                                                       break check;
+                                               }
+                                       }
+                               }
+                       }
+                       if (needRename) { // retry with a selector postfixed by a growing methodId
+                               this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+                       }
+               } while (needRename);
+       
+               // retrieve sourceStart position for the target field for line number attributes
+               FieldDeclaration[] fieldDecls = declaringSourceType.scope.referenceContext.fields;
+               if (fieldDecls != null) {
+                       for (int i = 0, max = fieldDecls.length; i < max; i++) {
+                               if (fieldDecls[i].binding == targetField) {
+                                       this.sourceStart = fieldDecls[i].sourceStart;
+                                       return;
+                               }
+                       }
+               }
+       
+       /* did not find the target field declaration - it is a synthetic one
+               public class A {
+                       public class B {
+                               public class C {
+                                       void foo() {
+                                               System.out.println("A.this = " + A.this);
+                                       }
+                               }
+                       }
+                       public static void main(String args[]) {
+                               new A().new B().new C().foo();
+                       }
+               }       
+       */
+               // We now at this point - per construction - it is for sure an enclosing instance, we are going to
+               // show the target field type declaration location.
+               this.sourceStart = declaringSourceType.scope.referenceContext.sourceStart; // use the target declaring class name position instead
+       }
+
+       public SyntheticAccessMethodBinding(MethodBinding targetMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
+       
+               if (targetMethod.isConstructor()) {
+                       this.initializeConstructorAccessor(targetMethod);
+               } else {
+                       this.initializeMethodAccessor(targetMethod, isSuperAccess, receiverType);
+               }
+       }
+
+       /**
+        * An constructor accessor is a constructor with an extra argument (declaringClass), in case of
+        * collision with an existing constructor, then add again an extra argument (declaringClass again).
+        */
+        public void initializeConstructorAccessor(MethodBinding accessedConstructor) {
+       
+               this.targetMethod = accessedConstructor;
+               this.modifiers = AccDefault | AccSynthetic;
+               SourceTypeBinding sourceType = (SourceTypeBinding) accessedConstructor.declaringClass; 
+               SyntheticAccessMethodBinding[] knownAccessMethods = 
+                       sourceType.syntheticAccessMethods(); 
+               this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+       
+               this.selector = accessedConstructor.selector;
+               this.returnType = accessedConstructor.returnType;
+               this.accessType = ConstructorAccess;
+               this.parameters = new TypeBinding[accessedConstructor.parameters.length + 1];
+               System.arraycopy(
+                       accessedConstructor.parameters, 
+                       0, 
+                       this.parameters, 
+                       0, 
+                       accessedConstructor.parameters.length); 
+               parameters[accessedConstructor.parameters.length] = 
+                       accessedConstructor.declaringClass; 
+               this.thrownExceptions = accessedConstructor.thrownExceptions;
+               this.declaringClass = sourceType;
+       
+               // check for method collision
+               boolean needRename;
+               do {
+                       check : {
+                               needRename = false;
+                               // check for collision with known methods
+                               MethodBinding[] methods = sourceType.methods;
+                               for (int i = 0, length = methods.length; i < length; i++) {
+                                       if (CharOperation.equals(this.selector, methods[i].selector)
+                                               && this.areParametersEqual(methods[i])) {
+                                               needRename = true;
+                                               break check;
+                                       }
+                               }
+                               // check for collision with synthetic accessors
+                               if (knownAccessMethods != null) {
+                                       for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
+                                               if (knownAccessMethods[i] == null)
+                                                       continue;
+                                               if (CharOperation.equals(this.selector, knownAccessMethods[i].selector)
+                                                       && this.areParametersEqual(knownAccessMethods[i])) {
+                                                       needRename = true;
+                                                       break check;
+                                               }
+                                       }
+                               }
+                       }
+                       if (needRename) { // retry with a new extra argument
+                               int length = this.parameters.length;
+                               System.arraycopy(
+                                       this.parameters, 
+                                       0, 
+                                       this.parameters = new TypeBinding[length + 1], 
+                                       0, 
+                                       length); 
+                               this.parameters[length] = this.declaringClass;
+                       }
+               } while (needRename);
+       
+               // retrieve sourceStart position for the target method for line number attributes
+               AbstractMethodDeclaration[] methodDecls = 
+                       sourceType.scope.referenceContext.methods; 
+               if (methodDecls != null) {
+                       for (int i = 0, length = methodDecls.length; i < length; i++) {
+                               if (methodDecls[i].binding == accessedConstructor) {
+                                       this.sourceStart = methodDecls[i].sourceStart;
+                                       return;
+                               }
+                       }
+               }
+       }
+
+       /**
+        * An method accessor is a method with an access$N selector, where N is incremented in case of collisions.
+        */
+       public void initializeMethodAccessor(MethodBinding accessedMethod, boolean isSuperAccess, ReferenceBinding receiverType) {
+               
+               this.targetMethod = accessedMethod;
+               this.modifiers = AccDefault | AccStatic | AccSynthetic;
+               SourceTypeBinding declaringSourceType = (SourceTypeBinding) receiverType;
+               SyntheticAccessMethodBinding[] knownAccessMethods = declaringSourceType.syntheticAccessMethods();
+               int methodId = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+               this.index = methodId;
+       
+               this.selector = CharOperation.concat(AccessMethodPrefix, String.valueOf(methodId).toCharArray());
+               this.returnType = accessedMethod.returnType;
+               this.accessType = isSuperAccess ? SuperMethodAccess : MethodAccess;
+               
+               if (accessedMethod.isStatic()) {
+                       this.parameters = accessedMethod.parameters;
+               } else {
+                       this.parameters = new TypeBinding[accessedMethod.parameters.length + 1];
+                       this.parameters[0] = declaringSourceType;
+                       System.arraycopy(accessedMethod.parameters, 0, this.parameters, 1, accessedMethod.parameters.length);
+               }
+               this.thrownExceptions = accessedMethod.thrownExceptions;
+               this.declaringClass = declaringSourceType;
+       
+               // check for method collision
+               boolean needRename;
+               do {
+                       check : {
+                               needRename = false;
+                               // check for collision with known methods
+                               MethodBinding[] methods = declaringSourceType.methods;
+                               for (int i = 0, length = methods.length; i < length; i++) {
+                                       if (CharOperation.equals(this.selector, methods[i].selector) && this.areParametersEqual(methods[i])) {
+                                               needRename = true;
+                                               break check;
+                                       }
+                               }
+                               // check for collision with synthetic accessors
+                               if (knownAccessMethods != null) {
+                                       for (int i = 0, length = knownAccessMethods.length; i < length; i++) {
+                                               if (knownAccessMethods[i] == null) continue;
+                                               if (CharOperation.equals(this.selector, knownAccessMethods[i].selector) && this.areParametersEqual(knownAccessMethods[i])) {
+                                                       needRename = true;
+                                                       break check;
+                                               }
+                                       }
+                               }
+                       }
+                       if (needRename) { // retry with a selector & a growing methodId
+                               this.setSelector(CharOperation.concat(AccessMethodPrefix, String.valueOf(++methodId).toCharArray()));
+                       }
+               } while (needRename);
+       
+               // retrieve sourceStart position for the target method for line number attributes
+               AbstractMethodDeclaration[] methodDecls = declaringSourceType.scope.referenceContext.methods;
+               if (methodDecls != null) {
+                       for (int i = 0, length = methodDecls.length; i < length; i++) {
+                               if (methodDecls[i].binding == accessedMethod) {
+                                       this.sourceStart = methodDecls[i].sourceStart;
+                                       return;
+                               }
+                       }
+               }
+       }
+
+       protected boolean isConstructorRelated() {
+               return accessType == ConstructorAccess;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticArgumentBinding.java
new file mode 100644 (file)
index 0000000..521c6ea
--- /dev/null
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Specific local variable location used to:
+ * - either provide emulation for outer local variables used from within innerclass constructs,
+ * - or provide emulation to enclosing instances. 
+ * When it is mapping to an outer local variable, this actual outer local is accessible through 
+ * the public field #actualOuterLocalVariable.
+ *
+ * Such a synthetic argument binding will be inserted in all constructors of local innertypes before
+ * the user arguments.
+ */
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+public class SyntheticArgumentBinding extends LocalVariableBinding {
+
+       {       
+               this.isArgument = true;
+               this.useFlag = USED;
+       }
+       
+       // if the argument is mapping to an outer local variable, this denotes the outer actual variable
+       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), 
+                       actualOuterLocalVariable.type, 
+                       AccFinal,
+                       true);
+               this.actualOuterLocalVariable = actualOuterLocalVariable;
+       }
+
+       public SyntheticArgumentBinding(ReferenceBinding enclosingType) {
+
+               super(
+                       CharOperation.concat(
+                               SyntheticArgumentBinding.EnclosingInstancePrefix,
+                               String.valueOf(enclosingType.depth()).toCharArray()),
+                       enclosingType, 
+                       AccFinal,
+                       true);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticFieldBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/SyntheticFieldBinding.java
new file mode 100644 (file)
index 0000000..ca40bca
--- /dev/null
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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;
+
+public class SyntheticFieldBinding extends FieldBinding {
+       public int index;
+public SyntheticFieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant, int index) {
+       super(name, type, modifiers, declaringClass, constant);
+       this.index = index;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
new file mode 100644 (file)
index 0000000..556a7c4
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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;
+
+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;
+
+       // test bit to see if default abstract methods were computed
+       final int KnowsDefaultAbstractMethods = 0x0400;
+
+       // Reusable bit currently used by Scopes
+       final int InterfaceVisited = 0x0800;
+
+       // test bits to see if parts of binary types are faulted
+       final int AreFieldsComplete = 0x1000;
+       final int AreMethodsComplete = 0x2000;
+
+       // test bit to avoid asking a type for a member type (includes inherited member types)
+       final int HasNoMemberTypes = 0x4000;
+
+       // test bit to identify if the type's hierarchy is inconsistent
+       final int HierarchyHasProblems = 0x8000;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
new file mode 100644 (file)
index 0000000..c6cd627
--- /dev/null
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * 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;
+
+/*
+ * Not all fields defined by this type (& its subclasses) are initialized when it is created.
+ * Some are initialized only when needed.
+ *
+ * Accessors have been provided for some public fields so all TypeBindings have the same API...
+ * but access public fields directly whenever possible.
+ * Non-public fields have accessors which should be used everywhere you expect the field to be initialized.
+ *
+ * null is NOT a valid value for a non-public field... it just means the field is not initialized.
+ */
+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
+/* API
+ * Answer the receiver's binding type from Binding.BindingID.
+ */
+
+public final int bindingType() {
+       return TYPE;
+}
+/* Answer true if the receiver can be instantiated
+ */
+public boolean canBeInstantiated() {
+       return !isBaseType();
+}
+/**
+ *  Answer the receiver's constant pool name.
+ *  NOTE: This method should only be used during/after code gen.
+ *  e.g. 'java/lang/Object' 
+ */
+public abstract char[] constantPoolName();
+
+String debugName() {
+       return new String(readableName());
+}
+/*
+ * Answer the receiver's dimensions - 0 for non-array types
+ */
+public int dimensions(){
+       return 0;
+}
+public abstract PackageBinding getPackage();
+/* 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;
+}
+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);
+/* 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 isNumericType() {
+       switch (id) {
+               case T_int :
+               case T_float :
+               case T_double :
+               case T_short :
+               case T_byte :
+               case T_long :
+               case T_char :
+                       return true;
+               default :
+                       return false;
+       }
+}
+
+public TypeBinding leafComponentType(){
+       return this;
+}
+
+/**
+ * Answer the qualified name of the receiver's package separated by periods
+ * or an empty string if its the default package.
+ *
+ * For example, {java.util.Hashtable}.
+ */
+
+public char[] qualifiedPackageName() {
+       PackageBinding packageBinding = getPackage();
+       return packageBinding == null  || packageBinding.compoundName == CharOperation.NO_CHAR_CHAR
+               ? CharOperation.NO_CHAR
+               : packageBinding.readableName();
+}
+/**
+* Answer the source name for the type.
+* In the case of member types, as the qualified name from its top level type.
+* For example, for a member type N defined inside M & A: "A.M.N".
+*/
+
+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.
+*/
+
+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;
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
new file mode 100644 (file)
index 0000000..5f6064f
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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;
+
+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$
+       
+       
+       // 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$
+
+       // Constants used by the flow analysis
+       final int EqualOrMoreSpecific = -1;
+       final int NotRelated = 0;
+       final 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];
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
new file mode 100644 (file)
index 0000000..5fe8af0
--- /dev/null
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * 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;
+
+public interface TypeIds {
+       //base type void null undefined Object String
+       //should have an id that is 0<= id <= 15
+
+       final int T_undefined = 0; // should not be changed
+       final int T_Object = 1;
+       final int T_char = 2;
+       final int T_byte = 3;
+       final int T_short = 4;
+       final int T_boolean = 5;
+       final int T_void = 6;
+       final int T_long = 7;
+       final int T_double = 8;
+       final int T_float = 9;
+       final int T_int = 10;
+       final int T_String = 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;
+       final int T_JavaLangSystem = 18;
+       final int T_JavaLangError = 19;
+       final int T_JavaLangReflectConstructor = 20;
+       final int T_JavaLangThrowable = 21;
+       final int T_JavaLangNoClassDefError = 22;
+       final int T_JavaLangClassNotFoundException = 23;
+       final int T_JavaIoPrintStream = 24;
+       final int T_JavaLangException = 25;
+
+       // wrapper types
+       final int T_JavaLangByte = 26;
+       final int T_JavaLangShort = 27;
+       final int T_JavaLangCharacter = 28;
+       final int T_JavaLangInteger = 29;
+       final int T_JavaLangLong = 30;
+       final int T_JavaLangFloat = 31;
+       final int T_JavaLangDouble = 32;
+       final int T_JavaLangBoolean = 33;
+       final int T_JavaLangVoid = 34;
+
+       // 1.4 feature
+       final int T_JavaLangAssertionError = 35;
+
+       // array interfaces
+       final int T_JavaLangCloneable = 36;
+       final int T_JavaIoSerializable = 37;
+       
+       final int NoId = Integer.MAX_VALUE;
+
+       // 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 Boolean2Boolean = T_boolean + (T_boolean << 4);
+       final int Byte2Byte = T_byte + (T_byte << 4);
+       final int Byte2Short = T_byte + (T_short << 4);
+       final int Byte2Char = T_byte + (T_char << 4);
+       final int Byte2Int = T_byte + (T_int << 4);
+       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 Short2Byte = T_short + (T_byte << 4);
+       final int Short2Short = T_short + (T_short << 4);
+       final int Short2Char = T_short + (T_char << 4);
+       final int Short2Int = T_short + (T_int << 4);
+       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 Char2Byte = T_char + (T_byte << 4);
+       final int Char2Short = T_char + (T_short << 4);
+       final int Char2Char = T_char + (T_char << 4);
+       final int Char2Int = T_char + (T_int << 4);
+       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 Int2Byte = T_int + (T_byte << 4);
+       final int Int2Short = T_int + (T_short << 4);
+       final int Int2Char = T_int + (T_char << 4);
+       final int Int2Int = T_int + (T_int << 4);
+       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 Long2Byte = T_long + (T_byte << 4);
+       final int Long2Short = T_long + (T_short << 4);
+       final int Long2Char = T_long + (T_char << 4);
+       final int Long2Int = T_long + (T_int << 4);
+       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 Float2Byte = T_float + (T_byte << 4);
+       final int Float2Short = T_float + (T_short << 4);
+       final int Float2Char = T_float + (T_char << 4);
+       final int Float2Int = T_float + (T_int << 4);
+       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 Double2Byte = T_double + (T_byte << 4);
+       final int Double2Short = T_double + (T_short << 4);
+       final int Double2Char = T_double + (T_char << 4);
+       final int Double2Int = T_double + (T_int << 4);
+       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);
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
new file mode 100644 (file)
index 0000000..65ff088
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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 UnresolvedReferenceBinding extends ReferenceBinding {
+       ReferenceBinding resolvedType;
+UnresolvedReferenceBinding(char[][] compoundName, PackageBinding packageBinding) {
+       this.compoundName = compoundName;
+       this.sourceName = compoundName[compoundName.length - 1]; // reasonable guess
+       this.fPackage = packageBinding;
+}
+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
+       }
+
+       environment.problemReporter.isClassPathCorrect(compoundName, null);
+       return null; // will not get here since the above error aborts the compilation
+}
+public String toString() {
+       return "Unresolved type " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/UpdatedMethodBinding.java
new file mode 100644 (file)
index 0000000..485c159
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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;
+
+public class UpdatedMethodBinding extends MethodBinding {
+       
+       public TypeBinding updatedDeclaringClass;
+
+       public UpdatedMethodBinding(TypeBinding updatedDeclaringClass, int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] args, ReferenceBinding[] exceptions, ReferenceBinding declaringClass) {
+               super(modifiers, selector, returnType, args, exceptions, declaringClass);
+               this.updatedDeclaringClass = updatedDeclaringClass;
+       }
+       
+       public TypeBinding constantPoolDeclaringClass() {
+               return this.updatedDeclaringClass;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/src/java/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
new file mode 100644 (file)
index 0000000..2e06558
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.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;
+       public int id; // for flow-analysis (position in flowInfo bit vector)
+
+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;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java b/src/java/org/eclipse/jdt/internal/compiler/parser/AbstractCommentParser.java
new file mode 100644 (file)
index 0000000..ca99505
--- /dev/null
@@ -0,0 +1,1402 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+
+/**
+ * Parser specialized for decoding javadoc comments
+ */
+public abstract class AbstractCommentParser {
+
+       // recognized tags
+       public static final char[] TAG_DEPRECATED = "deprecated".toCharArray(); //$NON-NLS-1$
+       public static final char[] TAG_PARAM = "param".toCharArray(); //$NON-NLS-1$
+       public static final char[] TAG_RETURN = "return".toCharArray(); //$NON-NLS-1$
+       public static final char[] TAG_THROWS = "throws".toCharArray(); //$NON-NLS-1$
+       public static final char[] TAG_EXCEPTION = "exception".toCharArray(); //$NON-NLS-1$
+       public static final char[] TAG_SEE = "see".toCharArray(); //$NON-NLS-1$
+       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$
+       
+       // tags expected positions
+       public final static int ORDERED_TAGS_NUMBER = 3;
+       public final static int PARAM_TAG_EXPECTED_ORDER = 0;
+       public final static int THROWS_TAG_EXPECTED_ORDER = 1;
+       public final static int SEE_TAG_EXPECTED_ORDER = 2;
+       
+       // Kind of comment parser
+       public final static int COMPIL_PARSER = 0x00000001;
+       public final static int DOM_PARSER = 0x00000002;
+       
+       // Public fields
+       public Scanner scanner;
+       public boolean checkDocComment = false;
+       
+       // Protected fields
+       protected boolean inherited, deprecated;
+       protected char[] source;
+       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;
+       
+       // Line pointers
+       private int linePtr, lastLinePtr;
+       
+       // Identifier stack
+       protected int identifierPtr;
+       protected char[][] identifierStack;
+       protected int identifierLengthPtr;
+       protected int[] identifierLengthStack;
+       protected long[] identifierPositionStack;
+       // Ast stack
+       protected static int AstStackIncrement = 10;
+       protected int astPtr;
+       protected Object[] astStack;
+       protected int astLengthPtr;
+       protected int[] astLengthStack;
+
+       protected AbstractCommentParser(Parser sourceParser) {
+               this.sourceParser = sourceParser;
+               this.scanner = new Scanner(false, false, false, ClassFileConstants.JDK1_3, null, null, true/*taskCaseSensitive*/);
+               this.identifierStack = new char[20][];
+               this.identifierPositionStack = new long[20];
+               this.identifierLengthStack = new int[10];
+               this.astStack = new Object[30];
+               this.astLengthStack = new int[20];
+       }
+
+       /* (non-Javadoc)
+        * Returns true if tag @deprecated is present in javadoc comment.
+        * 
+        * If javadoc checking is enabled, will also construct an Javadoc node, which will be stored into Parser.javadoc
+        * slot for being consumed later on.
+        */
+       protected boolean parseComment(int javadocStart, int javadocEnd) {
+
+               boolean validComment = true;
+               try {
+                       // Init scanner position
+                       this.scanner.resetTo(javadocStart, javadocEnd);
+                       this.endComment = javadocEnd;
+                       this.index = javadocStart;
+                       readChar(); // starting '/'
+                       int previousPosition = this.index;
+                       readChar(); // first '*'
+                       char nextCharacter= readChar(); // second '*'
+                       
+                       // Init local variables
+                       this.astLengthPtr = -1;
+                       this.astPtr = -1;
+                       this.currentTokenType = -1;
+                       this.inlineTagStarted = false;
+                       this.inlineTagStart = -1;
+                       this.lineStarted = false;
+                       this.returnStatement = null;
+                       this.inherited = false;
+                       this.deprecated = false;
+                       this.linePtr = getLineNumber(javadocStart);
+                       this.lastLinePtr = getLineNumber(javadocEnd);
+                       this.lineEnd = (this.linePtr == this.lastLinePtr) ? this.endComment : this.scanner.getLineEnd(this.linePtr);
+                       this.textStart = -1;
+                       char previousChar = 0;
+                       int invalidTagLineEnd = -1;
+                       int invalidInlineTagLineEnd = -1;
+                       
+                       // Loop on each comment character
+                       while (this.index < this.endComment) {
+                               previousPosition = this.index;
+                               previousChar = nextCharacter;
+                               
+                               // Calculate line end (cannot use this.scanner.linePtr as scanner does not parse line ends again)
+                               if (this.index > (this.lineEnd+1)) {
+                                       updateLineEnd();
+                               }
+                               
+                               // Read next char only if token was consumed
+                               if (this.currentTokenType < 0) {
+                                       nextCharacter = readChar(); // consider unicodes
+                               } else {
+                                       previousPosition = this.scanner.getCurrentTokenStartPosition();
+                                       switch (this.currentTokenType) {
+                                               case TerminalTokens.TokenNameRBRACE:
+                                                       nextCharacter = '}';
+                                                       break;
+                                               case TerminalTokens.TokenNameMULTIPLY:
+                                                       nextCharacter = '*';
+                                                       break;
+                                       default:
+                                                       nextCharacter = this.scanner.currentCharacter;
+                                       }
+                                       consumeToken();
+                               }
+                       
+                               if (this.index >= this.endComment) {
+                                       break;
+                               }
+                               
+                               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
+                                               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) {
+                                                                       int end = previousPosition<invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd;
+                                                                       this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
+                                                               }
+                                                               validComment = false;
+                                                               if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) {
+                                                                       pushText(this.textStart, previousPosition);
+                                                               }
+                                                               if (this.kind == DOM_PARSER) refreshInlineTagPosition(previousPosition);
+                                                       }
+                                                       if (previousChar == '{') {
+                                                               if (this.textStart != -1 && this.textStart < this.inlineTagStart) {
+                                                                       pushText(this.textStart, this.inlineTagStart);
+                                                               }
+                                                               this.inlineTagStarted = true;
+                                                               invalidInlineTagLineEnd = this.lineEnd;
+                                                       } else if (this.textStart != -1 && this.textStart < invalidTagLineEnd) {
+                                                               pushText(this.textStart, invalidTagLineEnd);
+                                                       }
+                                                       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) {
+                                                                       // 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();
+                                                                               this.textStart = this.tagSourceEnd+1;
+                                                                               invalidTagLineEnd  = this.lineEnd;
+                                                                       }
+                                                               }
+                                                       } catch (InvalidInputException e) {
+                                                               consumeToken();
+                                                       }
+                                               }
+                                               break;
+                                       case '\r':
+                                       case '\n':
+                                               if (this.lineStarted && this.textStart < previousPosition) {
+                                                       pushText(this.textStart, previousPosition);
+                                               }
+                                               this.lineStarted = false;
+                                               // Fix bug 51650
+                                               this.textStart = -1;
+                                               break;
+                                       case '}' :
+                                               if (this.inlineTagStarted) {
+                                                       if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) {
+                                                               pushText(this.textStart, previousPosition);
+                                                       }
+                                                       if (this.kind == DOM_PARSER) refreshInlineTagPosition(previousPosition);
+                                                       this.textStart = this.index;
+                                                       this.inlineTagStarted = false;
+                                               } else {
+                                                       if (!this.lineStarted) {
+                                                               this.textStart = previousPosition;
+                                                       }
+                                               }
+                                               this.lineStarted = true;
+                                               break;
+                                       case '{' :
+                                               if (this.inlineTagStarted) {
+                                                       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) {
+                                                               int end = previousPosition<invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd;
+                                                               this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
+                                                       }
+                                                       if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) {
+                                                               pushText(this.textStart, previousPosition);
+                                                       }
+                                                       if (this.kind == DOM_PARSER) refreshInlineTagPosition(previousPosition);
+                                               }
+                                               if (!this.lineStarted) {
+                                                       this.textStart = previousPosition;
+                                               }
+                                               this.lineStarted = true;
+                                               this.inlineTagStart = previousPosition;
+                                               break;
+                                       case '*' :
+                                       case '\u000c' : /* FORM FEED               */
+                                       case ' ' :                      /* SPACE                   */
+                                       case '\t' :                     /* HORIZONTAL TABULATION   */
+                                               // do nothing for space or '*' characters
+                                               break;
+                                       default :
+                                               if (!this.lineStarted) {
+                                                       this.textStart = previousPosition;
+                                               }
+                                               this.lineStarted = true;
+                                               break;
+                               }
+                       }
+                       // bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=53279
+                       // Cannot leave comment inside inline comment
+                       if (this.inlineTagStarted) {
+                               this.inlineTagStarted = false;
+                               if (this.sourceParser != null) {
+                                       int end = previousPosition<invalidInlineTagLineEnd ? previousPosition : invalidInlineTagLineEnd;
+                                       if (this.index >= this.endComment) end = invalidInlineTagLineEnd;
+                                       this.sourceParser.problemReporter().javadocUnterminatedInlineTag(this.inlineTagStart, end);
+                               }
+                               if (this.lineStarted && this.textStart != -1 && this.textStart < previousPosition) {
+                                       pushText(this.textStart, previousPosition);
+                               }
+                               if (this.kind == DOM_PARSER) {
+                                       refreshInlineTagPosition(previousPosition);
+                               }
+                       } else if (this.lineStarted && this.textStart < previousPosition) {
+                               pushText(this.textStart, previousPosition);
+                       }
+                       updateDocComment();
+               } catch (Exception ex) {
+                       validComment = false;
+               }
+               return validComment;
+       }
+
+       private void consumeToken() {
+               this.currentTokenType = -1; // flush token cache
+               updateLineEnd();
+       }
+
+       protected abstract Object createArgumentReference(char[] name, int dim, Object typeRef, long[] dimPos, long argNamePos) throws InvalidInputException;
+       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 Object createTypeReference(int primitiveToken);
+       
+       private int getEndPosition() {
+               if (this.scanner.getCurrentTokenEndPosition() > 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);
+               }
+               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.
+        * Warning: returned position is 1-based index!
+        * @see Scanner#getLineNumber(int) We cannot directly use this method
+        * when linePtr field is not initialized.
+        */
+       private int getLineNumber(int position) {
+       
+               if (this.scanner.linePtr != -1) {
+                       return this.scanner.getLineNumber(position);
+               }
+               if (this.lineEnds == null)
+                       return 1;
+               int length = this.lineEnds.length;
+               if (length == 0)
+                       return 1;
+               int g = 0, d = length - 1;
+               int m = 0;
+               while (g <= d) {
+                       m = (g + d) /2;
+                       if (position < this.lineEnds[m]) {
+                               d = m-1;
+                       } else if (position > this.lineEnds[m]) {
+                               g = m+1;
+                       } else {
+                               return m + 1;
+                       }
+               }
+               if (position < this.lineEnds[m]) {
+                       return m+1;
+               }
+               return m+2;
+       }
+
+       /*
+        * Parse argument in @see tag method reference
+        */
+       private Object parseArguments(Object receiver) throws InvalidInputException {
+
+               // Init
+               int modulo = 0; // should be 2 for (Type,Type,...) or 3 for (Type arg,Type arg,...)
+               int iToken = 0;
+               char[] argName = null;
+               List arguments = new ArrayList(10);
+               int start = this.scanner.getCurrentTokenStartPosition();
+               
+               // Parse arguments declaration if method reference
+               nextArg : while (this.index < this.scanner.eofPosition) {
+
+                       // Read argument type reference
+                       Object typeRef;
+                       try {
+                               typeRef = parseQualifiedName(false);
+                       } catch (InvalidInputException e) {
+                               break nextArg;
+                       }
+                       boolean firstArg = modulo == 0;
+                       if (firstArg) { // verify position
+                               if (iToken != 0)
+                                       break nextArg;
+                       } else if ((iToken % modulo) != 0) {
+                                       break nextArg;
+                       }
+                       if (typeRef == null) {
+                               if (firstArg && this.currentTokenType == TerminalTokens.TokenNameRPAREN) {
+                                       // verify characters after arguments declaration (expecting white space or end comment)
+                                       if (!verifySpaceOrEndComment()) {
+                                               int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
+                                               if (this.source[end]=='\n') end--;
+                                               if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+                                               return null;
+                                       }
+                                       this.lineStarted = true;
+                                       return createMethodReference(receiver, null);
+                               }
+                               break nextArg;
+                       }
+                       iToken++;
+
+                       // Read possible array declaration
+                       int dim = 0;
+                       long[] dimPositions = new long[20]; // assume that there won't be more than 20 dimensions...
+                       if (readToken() == TerminalTokens.TokenNameLBRACKET) {
+                               int dimStart = this.scanner.getCurrentTokenStartPosition();
+                               while (readToken() == TerminalTokens.TokenNameLBRACKET) {
+                                       consumeToken();
+                                       if (readToken() != TerminalTokens.TokenNameRBRACKET) {
+                                               break nextArg;
+                                       }
+                                       consumeToken();
+                                       dimPositions[dim++] = (((long) dimStart) << 32) + this.scanner.getCurrentTokenEndPosition();
+                               }
+                       }
+
+                       // Read argument name
+                       long argNamePos = -1;
+                       if (readToken() == TerminalTokens.TokenNameIdentifier) {
+                               consumeToken();
+                               if (firstArg) { // verify position
+                                       if (iToken != 1)
+                                               break nextArg;
+                               } else if ((iToken % modulo) != 1) {
+                                               break nextArg;
+                               }
+                               if (argName == null) { // verify that all arguments name are declared
+                                       if (!firstArg) {
+                                               break nextArg;
+                                       }
+                               }
+                               argName = this.scanner.getCurrentIdentifierSource();
+                               argNamePos = (((long)this.scanner.getCurrentTokenStartPosition())<<32)+this.scanner.getCurrentTokenEndPosition();
+                               iToken++;
+                       } else if (argName != null) { // verify that no argument name is declared
+                               break nextArg;
+                       }
+                       
+                       // Verify token position
+                       if (firstArg) {
+                               modulo = iToken + 1;
+                       } else {
+                               if ((iToken % modulo) != (modulo - 1)) {
+                                       break nextArg;
+                               }
+                       }
+
+                       // Read separator or end arguments declaration
+                       int token = readToken();
+                       char[] name = argName == null ? new char[0] : argName;
+                       if (token == TerminalTokens.TokenNameCOMMA) {
+                               // Create new argument
+                               Object argument = createArgumentReference(name, dim, typeRef, dimPositions, argNamePos);
+                               arguments.add(argument);
+                               consumeToken();
+                               iToken++;
+                       } else if (token == TerminalTokens.TokenNameRPAREN) {
+                               // verify characters after arguments declaration (expecting white space or end comment)
+                               if (!verifySpaceOrEndComment()) {
+                                       int end = this.starPosition == -1 ? this.lineEnd : this.starPosition;
+                                       if (this.source[end]=='\n') end--;
+                                       if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMalformedSeeReference(start, end);
+                                       return null;
+                               }
+                               // Create new argument
+                               Object argument = createArgumentReference(name, dim, typeRef, dimPositions, argNamePos);
+                               arguments.add(argument);
+                               consumeToken();
+                               return createMethodReference(receiver, arguments);
+                       } else {
+                               break nextArg;
+                       }
+               }
+
+               // Something wrong happened => Invalid input
+               throw new InvalidInputException();
+       }
+
+       /*
+        * Parse an URL link reference in @see tag
+        */
+       private boolean parseHref() throws InvalidInputException {
+               int start = this.scanner.getCurrentTokenStartPosition();
+               if (Character.toLowerCase(readChar()) == 'a') {
+                       this.scanner.currentPosition = this.index;
+                       if (readToken() == TerminalTokens.TokenNameIdentifier) {
+                               this.currentTokenType = -1; // do not update line end
+                               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
+                                               if (readToken() == TerminalTokens.TokenNameStringLiteral) {
+                                                       this.currentTokenType = -1; // do not update line end
+                                                       // Skip all characters after string literal until closing '>' (see bug 68726)
+                                                       while (this.index <= this.lineEnd && readToken() != TerminalTokens.TokenNameGREATER) {
+                                                               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 == '@') {
+                                                                               // 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);
+                                                                               return false;
+                                                                       }
+                                                                       consumeToken();
+                                                               }
+                                                               this.currentTokenType = -1; // do not update line end
+                                                               if (readChar() == '/') {
+                                                                       if (Character.toLowerCase(readChar()) == 'a') {
+                                                                               if (readChar() == '>') {
+                                                                                       // Valid href
+                                                                                       return true;
+                                                                               }
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               } catch (InvalidInputException ex) {
+                                       // Do nothing as we want to keep positions for error message
+                               }
+                       }
+               }
+               // 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);
+               return false;
+       }
+
+       /*
+        * Parse a method reference in @see tag
+        */
+       private Object parseMember(Object receiver) throws InvalidInputException {
+               // Init
+               this.identifierPtr = -1;
+               this.identifierLengthPtr = -1;
+               int start = this.scanner.getCurrentTokenStartPosition();
+               this.memberStart = start;
+
+               // Get member identifier
+               if (readToken() == TerminalTokens.TokenNameIdentifier) {
+                       consumeToken();
+                       pushIdentifier(true);
+                       // Look for next token to know whether it's a field or method reference
+                       int previousPosition = this.index;
+                       if (readToken() == TerminalTokens.TokenNameLPAREN) {
+                               consumeToken();
+                               start = this.scanner.getCurrentTokenStartPosition();
+                               try {
+                                       return parseArguments(receiver);
+                               } catch (InvalidInputException e) {
+                                       int end = this.scanner.getCurrentTokenEndPosition() < this.lineEnd ?
+                                                       this.scanner.getCurrentTokenEndPosition() :
+                                                       this.scanner.getCurrentTokenStartPosition();
+                                       end = end < this.lineEnd ? end : this.lineEnd;
+                                       if (this.sourceParser != null) 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);
+                               return null;
+                       }
+                       return createFieldReference(receiver);
+               }
+               int end = getEndPosition() - 1;
+               end = start > end ? start : end;
+               if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidSeeReference(start, end);
+               // Reset position: we want to rescan last token
+               this.index = this.tokenPreviousPosition;
+               this.scanner.currentPosition = this.tokenPreviousPosition;
+               this.currentTokenType = -1;
+               return null;
+       }
+
+       /*
+        * Parse @param tag declaration
+        */
+       protected boolean parseParam() {
+
+               // Store current token state
+               int start = this.tagSourceStart;
+               int end = this.tagSourceEnd;
+
+               try {
+                       // Push identifier next
+                       int token = readToken();
+                       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;
+                       }
+               } 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;
+
+               // Report problem
+               if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingParamName(start, end);
+               return false;
+       }
+
+       /*
+        * Parse a qualified name and built a type reference if the syntax is valid.
+        */
+       protected Object parseQualifiedName(boolean reset) throws InvalidInputException {
+
+               // Reset identifier stack if requested
+               if (reset) {
+                       this.identifierPtr = -1;
+                       this.identifierLengthPtr = -1;
+               }
+
+               // Scan tokens
+               int primitiveToken = -1;
+               nextToken : for (int iToken = 0; ; iToken++) {
+                       int token = readToken();
+                       switch (token) {
+                               case TerminalTokens.TokenNameIdentifier :
+                                       if (((iToken % 2) > 0)) { // identifiers must be odd tokens
+                                               break nextToken;
+                                       }
+                                       pushIdentifier(iToken == 0);
+                                       consumeToken();
+                                       break;
+
+                               case TerminalTokens.TokenNameDOT :
+                                       if ((iToken % 2) == 0) { // dots must be even tokens
+                                               throw new InvalidInputException();
+                                       }
+                                       consumeToken();
+                                       break;
+
+                               case TerminalTokens.TokenNamevoid :
+                               case TerminalTokens.TokenNameboolean :
+                               case TerminalTokens.TokenNamebyte :
+                               case TerminalTokens.TokenNamechar :
+                               case TerminalTokens.TokenNamedouble :
+                               case TerminalTokens.TokenNamefloat :
+                               case TerminalTokens.TokenNameint :
+                               case TerminalTokens.TokenNamelong :
+                               case TerminalTokens.TokenNameshort :
+                                       if (iToken > 0) {
+                                               throw new InvalidInputException();
+                                       }
+                                       pushIdentifier(true);
+                                       primitiveToken = token;
+                                       consumeToken();
+                                       break nextToken;
+
+                               default :
+                                       if (iToken == 0) {
+                                               return null;
+                                       }
+                                       if ((iToken % 2) == 0) { // cannot leave on a dot
+                                               // Reset position: we want to rescan last token
+                                               if (this.kind == DOM_PARSER && this.currentTokenType != -1) {
+                                                       this.index = this.tokenPreviousPosition;
+                                                       this.scanner.currentPosition = this.tokenPreviousPosition;
+                                                       this.currentTokenType = -1;
+                                               }
+                                               throw new InvalidInputException();
+                                       }
+                                       break nextToken;
+                       }
+               }
+               // Reset position: we want to rescan last token
+               if (this.currentTokenType != -1) {
+                       this.index = this.tokenPreviousPosition;
+                       this.scanner.currentPosition = this.tokenPreviousPosition;
+                       this.currentTokenType = -1;
+               }
+               this.lastIdentifierEndPosition = (int) this.identifierPositionStack[this.identifierPtr];
+               return createTypeReference(primitiveToken);
+       }
+
+       /*
+        * Parse a reference in @see tag
+        */
+       protected boolean parseReference(boolean plain) throws InvalidInputException {
+               Object typeRef = null;
+               Object reference = null;
+               int previousPosition = -1;
+               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()) {
+                                               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.TokenNameERROR :
+                                       if (this.scanner.currentCharacter == '#') { // @see ...#member
+                                               consumeToken();
+                                               reference = parseMember(typeRef);
+                                               if (reference != null) {
+                                                       return pushSeeRef(reference, plain);
+                                               }
+                                               return false;
+                                       }
+                                       break nextToken;
+                               case TerminalTokens.TokenNameIdentifier :
+                                       if (typeRef == null) {
+                                               typeRefStartPosition = this.scanner.getCurrentTokenStartPosition();
+                                               typeRef = parseQualifiedName(true);
+                                               break;
+                                       }
+                                       break nextToken;
+                               default :
+                                       break nextToken;
+                       }
+               }
+               
+               // Verify that we got a reference
+               if (reference == null) reference = typeRef;
+               if (reference == null) {
+                       this.index = this.tokenPreviousPosition;
+                       this.scanner.currentPosition = this.tokenPreviousPosition;
+                       this.currentTokenType = -1;
+                       if (this.sourceParser != null) this.sourceParser.problemReporter().javadocMissingSeeReference(this.tagSourceStart, this.tagSourceEnd);
+                       return false;
+               }
+
+               // 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 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.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();
+
+       /*
+        * 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());
+               }
+               // Reset position to avoid missing tokens when new line was encountered
+               this.index = this.tokenPreviousPosition;
+               this.scanner.currentPosition = this.tokenPreviousPosition;
+               this.currentTokenType = -1;
+               return false;
+       }
+
+       /*
+        * Parse @return tag declaration
+        */
+       protected abstract boolean parseTag();
+
+       /*
+        * Parse @throws tag declaration
+        */
+       protected boolean parseThrows(boolean real) {
+               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);
+                       } else {
+                               return pushThrowName(typeRef, real);
+                       }
+               } catch (InvalidInputException ex) {
+                       if (this.sourceParser != null) this.sourceParser.problemReporter().javadocInvalidThrowsClass(start, getEndPosition());
+               }
+               return false;
+       }
+
+       /*
+        * Return current character without move index position.
+        */
+       private char peekChar() {
+               int idx = this.index;
+               char c = this.source[idx++];
+               if (c == '\\' && this.source[idx] == 'u') {
+                       int c1, c2, c3, c4;
+                       idx++;
+                       while (this.source[idx] == 'u')
+                               idx++;
+                       if (!(((c1 = Character.getNumericValue(this.source[idx++])) > 15 || c1 < 0)
+                                       || ((c2 = Character.getNumericValue(this.source[idx++])) > 15 || c2 < 0)
+                                       || ((c3 = Character.getNumericValue(this.source[idx++])) > 15 || c3 < 0) || ((c4 = Character.getNumericValue(this.source[idx++])) > 15 || c4 < 0))) {
+                               c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       }
+               }
+               return c;
+       }
+
+       /*
+        * push the consumeToken on the identifier stack. Increase the total number of identifier in the stack.
+        */
+       protected void pushIdentifier(boolean newLength) {
+
+               int stackLength = this.identifierStack.length;
+               if (++this.identifierPtr >= stackLength) {
+                       System.arraycopy(
+                               this.identifierStack, 0,
+                               this.identifierStack = new char[stackLength + 10][], 0,
+                               stackLength);
+                       System.arraycopy(
+                               this.identifierPositionStack, 0,
+                               this.identifierPositionStack = new long[stackLength + 10], 0,
+                               stackLength);
+               }
+               this.identifierStack[this.identifierPtr] = this.scanner.getCurrentIdentifierSource();
+               this.identifierPositionStack[this.identifierPtr] = (((long) this.scanner.startPosition) << 32) + (this.scanner.currentPosition - 1);
+
+               if (newLength) {
+                       stackLength = this.identifierLengthStack.length;
+                       if (++this.identifierLengthPtr >= stackLength) {
+                               System.arraycopy(
+                                       this.identifierLengthStack, 0,
+                                       this.identifierLengthStack = new int[stackLength + 10], 0,
+                                       stackLength);
+                       }
+                       this.identifierLengthStack[this.identifierLengthPtr] = 1;
+               } else {
+                       this.identifierLengthStack[this.identifierLengthPtr]++;
+               }
+       }
+
+       /*
+        * Add a new obj on top of the ast stack.
+        * If new length is required, then add also a new length in length stack.
+        */
+       protected void pushOnAstStack(Object node, boolean newLength) {
+
+               if (node == null) {
+                       this.astLengthStack[++this.astLengthPtr] = 0;
+                       return;
+               }
+
+               int stackLength = this.astStack.length;
+               if (++this.astPtr >= stackLength) {
+                       System.arraycopy(
+                               this.astStack, 0,
+                               this.astStack = new Object[stackLength + AstStackIncrement], 0,
+                               stackLength);
+                       this.astPtr = stackLength;
+               }
+               this.astStack[this.astPtr] = node;
+
+               if (newLength) {
+                       stackLength = this.astLengthStack.length;
+                       if (++this.astLengthPtr >= stackLength) {
+                               System.arraycopy(
+                                       this.astLengthStack, 0,
+                                       this.astLengthStack = new int[stackLength + AstStackIncrement], 0,
+                                       stackLength);
+                       }
+                       this.astLengthStack[this.astLengthPtr] = 1;
+               } else {
+                       this.astLengthStack[this.astLengthPtr]++;
+               }
+       }
+
+       /*
+        * Push a param name in ast node stack.
+        */
+       protected abstract boolean pushParamName();
+
+       /*
+        * Push a reference statement in ast node stack.
+        */
+       protected abstract boolean pushSeeRef(Object statement, boolean plain);
+
+       /*
+        * Push a text element in ast node stack
+        */
+       protected abstract void pushText(int start, int end);
+
+       /*
+        * Push a throws type ref in ast node stack.
+        */
+       protected abstract boolean pushThrowName(Object typeRef, boolean real);
+
+       /*
+        * Read current character and move index position.
+        * Warning: scanner position is unchanged using this method!
+        */
+       protected char readChar() {
+       
+               char c = this.source[this.index++];
+               if (c == '\\' && this.source[this.index] == 'u') {
+                       int c1, c2, c3, c4;
+                       int pos = this.index;
+                       this.index++;
+                       while (this.source[this.index] == 'u')
+                               this.index++;
+                       if (!(((c1 = Character.getNumericValue(this.source[this.index++])) > 15 || c1 < 0)
+                                       || ((c2 = Character.getNumericValue(this.source[this.index++])) > 15 || c2 < 0)
+                                       || ((c3 = Character.getNumericValue(this.source[this.index++])) > 15 || c3 < 0) || ((c4 = Character.getNumericValue(this.source[this.index++])) > 15 || c4 < 0))) {
+                               c = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       } else {
+                               // TODO (frederic) currently reset to previous position, perhaps signal a syntax error would be more appropriate
+                               this.index = pos;
+                       }
+               }
+               return c;
+       }
+
+       /*
+        * Read token only if previous was consumed
+        */
+       private int readToken() throws InvalidInputException {
+               if (this.currentTokenType < 0) {
+                       this.tokenPreviousPosition = this.scanner.currentPosition;
+                       this.currentTokenType = this.scanner.getNextToken();
+                       if (this.scanner.currentPosition > (this.lineEnd+1)) { // be sure to be on next line (lineEnd is still on the same line)
+                               this.lineStarted = false;
+                               while (this.currentTokenType == TerminalTokens.TokenNameMULTIPLY) {
+                                       this.currentTokenType = this.scanner.getNextToken();
+                               }
+                       }
+                       this.index = this.scanner.currentPosition;
+                       this.lineStarted = true; // after having read a token, line is obviously started...
+               }
+               return this.currentTokenType;
+       }
+
+       private int readTokenAndConsume() throws InvalidInputException {
+               int token = readToken();
+               consumeToken();
+               return token;
+       }
+       
+       /*
+        * Refresh start position and length of an inline tag.
+        */
+       protected void refreshInlineTagPosition(int previousPosition) {
+               // do nothing by default
+       }
+
+       public String toString() {
+               StringBuffer buffer = new StringBuffer();
+               int startPos = this.scanner.currentPosition<this.index ? this.scanner.currentPosition : this.index;
+               int endPos = this.scanner.currentPosition<this.index ? this.index : this.scanner.currentPosition;
+               if (startPos == this.source.length)
+                       return "EOF\n\n" + new String(this.source); //$NON-NLS-1$
+               if (endPos > this.source.length)
+                       return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$
+       
+               char front[] = new char[startPos];
+               System.arraycopy(this.source, 0, front, 0, startPos);
+       
+               int middleLength = (endPos - 1) - startPos + 1;
+               char middle[];
+               if (middleLength > -1) {
+                       middle = new char[middleLength];
+                       System.arraycopy(
+                               this.source, 
+                               startPos, 
+                               middle, 
+                               0, 
+                               middleLength);
+               } else {
+                       middle = CharOperation.NO_CHAR;
+               }
+               
+               char end[] = new char[this.source.length - (endPos - 1)];
+               System.arraycopy(
+                       this.source, 
+                       (endPos - 1) + 1, 
+                       end, 
+                       0, 
+                       this.source.length - (endPos - 1) - 1);
+               
+               buffer.append(front);
+               if (this.scanner.currentPosition<this.index) {
+                       buffer.append("\n===============================\nScanner current position here -->"); //$NON-NLS-1$
+               } else {
+                       buffer.append("\n===============================\nParser index here -->"); //$NON-NLS-1$
+               }
+               buffer.append(middle);
+               if (this.scanner.currentPosition<this.index) {
+                       buffer.append("<-- Parser index here\n===============================\n"); //$NON-NLS-1$
+               } else {
+                       buffer.append("<-- Scanner current position here\n===============================\n"); //$NON-NLS-1$
+               }
+               buffer.append(end);
+
+               return buffer.toString();
+       }
+
+       /*
+        * Update 
+        */
+       protected abstract void updateDocComment();
+
+       /*
+        * Update line end
+        */
+       protected void updateLineEnd() {
+               while (this.index > (this.lineEnd+1)) { // be sure to be on next line (lineEnd is still on the same line)
+                       if (this.linePtr < this.lastLinePtr) {
+                               this.lineEnd = this.scanner.getLineEnd(++this.linePtr) - 1;
+                       } else {
+                               this.lineEnd = this.endComment;
+                               return;
+                       }
+               }
+       }
+
+       /*
+        * Verify that end of the line only contains space characters or end of comment.
+        * Note that end of comment may be preceeding by several contiguous '*' chars.
+        */
+       private boolean verifyEndLine(int textPosition) {
+               int startPosition = this.index;
+               int previousPosition = this.index;
+               this.starPosition = -1;
+               char ch = readChar();
+               nextChar: while (true) {
+                       switch (ch) {
+                               case '\r':
+                               case '\n':
+                                       if (this.kind == DOM_PARSER) {
+                                               parseTag();
+                                               pushText(textPosition, previousPosition);
+                                       }
+                                       this.index = previousPosition;
+                                       return true;
+                               case '\u000c' : /* FORM FEED               */
+                               case ' ' :                      /* SPACE                   */
+                               case '\t' :                     /* HORIZONTAL TABULATION   */
+                                       if (this.starPosition >= 0) break nextChar;
+                                       break;
+                               case '*':
+                                       this.starPosition = previousPosition;
+                                       break;
+                               case '/':
+                                       if (this.starPosition >= textPosition) {
+                                               if (this.kind == DOM_PARSER) {
+                                                       parseTag();
+                                                       pushText(textPosition, this.starPosition);
+                                               }
+                                               return true;
+                                       }
+                               default :
+                                       // leave loop
+                                       break nextChar;
+                               
+                       }
+                       previousPosition = this.index;
+                       ch = readChar();
+               }
+               this.index = startPosition;
+               return false;
+       }
+
+       /*
+        * 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
+        *      3- are the end of comment (several contiguous star ('*') characters may be
+        *          found before the last slash ('/') character).
+        */
+       private boolean verifySpaceOrEndComment() {
+               int startPosition = this.index;
+               // Whitespace or inline tag closing brace
+               char ch = peekChar();
+               switch (ch) {
+                       case '}':
+                               return this.inlineTagStarted;
+                       default:
+                               if (Character.isWhitespace(ch)) {
+                                       return true;
+                               }
+               }
+               // End of comment
+               int previousPosition = this.index;
+               this.starPosition = -1;
+               ch = readChar();
+               nextChar: while (this.index<this.source.length) {
+                       switch (ch) {
+                               case '*':
+                                       // valid whatever the number of star before last '/'
+                                       this.starPosition = previousPosition;
+                                       break;
+                               case '/':
+                                       if (this.starPosition >= startPosition) { // valid only if a star was previous character
+                                               return true;
+                                       }
+                               default :
+                                       // invalid whatever other character, even white spaces
+                                       this.index = startPosition;
+                                       return false;
+                               
+                       }
+                       previousPosition = this.index;
+                       ch = readChar();
+               }
+               this.index = startPosition;
+               return false;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java b/src/java/org/eclipse/jdt/internal/compiler/parser/JavadocParser.java
new file mode 100644 (file)
index 0000000..7786636
--- /dev/null
@@ -0,0 +1,466 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import 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.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+
+/**
+ * Parser specialized for decoding javadoc comments
+ */
+public class JavadocParser extends AbstractCommentParser {
+
+       // Public fields
+       public Javadoc docComment;
+       
+       // 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;
+
+       JavadocParser(Parser sourceParser) {
+               super(sourceParser);
+               this.checkDocComment = this.sourceParser.options.docCommentSupport;
+               this.kind = COMPIL_PARSER;
+       }
+
+       /* (non-Javadoc)
+        * Returns true if tag @deprecated is present in javadoc comment.
+        * 
+        * If javadoc checking is enabled, will also construct an Javadoc node, which will be stored into Parser.javadoc
+        * slot for being consumed later on.
+        */
+       public boolean checkDeprecation(int javadocStart, int javadocEnd) {
+
+               try {
+                       this.source = this.sourceParser.scanner.source;
+                       this.index = javadocStart +3;
+                       this.endComment = javadocEnd - 2;
+                       if (this.checkDocComment) {
+                               // Initialization
+                               this.scanner.lineEnds = this.sourceParser.scanner.lineEnds;
+                               this.scanner.linePtr = this.sourceParser.scanner.linePtr;
+                               this.lineEnds = this.scanner.lineEnds;
+                               this.docComment = new Javadoc(javadocStart, javadocEnd);
+                               parseComment(javadocStart, javadocEnd);
+                       } else {
+                               // Init javadoc if necessary
+                               if (this.sourceParser.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore) {
+                                       this.docComment = new Javadoc(javadocStart, javadocEnd);
+                               } else {
+                                       this.docComment = null;
+                               }
+                               
+                               // Parse comment
+                               int firstLineNumber = this.sourceParser.scanner.getLineNumber(javadocStart);
+                               int lastLineNumber = this.sourceParser.scanner.getLineNumber(javadocEnd);
+       
+                               // scan line per line, since tags must be at beginning of lines only
+                               nextLine : for (int line = firstLineNumber; line <= lastLineNumber; line++) {
+                                       int lineStart = line == firstLineNumber
+                                                       ? javadocStart + 3 // skip leading /**
+                                                       : this.sourceParser.scanner.getLineStart(line);
+                                       this.index = lineStart;
+                                       this.lineEnd = line == lastLineNumber
+                                                       ? javadocEnd - 2 // remove trailing * /
+                                                       : this.sourceParser.scanner.getLineEnd(line);
+                                       nextCharacter : while (this.index < this.lineEnd) {
+                                               char c = readChar(); // consider unicodes
+                                               switch (c) {
+                                                   default : 
+                                                       if (Character.isWhitespace(c)) {
+                                                           continue nextCharacter;
+                                                       }
+                                                       break;
+                                                   case '*' :
+                                                       continue nextCharacter;
+                                                   case '@' :
+                                                       if ((readChar() == 'd') && (readChar() == 'e') &&
+                                                                               (readChar() == 'p') && (readChar() == 'r') &&
+                                                                               (readChar() == 'e') && (readChar() == 'c') &&
+                                                                               (readChar() == 'a') && (readChar() == 't') &&
+                                                                               (readChar() == 'e') && (readChar() == 'd')) {
+                                                                       // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk.
+                                                                       c = readChar();
+                                                                       if (Character.isWhitespace(c) || c == '*') {
+                                                                               return true;
+                                                                       }
+                                                       }
+                                               }
+                                       continue nextLine;
+                                       }
+                               }
+                               return false;
+                       }
+               } finally {
+                       this.source = null; // release source as soon as finished
+               }
+               return this.deprecated;
+       }
+
+       public String toString() {
+               StringBuffer buffer = new StringBuffer();
+               buffer.append("check javadoc: ").append(this.checkDocComment).append("\n");     //$NON-NLS-1$ //$NON-NLS-2$
+               buffer.append("javadoc: ").append(this.docComment).append("\n");        //$NON-NLS-1$ //$NON-NLS-2$
+               buffer.append(super.toString());
+               return buffer.toString();
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createArgumentReference(char[], java.lang.Object, int)
+        */
+       protected Object createArgumentReference(char[] name, int dim, Object typeRef, long[] dimPositions, long argNamePos) throws InvalidInputException {
+               try {
+                       TypeReference argTypeRef = (TypeReference) typeRef;
+                       if (dim > 0) {
+                               long pos = (((long) argTypeRef.sourceStart) << 32) + argTypeRef.sourceEnd;
+                               if (typeRef instanceof JavadocSingleTypeReference) {
+                                       JavadocSingleTypeReference singleRef = (JavadocSingleTypeReference) typeRef;
+                                       argTypeRef = new JavadocArraySingleTypeReference(singleRef.token, dim, pos);
+                               } else {
+                                       JavadocQualifiedTypeReference qualifRef = (JavadocQualifiedTypeReference) typeRef;
+                                       argTypeRef = new JavadocArrayQualifiedTypeReference(qualifRef, dim);
+                               }
+                       }
+                       int argEnd = argTypeRef.sourceEnd;
+                       if (dim > 0) argEnd = (int) dimPositions[dim-1];
+                       if (argNamePos >= 0) argEnd = (int) argNamePos;
+                       return new JavadocArgumentExpression(name, argTypeRef.sourceStart, argEnd, argTypeRef);
+               }
+               catch (ClassCastException ex) {
+                               throw new InvalidInputException();
+               }
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createFieldReference()
+        */
+       protected Object createFieldReference(Object receiver) throws InvalidInputException {
+               try {
+                       // Get receiver type
+                       TypeReference typeRef = (TypeReference) receiver;
+                       if (typeRef == null) {
+                               char[] name = this.sourceParser.compilationUnit.compilationResult.compilationUnit.getMainTypeName();
+                               typeRef = new ImplicitDocTypeReference(name, this.memberStart);
+                       }
+                       // Create field
+                       JavadocFieldReference field = new JavadocFieldReference(this.identifierStack[0], this.identifierPositionStack[0]);
+                       field.receiver = typeRef;
+                       field.tagSourceStart = this.tagSourceStart;
+                       field.tagSourceEnd = this.tagSourceEnd;
+                       return field;
+               }
+               catch (ClassCastException ex) {
+                               throw new InvalidInputException();
+               }
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createMethodReference(java.lang.Object[])
+        */
+       protected Object createMethodReference(Object receiver, List arguments) throws InvalidInputException {
+               try {
+                       // Get receiver type
+                       TypeReference typeRef = (TypeReference) receiver;
+                       // Decide whether we have a constructor or not
+                       boolean isConstructor = false;
+                       if (typeRef == null) {
+                               char[] name = this.sourceParser.compilationUnit.compilationResult.compilationUnit.getMainTypeName();
+                               isConstructor = CharOperation.equals(this.identifierStack[0], name);
+                               typeRef = new ImplicitDocTypeReference(name, this.memberStart);
+                       } else {
+                               char[] name = null;
+                               if (typeRef instanceof JavadocSingleTypeReference) {
+                                       name = ((JavadocSingleTypeReference)typeRef).token;
+                               } else if (typeRef instanceof JavadocQualifiedTypeReference) {
+                                       char[][] tokens = ((JavadocQualifiedTypeReference)typeRef).tokens;
+                                       name = tokens[tokens.length-1];
+                               } else {
+                                       throw new InvalidInputException();
+                               }
+                               isConstructor = CharOperation.equals(this.identifierStack[0], name);
+                       }
+                       // Create node
+                       if (arguments == null) {
+                               if (isConstructor) {
+                                       JavadocAllocationExpression expr = new JavadocAllocationExpression(this.identifierPositionStack[0]);
+                                       expr.type = typeRef;
+                                       return expr;
+                               } else {
+                                       JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0]);
+                                       msg.receiver = typeRef;
+                                       return msg;
+                               }
+                       } else {
+                               JavadocArgumentExpression[] expressions = new JavadocArgumentExpression[arguments.size()];
+                               arguments.toArray(expressions);
+                               if (isConstructor) {
+                                       JavadocAllocationExpression alloc = new JavadocAllocationExpression(this.identifierPositionStack[0]);
+                                       alloc.arguments = expressions;
+                                       alloc.type = typeRef;
+                                       return alloc;
+                               } else {
+                                       JavadocMessageSend msg = new JavadocMessageSend(this.identifierStack[0], this.identifierPositionStack[0], expressions);
+                                       msg.receiver = typeRef;
+                                       return msg;
+                               }
+                       }
+               }
+               catch (ClassCastException ex) {
+                               throw new InvalidInputException();
+               }
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createReturnStatement()
+        */
+       protected Object createReturnStatement() {
+               return new JavadocReturnStatement(this.scanner.getCurrentTokenStartPosition(),
+                                       this.scanner.getCurrentTokenEndPosition(),
+                                       this.scanner.getRawTokenSourceEnd());
+       }
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#createTypeReference()
+        */
+       protected Object createTypeReference(int primitiveToken) {
+               TypeReference typeRef = null;
+               int size = this.identifierLengthStack[this.identifierLengthPtr--];
+               if (size == 1) { // Single Type ref
+                       typeRef = new JavadocSingleTypeReference(
+                                               this.identifierStack[this.identifierPtr],
+                                               this.identifierPositionStack[this.identifierPtr],
+                                               this.tagSourceStart,
+                                               this.tagSourceEnd);
+               } else if (size > 1) { // Qualified Type ref
+                       char[][] tokens = new char[size][];
+                       System.arraycopy(this.identifierStack, this.identifierPtr - size + 1, tokens, 0, size);
+                       long[] positions = new long[size];
+                       System.arraycopy(this.identifierPositionStack, this.identifierPtr - size + 1, positions, 0, size);
+                       typeRef = new JavadocQualifiedTypeReference(tokens, positions, this.tagSourceStart, this.tagSourceEnd);
+               }
+               this.identifierPtr -= size;
+               return typeRef;
+       }
+
+       /*
+        * Parse @return tag declaration
+        */
+       protected boolean parseReturn() {
+               if (this.returnStatement == null) {
+                       this.returnStatement = createReturnStatement();
+                       return true;
+               }
+               if (this.sourceParser != null) this.sourceParser.problemReporter().javadocDuplicatedReturnTag(
+                               this.scanner.getCurrentTokenStartPosition(),
+                               this.scanner.getCurrentTokenEndPosition());
+               return false;
+       }
+
+       /*
+        * Parse @return tag declaration
+        */
+       protected boolean parseTag() {
+               return true;
+       }
+
+       /*
+        * 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;
+               // 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);
+                                       }
+                                       this.invParamsStack[this.invParamsPtr] = nameRef;
+                                       return false;
+                               }
+                       }
+                       switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
+                               case PARAM_TAG_EXPECTED_ORDER :
+                                       // previous push was a @param tag => push another param name
+                                       pushOnAstStack(nameRef, false);
+                                       break;
+                               case SEE_TAG_EXPECTED_ORDER :
+                                       // previous push was a @see tag => push new param name
+                                       pushOnAstStack(nameRef, true);
+                                       break;
+                               default:
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       /*
+        * Push a reference statement in ast node stack.
+        */
+       protected boolean pushSeeRef(Object statement, boolean plain) {
+               if (this.astLengthPtr == -1) { // First push
+                       pushOnAstStack(null, true);
+                       pushOnAstStack(null, true);
+                       pushOnAstStack(statement, true);
+               } else {
+                       switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
+                               case PARAM_TAG_EXPECTED_ORDER :
+                                       // previous push was a @param tag => push empty @throws tag and new @see tag
+                                       pushOnAstStack(null, true);
+                                       pushOnAstStack(statement, true);
+                                       break;
+                               case THROWS_TAG_EXPECTED_ORDER :
+                                       // previous push was a @throws tag => push new @see tag
+                                       pushOnAstStack(statement, true);
+                                       break;
+                               case SEE_TAG_EXPECTED_ORDER :
+                                       // previous push was a @see tag => push another @see tag
+                                       pushOnAstStack(statement, false);
+                                       break;
+                               default:
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       /* (non-Javadoc)
+        * @see org.eclipse.jdt.internal.compiler.parser.AbstractCommentParser#pushText(int, int)
+        */
+       protected void pushText(int start, int end) {
+               // compiler does not matter of text
+       }
+
+       /*
+        * Push a throws type ref in ast node stack.
+        */
+       protected boolean pushThrowName(Object typeRef, boolean real) {
+               if (this.astLengthPtr == -1) { // First push
+                       pushOnAstStack(null, true);
+                       pushOnAstStack(typeRef, true);
+               } else {
+                       switch (this.astLengthPtr % ORDERED_TAGS_NUMBER) {
+                               case PARAM_TAG_EXPECTED_ORDER :
+                                       // previous push was a @param tag => push new @throws tag
+                                       pushOnAstStack(typeRef, true);
+                                       break;
+                               case THROWS_TAG_EXPECTED_ORDER :
+                                       // previous push was a @throws tag => push another @throws tag
+                                       pushOnAstStack(typeRef, false);
+                                       break;
+                               case SEE_TAG_EXPECTED_ORDER :
+                                       // previous push was a @see tag => push empty @param and new @throws tags
+                                       pushOnAstStack(null, true);
+                                       pushOnAstStack(typeRef, true);
+                                       break;
+                               default:
+                                       return false;
+                       }
+               }
+               return true;
+       }
+
+       /*
+        * Fill associated comment fields with ast nodes information stored in stack.
+        */
+       protected void updateDocComment() {
+               
+               // Set inherited flag
+               this.docComment.inherited = this.inherited;
+
+               // Set return node if present
+               if (this.returnStatement != null) {
+                       this.docComment.returnStatement = (JavadocReturnStatement) this.returnStatement;
+               }
+               
+               // 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 no nodes stored return
+               if (this.astLengthPtr == -1) {
+                       return;
+               }
+
+               // Initialize arrays
+               int[] sizes = new int[ORDERED_TAGS_NUMBER];
+               for (int i=0; i<=this.astLengthPtr; i++) {
+                       sizes[i%ORDERED_TAGS_NUMBER] += this.astLengthStack[i];
+               }
+               this.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]];
+
+               // 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--];
+                               }
+                       }
+
+                       // 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--];
+                               }
+                       }
+
+                       // 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--];
+                               }
+                       }
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/NLSLine.java b/src/java/org/eclipse/jdt/internal/compiler/parser/NLSLine.java
new file mode 100644 (file)
index 0000000..99af1e3
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+
+public class NLSLine {
+
+       private List elements;
+
+       public NLSLine() {
+               this.elements = new ArrayList();
+       }
+       
+       /**
+        * Adds a NLS element to this line.
+        */
+       public void add(StringLiteral element) {
+               this.elements.add(element);
+       }
+       
+       /**
+        * returns an Iterator over NLSElements
+        */
+       public Iterator iterator() {
+               return this.elements.iterator();
+       }
+       
+       public StringLiteral get(int index) {
+               return (StringLiteral) this.elements.get(index);
+       }
+       
+       public void set(int index, StringLiteral literal) {
+               this.elements.set(index, literal);
+       }
+       
+       public boolean exists(int index) {
+               return index >= 0 && index < this.elements.size();
+       }
+       
+       public int size(){
+               return this.elements.size();
+       }
+       
+       public String toString() {
+               StringBuffer result= new StringBuffer();
+               for (Iterator iter= iterator(); iter.hasNext(); ) {
+                       result.append("\t"); //$NON-NLS-1$
+                       result.append(iter.next().toString());
+                       result.append("\n"); //$NON-NLS-1$
+               }
+               return result.toString();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/Parser.java b/src/java/org/eclipse/jdt/internal/compiler/parser/Parser.java
new file mode 100644 (file)
index 0000000..81fd8d4
--- /dev/null
@@ -0,0 +1,6244 @@
+/*******************************************************************************
+ * 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
+ *     Tom Tromey - patch for readTable(String) as described in http://bugs.eclipse.org/bugs/show_bug.cgi?id=32196
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
+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.CompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.parser.diagnose.DiagnoseParser;
+import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class Parser implements BindingIds, ParserBasicInformation, TerminalTokens, CompilerModifiers, OperatorIds, TypeIds {
+       protected ProblemReporter problemReporter;
+       protected CompilerOptions options;
+       public int firstToken ; // handle for multiple parsing goals
+       public int lastAct ; //handle for multiple parsing goals
+       public ReferenceContext referenceContext;
+       public int currentToken;
+       private int synchronizedBlockSourceStart;
+
+       //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;
+               
+       //internal data for the automat 
+       protected final static int StackIncrement = 255;
+       protected int stateStackTop;
+       protected int[] stack = new int[StackIncrement];
+       //scanner token 
+       public Scanner scanner;
+       //ast stack
+       final static int AstStackIncrement = 100;
+       protected int astPtr;
+       protected ASTNode[] astStack = new ASTNode[AstStackIncrement];
+       protected int astLengthPtr;
+       protected int[] astLengthStack;
+       public CompilationUnitDeclaration compilationUnit; /*the result from parse()*/
+       ASTNode [] noAstNodes = new ASTNode[AstStackIncrement];
+       //expression stack
+       final static int ExpressionStackIncrement = 100;
+       protected int expressionPtr;
+       protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
+       protected int expressionLengthPtr;
+       protected int[] expressionLengthStack;
+       Expression [] noExpressions = new Expression[ExpressionStackIncrement];
+       //identifiers stacks 
+       protected int identifierPtr;
+       protected char[][] identifierStack;
+       protected int identifierLengthPtr;
+       protected int[] identifierLengthStack;
+       protected long[] identifierPositionStack;
+       //positions , dimensions , .... (int stacks)
+       protected int intPtr;
+       protected int[] intStack;
+       protected int endPosition; //accurate only when used ! (the start position is pushed into intStack while the end the current one)
+       protected int endStatementPosition;
+       protected int lParenPos,rParenPos; //accurate only when used !
+       protected int rBraceStart, rBraceEnd, rBraceSuccessorStart; //accurate only when used !
+       //modifiers dimensions nestedType etc.......
+       protected boolean optimizeStringLiterals =true;
+       protected int modifiers;
+       protected int modifiersSourceStart;
+       protected int nestedType, dimensions;
+       protected int[] nestedMethod; //the ptr is nestedType
+       protected int[] realBlockStack;
+       protected int realBlockPtr;
+       protected boolean diet = false; //tells the scanner to jump over some parts of the code/expressions like method bodies
+       protected int dietInt = 0; // if > 0 force the none-diet-parsing mode (even if diet if requested) [field parsing with anonymous inner classes...]
+       protected int[] variablesCounter;
+
+       // javadoc
+       public JavadocParser javadocParser;
+       public Javadoc javadoc;
+       
+       public static byte rhs[] = null;
+       public static char asb[] = null;
+       public static char asr[] = null;
+       public static char nasb[] = null;
+       public static char nasr[] = null;
+
+       public static char terminal_index[] = null;
+       public static char non_terminal_index[] = null;
+       
+       public static char term_action[] = null;
+       public static byte term_check[] = null;
+
+       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$
+
+       static {
+               try{
+                       initTables();
+               } catch(java.io.IOException ex){
+                       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]++;
+}
+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;
+       }
+
+       //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);
+}
+private final static String[] buildFileForName(String filename, String contents) throws java.io.IOException {
+       String[] result = new String[contents.length()];
+       result[0] = null;
+       int resultCount = 1;
+       
+       StringBuffer buffer = new StringBuffer();
+       
+       int start = contents.indexOf("name[]"); //$NON-NLS-1$
+       start = contents.indexOf('\"', start); 
+       int end = contents.indexOf("};", start); //$NON-NLS-1$
+       
+       contents = contents.substring(start, end);
+       
+       boolean addLineSeparator = false;
+       int tokenStart = -1;
+       StringBuffer currentToken = new StringBuffer();
+       for (int i = 0; i < contents.length(); i++) {
+               char c = contents.charAt(i);
+               if(c == '\"') {
+                       if(tokenStart == -1) {
+                               tokenStart = i + 1;     
+                       } else {
+                               if(addLineSeparator) {
+                                       buffer.append('\n');
+                                       result[resultCount++] = currentToken.toString();
+                                       currentToken = new StringBuffer();
+                               }
+                               String token = contents.substring(tokenStart, i);
+                               if(token.equals(ERROR_TOKEN)){
+                                       token = INVALID_CHARACTER;
+                               } else if(token.equals(EOF_TOKEN)) {
+                                       token = UNEXPECTED_EOF;
+                               }
+                               buffer.append(token);
+                               currentToken.append(token);
+                               addLineSeparator = true;
+                               tokenStart = -1;
+                       }
+               }
+               if(tokenStart == -1 && c == '+'){
+                       addLineSeparator = false;
+               }
+       }
+       if(currentToken.length() > 0) {
+               result[resultCount++] = currentToken.toString();
+       }
+       
+       buildFileForTable(filename, buffer.toString().toCharArray());
+       
+       System.arraycopy(result, 0, result = new String[resultCount], 0, resultCount);
+       return result;
+}
+private static void buildFileForReadableName(
+       String file,
+       char[] newLhs,
+       char[] newNonTerminalIndex,
+       String[] newName,
+       String[] tokens) throws java.io.IOException {
+
+       ArrayList entries = new ArrayList();
+       
+       boolean[] alreadyAdded = new boolean[newName.length];
+       
+       for (int i = 0; i < tokens.length; i = i + 2) {
+               int index = newNonTerminalIndex[newLhs[Integer.parseInt(tokens[i])]];
+               StringBuffer buffer = new StringBuffer();
+               if(!alreadyAdded[index]) {
+                       alreadyAdded[index] = true;
+                       buffer.append(newName[index]);
+                       buffer.append('=');
+                       buffer.append(tokens[i+1].trim());
+                       buffer.append('\n');
+                       entries.add(String.valueOf(buffer));
+               }
+       }
+       int i = 1;
+       while(!INVALID_CHARACTER.equals(newName[i])) i++;
+       i++;
+       for (; i < alreadyAdded.length; i++) {
+               if(!alreadyAdded[i]) {
+                       System.out.println(newName[i] + " has no readable name"); //$NON-NLS-1$
+               }
+       }
+       Collections.sort(entries);
+       buildFile(file, entries);
+}
+private final static void buildFile(String filename, List listToDump) throws java.io.IOException {
+       BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
+       for (Iterator iterator = listToDump.iterator(); iterator.hasNext(); ) {
+               writer.write(String.valueOf(iterator.next()));
+       }
+       writer.flush();
+       writer.close();
+       System.out.println(filename + " creation complete"); //$NON-NLS-1$
+}
+private final static void buildFileForTable(String filename, char[] chars) throws java.io.IOException {
+
+       byte[] bytes = new byte[chars.length * 2];
+       for (int i = 0; i < chars.length; i++) {
+               bytes[2 * i] = (byte) (chars[i] >>> 8);
+               bytes[2 * i + 1] = (byte) (chars[i] & 0xFF);
+       }
+
+       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, byte[] bytes) throws java.io.IOException {
+       java.io.FileOutputStream stream = new java.io.FileOutputStream(filename);
+       stream.write(bytes);
+       stream.close();
+       System.out.println(filename + " creation complete"); //$NON-NLS-1$
+}
+public final static void buildFilesFromLPG(String dataFilename, String dataFilename2)  throws java.io.IOException {
+
+       //RUN THIS METHOD TO GENERATE PARSER*.RSC FILES
+
+       //build from the lpg javadcl.java files that represents the parser tables
+       //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);
+       } catch (IOException ex) {
+               System.out.println(Util.bind("parser.incorrectPath")); //$NON-NLS-1$
+               return;
+       }
+       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;
+       while (st.hasMoreTokens()) {
+               tokens[i++] = st.nextToken();
+       }
+       final String prefix = FILEPREFIX;
+       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$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "asb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "asr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "nasb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "nasr", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "terminal_index", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       char[] newNonTerminalIndex = buildFileOfIntFor(prefix + (++i) + ".rsc", "non_terminal_index", tokens); //$NON-NLS-1$ //$NON-NLS-2$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "term_action", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_prefix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_suffix", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_lhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state_set", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "scope_state", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfIntFor(prefix + (++i) + ".rsc", "in_symb", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       
+       buildFileOfByteFor(prefix + (++i) + ".rsc", "rhs", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfByteFor(prefix + (++i) + ".rsc", "term_check", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       buildFileOfByteFor(prefix + (++i) + ".rsc", "scope_la", tokens); //$NON-NLS-2$ //$NON-NLS-1$
+       
+       String[] newName = buildFileForName(prefix + (++i) + ".rsc", new String(contents)); //$NON-NLS-1$
+       
+       contents = new char[] {};
+       try {
+               contents = Util.getFileCharContent(new File(dataFilename2), null);
+       } catch (IOException ex) {
+               System.out.println(Util.bind("parser.incorrectPath")); //$NON-NLS-1$
+               return;
+       }
+       st = new java.util.StringTokenizer(new String(contents), "\t\n\r=");  //$NON-NLS-1$
+       tokens = new String[st.countTokens()];
+       i = 0;
+       while (st.hasMoreTokens()) {
+               tokens[i++] = st.nextToken();
+       }
+       buildFileForReadableName(READABLE_NAMES_FILE+".properties", newLhs, newNonTerminalIndex, newName, tokens);//$NON-NLS-1$
+       
+       System.out.println(Util.bind("parser.moveFiles")); //$NON-NLS-1$
+}
+/*
+ * 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;
+
+       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;
+                                       }
+                               }
+                       } 
+               }
+       }
+
+       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);
+                               this.lastCheckPoint = method.bodyStart;
+                       } else {
+                               element = element.add(method, 0);
+                               this.lastCheckPoint = method.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }
+               if (node instanceof Initializer){
+                       Initializer initializer = (Initializer) node;
+                       if (initializer.declarationSourceEnd == 0){
+                               element = element.add(initializer, 1);
+                               this.lastCheckPoint = initializer.sourceStart;                          
+                       } else {
+                               element = element.add(initializer, 0);
+                               this.lastCheckPoint = initializer.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }               
+               if (node instanceof FieldDeclaration){
+                       FieldDeclaration field = (FieldDeclaration) node;
+                       if (field.declarationSourceEnd == 0){
+                               element = element.add(field, 0);
+                               if (field.initialization == null){
+                                       this.lastCheckPoint = field.sourceEnd + 1;
+                               } else {
+                                       this.lastCheckPoint = field.initialization.sourceEnd + 1;
+                               }
+                       } else {
+                               element = element.add(field, 0);
+                               this.lastCheckPoint = field.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }
+               if (node instanceof TypeDeclaration){
+                       TypeDeclaration type = (TypeDeclaration) node;
+                       if (type.declarationSourceEnd == 0){
+                               element = element.add(type, 0); 
+                               this.lastCheckPoint = type.bodyStart;
+                       } else {
+                               element = element.add(type, 0);                         
+                               this.lastCheckPoint = type.declarationSourceEnd + 1;
+                       }
+                       continue;
+               }
+               if (node instanceof ImportReference){
+                       ImportReference importRef = (ImportReference) node;
+                       element = element.add(importRef, 0);
+                       this.lastCheckPoint = importRef.declarationSourceEnd + 1;
+               }
+       }
+       return element;
+}
+public final static short base_check(int i) {
+       return check_table[i - (NUM_RULES + 1)];
+}
+public final 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. */
+
+       if ((this.modifiers & flag) != 0){ // duplicate modifier
+               this.modifiers |= AccAlternateModifierProblem;
+       }
+       this.modifiers |= flag;
+                       
+       if (this.modifiersSourceStart < 0) this.modifiersSourceStart = this.scanner.startPosition;
+}
+public void checkComment() {
+
+       if (this.currentElement != null && this.scanner.commentPtr >= 0) {
+               flushCommentsDefinedPriorTo(this.endStatementPosition); // discard obsolete comments during recovery
+       }
+       
+       int lastComment = this.scanner.commentPtr;
+       
+       if (this.modifiersSourceStart >= 0) {
+               // eliminate comments located after modifierSourceStart if positionned
+               while (lastComment >= 0 && this.scanner.commentStarts[lastComment] > this.modifiersSourceStart) lastComment--;
+       }
+       if (lastComment >= 0) {
+               // consider all remaining leading comments to be part of current declaration
+               this.modifiersSourceStart = this.scanner.commentStarts[0]; 
+       
+               // check deprecation in last comment if javadoc (can be followed by non-javadoc comments which are simply ignored)      
+               while (lastComment >= 0 && this.scanner.commentStops[lastComment] < 0) lastComment--; // non javadoc comment have negative end positions
+               if (lastComment >= 0 && this.javadocParser != null) {
+                       if (this.javadocParser.checkDeprecation(
+                                       this.scanner.commentStarts[lastComment],
+                                       this.scanner.commentStops[lastComment] - 1)) { //stop is one over,
+                               checkAndSetModifiers(AccDeprecated);
+                       }
+                       this.javadoc = this.javadocParser.docComment;   // null if check javadoc is not activated 
+               }
+       }
+}
+protected void checkNonExternalizedStringLiteral() {
+       if (this.scanner.wasNonExternalizedStringLiteral) {
+               StringLiteral[] literals = this.scanner.nonNLSStrings;
+               // could not reproduce, but this is the only NPE
+               // added preventive null check see PR 9035
+               if (literals != null) {
+                       for (int i = 0, max = literals.length; i < max; i++) {
+                               problemReporter().nonExternalizedStringLiteral(literals[i]);
+                       }
+               }
+               this.scanner.wasNonExternalizedStringLiteral = false;
+       }
+}
+protected void checkNonNLSAfterBodyEnd(int declarationEnd){
+       if(this.scanner.currentPosition - 1 <= declarationEnd) {
+               this.scanner.eofPosition = declarationEnd < Integer.MAX_VALUE ? declarationEnd + 1 : declarationEnd;
+               try {
+                       while(this.scanner.getNextToken() != TokenNameEOF){/*empty*/}
+                       checkNonExternalizedStringLiteral();
+               } catch (InvalidInputException e) {
+                       // Nothing to do
+               }
+       }
+}
+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) {
+       // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+
+       // ClassBodyopt produces a null item on the astStak if it produces NO class body
+       // An empty class body produces a 0 on the length stack.....
+
+       AllocationExpression alloc;
+       int length;
+       if (((length = this.astLengthStack[this.astLengthPtr--]) == 1)
+               && (this.astStack[this.astPtr] == null)) {
+               //NO ClassBody
+               this.astPtr--;
+               if (alwaysQualified) {
+                       alloc = new QualifiedAllocationExpression();
+               } else {
+                       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);
+               //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 (anonymousTypeDeclaration.allocation != null) {
+                       anonymousTypeDeclaration.allocation.sourceEnd = this.endStatementPosition;
+               }
+               if (length == 0 && !containsComment(anonymousTypeDeclaration.bodyStart, anonymousTypeDeclaration.bodyEnd)) {
+                       anonymousTypeDeclaration.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+               }
+               this.astPtr--;
+               this.astLengthPtr--;
+               
+               // mark initializers with local type mark if needed
+               markInitializersWithLocalType(anonymousTypeDeclaration);
+       }
+}
+protected final void concatExpressionLists() {
+       this.expressionLengthStack[--this.expressionLengthPtr]++;
+}
+private final 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
+        * 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.
+        * Look at the InterfaceMemberDeclarations for an example.
+        */
+
+       this.astLengthStack[this.astLengthPtr - 1] += this.astLengthStack[this.astLengthPtr--];
+}
+protected void consumeAllocationHeader() {
+       // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+
+       // ClassBodyopt produces a null item on the astStak if it produces NO class body
+       // An empty class body produces a 0 on the length stack.....
+
+       if (this.currentElement == null){
+               return; // should never occur, this consumeRule is only used in recovery mode
+       }
+       if (this.currentToken == TokenNameLBRACE){
+               // beginning of an anonymous type
+               TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
+               anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+               anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+               anonymousType.sourceStart = this.intStack[this.intPtr--];
+               anonymousType.sourceEnd = this.rParenPos; // closing parenthesis
+               QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType);
+               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;
+               this.currentToken = 0; // opening brace already taken into account
+               return;
+       }
+       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 consumeArrayAccess(boolean unspecifiedReference) {
+       // ArrayAccess ::= Name '[' Expression ']' ==> true
+       // ArrayAccess ::= PrimaryNoNewArray '[' Expression ']' ==> false
+
+
+       //optimize push/pop
+       Expression exp;
+       if (unspecifiedReference) {
+               exp = 
+                       this.expressionStack[this.expressionPtr] = 
+                               new ArrayReference(
+                                       getUnspecifiedReferenceOptimized(),
+                                       this.expressionStack[this.expressionPtr]);
+       } else {
+               this.expressionPtr--;
+               this.expressionLengthPtr--;
+               exp = 
+                       this.expressionStack[this.expressionPtr] = 
+                               new ArrayReference(
+                                       this.expressionStack[this.expressionPtr],
+                                       this.expressionStack[this.expressionPtr + 1]);
+       }
+       exp.sourceEnd = this.endPosition;
+}
+protected void consumeArrayCreationExpressionWithoutInitializer() {
+       // ArrayCreationWithoutArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs
+       // ArrayCreationWithoutArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs
+
+       int length;
+       ArrayAllocationExpression aae = new ArrayAllocationExpression();
+       aae.type = getTypeReference(0);
+       length = (this.expressionLengthStack[this.expressionLengthPtr--]);
+       this.expressionPtr -= length ;
+       System.arraycopy(
+               this.expressionStack,
+               this.expressionPtr+1,
+               aae.dimensions = new Expression[length],
+               0,
+               length);
+       aae.sourceStart = this.intStack[this.intPtr--];
+       if (aae.initializer == null) {
+               aae.sourceEnd = this.endPosition;
+       } else {
+               aae.sourceEnd = aae.initializer.sourceEnd ;
+       }
+       pushOnExpressionStack(aae);
+}
+
+protected void consumeArrayCreationHeader() {
+       // nothing to do
+}
+protected void consumeArrayCreationExpressionWithInitializer() {
+       // ArrayCreationWithArrayInitializer ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializer
+       // ArrayCreationWithArrayInitializer ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializer
+
+       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 ;
+       System.arraycopy(
+               this.expressionStack,
+               this.expressionPtr+1,
+               aae.dimensions = new Expression[length],
+               0,
+               length);
+       aae.sourceStart = this.intStack[this.intPtr--];
+       if (aae.initializer == null) {
+               aae.sourceEnd = this.endPosition;
+       } else {
+               aae.sourceEnd = aae.initializer.sourceEnd ;
+       }
+       pushOnExpressionStack(aae);
+}
+protected void consumeArrayInitializer() {
+       // ArrayInitializer ::= '{' VariableInitializers '}'
+       // ArrayInitializer ::= '{' VariableInitializers , '}'
+
+       arrayInitializer(this.expressionLengthStack[this.expressionLengthPtr--]);
+}
+
+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
+
+       int op = this.intStack[this.intPtr--] ; //<--the encoded operator
+       
+       this.expressionPtr -- ; this.expressionLengthPtr -- ;
+       this.expressionStack[this.expressionPtr] =
+               (op != EQUAL ) ?
+                       new CompoundAssignment(
+                               this.expressionStack[this.expressionPtr] ,
+                               this.expressionStack[this.expressionPtr+1], 
+                               op,
+                               this.scanner.startPosition - 1) :
+                       new Assignment(
+                               this.expressionStack[this.expressionPtr] ,
+                               this.expressionStack[this.expressionPtr+1],
+                               this.scanner.startPosition - 1);
+}
+protected void consumeAssignmentOperator(int pos) {
+       // AssignmentOperator ::= '='
+       // AssignmentOperator ::= '*='
+       // AssignmentOperator ::= '/='
+       // AssignmentOperator ::= '%='
+       // AssignmentOperator ::= '+='
+       // AssignmentOperator ::= '-='
+       // AssignmentOperator ::= '<<='
+       // AssignmentOperator ::= '>>='
+       // AssignmentOperator ::= '>>>='
+       // AssignmentOperator ::= '&='
+       // AssignmentOperator ::= '^='
+       // AssignmentOperator ::= '|='
+
+       pushOnIntStack(pos);
+}
+protected void consumeBinaryExpression(int op) {
+       // MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression
+       // MultiplicativeExpression ::= MultiplicativeExpression '/' UnaryExpression
+       // MultiplicativeExpression ::= MultiplicativeExpression '%' UnaryExpression
+       // AdditiveExpression ::= AdditiveExpression '+' MultiplicativeExpression
+       // AdditiveExpression ::= AdditiveExpression '-' MultiplicativeExpression
+       // ShiftExpression ::= ShiftExpression '<<'  AdditiveExpression
+       // ShiftExpression ::= ShiftExpression '>>'  AdditiveExpression
+       // ShiftExpression ::= ShiftExpression '>>>' AdditiveExpression
+       // RelationalExpression ::= RelationalExpression '<'  ShiftExpression
+       // RelationalExpression ::= RelationalExpression '>'  ShiftExpression
+       // RelationalExpression ::= RelationalExpression '<=' ShiftExpression
+       // RelationalExpression ::= RelationalExpression '>=' ShiftExpression
+       // AndExpression ::= AndExpression '&' EqualityExpression
+       // ExclusiveOrExpression ::= ExclusiveOrExpression '^' AndExpression
+       // InclusiveOrExpression ::= InclusiveOrExpression '|' ExclusiveOrExpression
+       // ConditionalAndExpression ::= ConditionalAndExpression '&&' InclusiveOrExpression
+       // ConditionalOrExpression ::= ConditionalOrExpression '||' ConditionalAndExpression
+
+       //optimize the push/pop
+
+       this.expressionPtr--;
+       this.expressionLengthPtr--;
+       Expression expr1 = this.expressionStack[this.expressionPtr];
+       Expression expr2 = this.expressionStack[this.expressionPtr + 1];
+       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;
+               default :
+                       this.expressionStack[this.expressionPtr] = 
+                               new BinaryExpression(
+                                       expr1, 
+                                       expr2, 
+                                       op);            
+       }
+}
+protected void consumeBlock() {
+       // Block ::= OpenBlock '{' BlockStatementsopt '}'
+       // simpler action for empty blocks
+
+       int statementsLength = this.astLengthStack[this.astLengthPtr--];
+       Block block;
+       if (statementsLength == 0) { // empty block 
+               block = new Block(0);
+               block.sourceStart = this.intStack[this.intPtr--];
+               block.sourceEnd = this.endStatementPosition;
+               // check whether this block at least contains some comment in it
+               if (!containsComment(block.sourceStart, block.sourceEnd)) {
+                       block.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+               }
+               this.realBlockPtr--; // still need to pop the block variable counter
+       } else {
+               block = new Block(this.realBlockStack[this.realBlockPtr--]);
+               this.astPtr -= statementsLength;
+               System.arraycopy(
+                       this.astStack, 
+                       this.astPtr + 1, 
+                       block.statements = new Statement[statementsLength], 
+                       0, 
+                       statementsLength); 
+               block.sourceStart = this.intStack[this.intPtr--];
+               block.sourceEnd = this.endStatementPosition;
+       }
+       pushOnAstStack(block);
+}
+protected void consumeBlockStatements() {
+       // BlockStatements ::= BlockStatements BlockStatement
+       concatNodeLists();
+}
+protected void consumeCaseLabel() {
+       // SwitchLabel ::= 'case' ConstantExpression ':'
+       this.expressionLengthPtr--;
+       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
+
+       //optimize push/pop
+
+       Expression cast,exp;
+       this.expressionPtr--;
+       this.expressionStack[this.expressionPtr] = 
+               cast = new CastExpression(
+                       exp=this.expressionStack[this.expressionPtr+1] ,
+                       getTypeReference(this.expressionStack[this.expressionPtr]));
+       this.expressionLengthPtr -- ;
+       updateSourcePosition(cast);
+       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;
+}
+protected void consumeClassBodyDeclaration() {
+       // ClassBodyDeclaration ::= Diet Block
+       //push an Initializer
+       //optimize the push/pop
+       this.nestedMethod[this.nestedType]--;
+       Block block = (Block) this.astStack[this.astPtr];
+       if (this.diet) block.bits &= ~ASTNode.UndocumentedEmptyBlockMASK; // clear bit since was diet
+       Initializer initializer = new Initializer(block, 0);
+       this.intPtr--; // pop sourcestart left on the stack by consumeNestedMethod.
+       initializer.bodyStart = this.intStack[this.intPtr--];
+       this.realBlockPtr--; // pop the block variable counter left on the stack by consumeNestedMethod
+       int javadocCommentStart = this.intStack[this.intPtr--];
+       if (javadocCommentStart != -1) {
+               initializer.declarationSourceStart = javadocCommentStart;
+               initializer.javadoc = this.javadoc;
+               this.javadoc = null;
+       }
+       this.astStack[this.astPtr] = initializer;
+       initializer.bodyEnd = this.endPosition;
+       initializer.sourceEnd = this.endStatementPosition;
+       initializer.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+}
+protected void consumeClassBodyDeclarations() {
+       // ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration
+       concatNodeLists();
+}
+protected void consumeClassBodyDeclarationsopt() {
+       // ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations
+       this.nestedType-- ;
+}
+protected void consumeClassBodyopt() {
+       // ClassBodyopt ::= $empty
+       pushOnAstStack(null);
+       this.endPosition = this.scanner.startPosition - 1;
+}
+protected void consumeClassDeclaration() {
+       // ClassDeclaration ::= ClassHeader ClassBody
+
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               //there are length declarations
+               //dispatch according to the type of the declarations
+               dispatchDeclarationInto(length);
+       }
+
+       TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+
+       // mark initializers with local type mark if needed
+       markInitializersWithLocalType(typeDecl);
+
+       //convert constructor that do not have the type's name into methods
+       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;
+                               }
+                       }
+               }
+               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;
+       }
+       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 consumeClassHeader() {
+       // ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt
+
+       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 class header
+       this.scanner.commentPtr = -1;
+}
+protected void consumeClassHeaderExtends() {
+       // ClassHeaderExtends ::= 'extends' ClassType
+       // There is a class declaration on the top of stack
+       TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+       //superclass
+       typeDecl.superclass = getTypeReference(0);
+       typeDecl.bodyStart = typeDecl.superclass.sourceEnd + 1;
+       // recovery
+       if (this.currentElement != null){
+               this.lastCheckPoint = typeDecl.bodyStart;
+       }
+}
+protected void consumeClassHeaderImplements() {
+       // ClassHeaderImplements ::= 'implements' InterfaceTypeList
+       int length = this.astLengthStack[this.astLengthPtr--];
+       //super interfaces
+       this.astPtr -= length;
+       // There is a class declaration on the top of stack
+       TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+       System.arraycopy(
+               this.astStack, 
+               this.astPtr + 1, 
+               typeDecl.superInterfaces = new TypeReference[length], 
+               0, 
+               length); 
+       typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
+       this.listLength = 0; // reset after having read super-interfaces
+       // recovery
+       if (this.currentElement != null) { // is recovering
+               this.lastCheckPoint = typeDecl.bodyStart;
+       }
+}
+protected void consumeClassHeaderName() {
+       // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+       TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+       if (this.nestedMethod[this.nestedType] == 0) {
+               if (this.nestedType != 0) {
+                       typeDecl.bits |= ASTNode.IsMemberTypeMASK;
+               }
+       } else {
+               // Record that the block has a declaration for local types
+               typeDecl.bits |= ASTNode.IsLocalTypeMASK;
+               markEnclosingMemberWithLocalType();
+               blockReal();
+       }
+
+       //highlight the name of the type
+       long pos = this.identifierPositionStack[this.identifierPtr];
+       typeDecl.sourceEnd = (int) pos;
+       typeDecl.sourceStart = (int) (pos >>> 32);
+       typeDecl.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.
+       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--];
+       if (typeDecl.modifiersSourceStart >= 0) {
+               typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
+       }
+       typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+       pushOnAstStack(typeDecl);
+
+       this.listLength = 0; // will be updated when reading super-interfaces
+       // recovery
+       if (this.currentElement != null){ 
+               this.lastCheckPoint = typeDecl.bodyStart;
+               this.currentElement = this.currentElement.add(typeDecl, 0);
+               this.lastIgnoredToken = -1;
+       }
+       // javadoc
+       typeDecl.javadoc = this.javadoc;
+       this.javadoc = null;
+}
+protected void consumeClassInstanceCreationExpression() {
+       // ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+       classInstanceCreation(false);
+}
+protected void consumeClassInstanceCreationExpressionName() {
+       // ClassInstanceCreationExpressionName ::= Name '.'
+       pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+}
+protected void consumeClassInstanceCreationExpressionQualified() {
+       // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
+       // ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
+
+       classInstanceCreation(true); //  <-- push the Qualifed....
+
+       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 consumeClassTypeElt() {
+       // ClassTypeElt ::= ClassType
+       pushOnAstStack(getTypeReference(0));
+       /* if incomplete thrown exception list, listLength counter will not have been reset,
+               indicating that some items are available on the stack */
+       this.listLength++;      
+}
+protected void consumeClassTypeList() {
+       // ClassTypeList ::= ClassTypeList ',' ClassTypeElt
+       optimizedConcatNodeLists();
+}
+protected void consumeCompilationUnit() {
+       // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
+       // do nothing by default
+}
+protected void consumeConditionalExpression(int op) {
+       // ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression
+       //optimize the push/pop
+
+       this.expressionPtr -= 2;
+       this.expressionLengthPtr -= 2;
+       this.expressionStack[this.expressionPtr] =
+               new ConditionalExpression(
+                       this.expressionStack[this.expressionPtr],
+                       this.expressionStack[this.expressionPtr + 1],
+                       this.expressionStack[this.expressionPtr + 2]);
+}
+protected void consumeConstructorBlockStatements() {
+       // ConstructorBody ::= NestedMethod '{' ExplicitConstructorInvocation BlockStatements '}'
+       concatNodeLists(); // explictly add the first statement into the list of statements 
+}
+protected void consumeConstructorBody() {
+       // ConstructorBody ::= NestedMethod  '{' BlockStatementsopt '}'
+       // ConstructorBody ::= NestedMethod  '{' ExplicitConstructorInvocation '}'
+       this.nestedMethod[this.nestedType] --;
+}
+protected void consumeConstructorDeclaration() {
+       // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
+
+       /*
+       astStack : MethodDeclaration statements
+       identifierStack : name
+        ==>
+       astStack : MethodDeclaration
+       identifierStack :
+       */
+
+       //must provide a default constructor call when needed
+
+       int length;
+
+       // pop the position of the {  (body of the method) pushed in block decl
+       this.intPtr--;
+       this.intPtr--;
+
+       //statements
+       this.realBlockPtr--;
+       ExplicitConstructorCall constructorCall = null;
+       Statement[] statements = null;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               this.astPtr -= length;
+               if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall) {
+                       //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+                       System.arraycopy(
+                               this.astStack, 
+                               this.astPtr + 2, 
+                               statements = new Statement[length - 1], 
+                               0, 
+                               length - 1); 
+                       constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
+               } else { //need to add explicitly the super();
+                       System.arraycopy(
+                               this.astStack, 
+                               this.astPtr + 1, 
+                               statements = new Statement[length], 
+                               0, 
+                               length); 
+                       constructorCall = SuperReference.implicitSuperConstructorCall();
+               }
+       } else {
+               boolean insideFieldInitializer = false;
+               if (this.diet) {
+                       for (int i = this.nestedType; i > 0; i--){
+                               if (this.variablesCounter[i] > 0) {
+                                       insideFieldInitializer = true;
+                                       break;
+                               }
+                       }
+               }
+               
+               if (!this.diet || insideFieldInitializer){
+                       // add it only in non-diet mode, if diet_bodies, then constructor call will be added elsewhere.
+                       constructorCall = SuperReference.implicitSuperConstructorCall();
+               }
+       }
+
+       // now we know that the top of stack is a constructorDeclaration
+       ConstructorDeclaration cd = (ConstructorDeclaration) this.astStack[this.astPtr];
+       cd.constructorCall = constructorCall;
+       cd.statements = statements;
+
+       //highlight of the implicit call on the method name
+       if (constructorCall != null && cd.constructorCall.sourceEnd == 0) {
+               cd.constructorCall.sourceEnd = cd.sourceEnd;
+               cd.constructorCall.sourceStart = cd.sourceStart;
+       }
+
+       if (!this.diet && (statements == null && constructorCall.isImplicitSuper())) {
+               if (!containsComment(cd.bodyStart, this.endPosition)) {
+                       cd.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+               }
+       }
+
+       //watch for } that could be given as a unicode ! ( u007D is '}' )
+       // store the endPosition (position just before the '}') in case there is
+       // a trailing comment behind the end of the method
+       cd.bodyEnd = 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
+
+       AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
+
+       if (this.currentToken == TokenNameLBRACE){ 
+               method.bodyStart = this.scanner.currentPosition;
+       }
+       // recovery
+       if (this.currentElement != null){
+               if (this.currentToken == TokenNameSEMICOLON){ // for invalid constructors
+                       method.modifiers |= AccSemicolonBody;                   
+                       method.declarationSourceEnd = this.scanner.currentPosition-1;
+                       method.bodyEnd = this.scanner.currentPosition-1;
+                       if (this.currentElement.parseTree() == method && this.currentElement.parent != null) {
+                               this.currentElement = this.currentElement.parent;
+                       }
+               }               
+               this.restartRecovery = true; // used to avoid branching back into the regular automaton
+       }               
+}
+protected void consumeConstructorHeaderName() {
+
+       /* 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 '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--;
+
+       //modifiers
+       cd.declarationSourceStart = this.intStack[this.intPtr--];
+       cd.modifiers = this.intStack[this.intPtr--];
+       // 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 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 consumeDefaultLabel() {
+       // SwitchLabel ::= 'default' ':'
+       pushOnAstStack(new CaseStatement(null, this.intStack[this.intPtr--], this.intStack[this.intPtr--]));
+}
+protected void consumeDefaultModifiers() {
+       checkComment(); // might update modifiers with AccDeprecated
+       pushOnIntStack(this.modifiers); // modifiers
+       pushOnIntStack(
+               this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition); 
+       resetModifiers();
+}
+protected void consumeDiet() {
+       // Diet ::= $empty
+       checkComment();
+       pushOnIntStack(this.modifiersSourceStart); // push the start position of a javadoc comment if there is one
+       resetModifiers();
+       jumpOverMethodBody();
+}
+protected void consumeDims() {
+       // Dims ::= DimsLoop
+       pushOnIntStack(this.dimensions);
+       this.dimensions = 0;
+}
+protected void consumeDimWithOrWithOutExpr() {
+       // DimWithOrWithOutExpr ::= '[' ']'
+       pushOnExpressionStack(null);
+       
+       if(this.currentElement != null && this.currentToken == TokenNameLBRACE) {
+               this.ignoreNextOpeningBrace = true;
+               this.currentElement.bracketBalance++; 
+       }
+}
+protected void consumeDimWithOrWithOutExprs() {
+       // DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
+       concatExpressionLists();
+}
+protected void consumeEmptyArgumentListopt() {
+       // ArgumentListopt ::= $empty
+       pushOnExpressionStackLengthStack(0);
+}
+protected void consumeEmptyArrayInitializer() {
+       // ArrayInitializer ::= '{' ,opt '}'
+       arrayInitializer(0);
+}
+protected void consumeEmptyArrayInitializeropt() {
+       // ArrayInitializeropt ::= $empty
+       pushOnExpressionStackLengthStack(0);
+}
+protected void consumeEmptyBlockStatementsopt() {
+       // BlockStatementsopt ::= $empty
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyCatchesopt() {
+       // Catchesopt ::= $empty
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyClassBodyDeclarationsopt() {
+       // ClassBodyDeclarationsopt ::= $empty
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyClassMemberDeclaration() {
+       // ClassMemberDeclaration ::= ';'
+       pushOnAstLengthStack(0);
+       problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition);
+       flushCommentsDefinedPriorTo(this.endStatementPosition);
+}
+protected void consumeEmptyDimsopt() {
+       // Dimsopt ::= $empty
+       pushOnIntStack(0);
+}
+protected void consumeEmptyExpression() {
+       // Expressionopt ::= $empty
+       pushOnExpressionStackLengthStack(0);
+}
+protected void consumeEmptyForInitopt() {
+       // ForInitopt ::= $empty
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyForUpdateopt() {
+       // ForUpdateopt ::= $empty
+       pushOnExpressionStackLengthStack(0);
+}
+protected void consumeEmptyImportDeclarationsopt() {
+       // ImportDeclarationsopt ::= $empty
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyInterfaceMemberDeclaration() {
+       // InterfaceMemberDeclaration ::= ';'
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyInterfaceMemberDeclarationsopt() {
+       // InterfaceMemberDeclarationsopt ::= $empty
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyStatement() {
+       // EmptyStatement ::= ';'
+       if (this.scanner.source[this.endStatementPosition] == ';') {
+               pushOnAstStack(new EmptyStatement(this.endStatementPosition, this.endStatementPosition));
+       } else {
+               // we have a Unicode for the ';' (/u003B)
+               pushOnAstStack(new EmptyStatement(this.endStatementPosition - 5, this.endStatementPosition));
+       }
+}
+protected void consumeEmptySwitchBlock() {
+       // SwitchBlock ::= '{' '}'
+       pushOnAstLengthStack(0);
+}
+protected void consumeEmptyTypeDeclaration() {
+       // TypeDeclaration ::= ';' 
+       pushOnAstLengthStack(0);
+       problemReporter().superfluousSemicolon(this.endPosition+1, this.endStatementPosition);
+       flushCommentsDefinedPriorTo(this.endStatementPosition);
+}
+protected void consumeEmptyTypeDeclarationsopt() {
+       // TypeDeclarationsopt ::= $empty
+       pushOnAstLengthStack(0); 
+}
+protected void consumeEnterAnonymousClassBody() {
+       // EnterAnonymousClassBody ::= $empty
+       QualifiedAllocationExpression alloc;
+       TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult); 
+       anonymousType.name = TypeDeclaration.ANONYMOUS_EMPTY_NAME;
+       anonymousType.bits |= ASTNode.AnonymousAndLocalMask;
+       alloc = anonymousType.allocation = new QualifiedAllocationExpression(anonymousType); 
+       markEnclosingMemberWithLocalType();
+       pushOnAstStack(anonymousType);
+
+       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 = getTypeReference(0);
+
+       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 consumeEnterCompilationUnit() {
+       // EnterCompilationUnit ::= $empty
+       // do nothing by default
+}
+protected void consumeEnterVariable() {
+       // EnterVariable ::= $empty
+       // do nothing by default
+
+       char[] identifierName = this.identifierStack[this.identifierPtr];
+       long namePosition = this.identifierPositionStack[this.identifierPtr];
+       int extendedDimension = this.intStack[this.intPtr--];
+       AbstractVariableDeclaration declaration;
+       // create the ast node
+       boolean isLocalDeclaration = this.nestedMethod[this.nestedType] != 0; 
+       if (isLocalDeclaration) {
+               // create the local variable declarations
+               declaration = 
+                       this.createLocalDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition);
+       } else {
+               // create the field declaration
+               declaration = 
+                       this.createFieldDeclaration(identifierName, (int) (namePosition >>> 32), (int) namePosition); 
+       }
+       
+       this.identifierPtr--;
+       this.identifierLengthPtr--;
+       TypeReference type;
+       int variableIndex = this.variablesCounter[this.nestedType];
+       int typeDim = 0;
+       if (variableIndex == 0) {
+               // first variable of the declaration (FieldDeclaration or LocalDeclaration)
+               if (isLocalDeclaration) {
+                       declaration.declarationSourceStart = this.intStack[this.intPtr--];
+                       declaration.modifiers = this.intStack[this.intPtr--];
+                       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
+                               declaration.declarationSourceStart = type.sourceStart;
+                       }
+                       pushOnAstStack(type);
+               } else {
+                       type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
+                       pushOnAstStack(type);
+                       declaration.declarationSourceStart = this.intStack[this.intPtr--];
+                       declaration.modifiers = this.intStack[this.intPtr--];
+                       
+                       // Store javadoc only on first declaration as it is the same for all ones
+                       FieldDeclaration fieldDeclaration = (FieldDeclaration) declaration;
+                       fieldDeclaration.javadoc = this.javadoc;
+                       this.javadoc = null;
+               }
+       } else {
+               type = (TypeReference) this.astStack[this.astPtr - variableIndex];
+               typeDim = type.dimensions();
+               AbstractVariableDeclaration previousVariable = 
+                       (AbstractVariableDeclaration) this.astStack[this.astPtr]; 
+               declaration.declarationSourceStart = previousVariable.declarationSourceStart;
+               declaration.modifiers = previousVariable.modifiers;
+       }
+
+       if (extendedDimension == 0) {
+               declaration.type = type;
+       } else {
+               int dimension = typeDim + extendedDimension;
+               //on the identifierLengthStack there is the information about the type....
+               int baseType;
+               if ((baseType = this.identifierLengthStack[this.identifierLengthPtr + 1]) < 0) {
+                       //it was a baseType
+                       int typeSourceStart = type.sourceStart;
+                       int typeSourceEnd = type.sourceEnd;
+                       type = TypeReference.baseTypeReference(-baseType, dimension);
+                       type.sourceStart = typeSourceStart;
+                       type.sourceEnd = typeSourceEnd;
+                       declaration.type = type;
+               } else {
+                       declaration.type = this.copyDims(type, dimension);
+               }
+       }
+       this.variablesCounter[this.nestedType]++;
+       pushOnAstStack(declaration);
+       // recovery
+       if (this.currentElement != null) {
+               if (!(this.currentElement instanceof RecoveredType)
+                       && (this.currentToken == TokenNameDOT
+                               //|| declaration.modifiers != 0
+                               || (this.scanner.getLineNumber(declaration.type.sourceStart)
+                                               != this.scanner.getLineNumber((int) (namePosition >>> 32))))){
+                       this.lastCheckPoint = (int) (namePosition >>> 32);
+                       this.restartRecovery = true;
+                       return;
+               }
+               if (isLocalDeclaration){
+                       LocalDeclaration localDecl = (LocalDeclaration) this.astStack[this.astPtr];
+                       this.lastCheckPoint = localDecl.sourceEnd + 1;
+                       this.currentElement = this.currentElement.add(localDecl, 0);
+               } else {
+                       FieldDeclaration fieldDecl = (FieldDeclaration) this.astStack[this.astPtr];
+                       this.lastCheckPoint = fieldDecl.sourceEnd + 1;
+                       this.currentElement = this.currentElement.add(fieldDecl, 0);
+               }
+               this.lastIgnoredToken = -1;
+       }
+}
+protected void consumeEqualityExpression(int op) {
+       // EqualityExpression ::= EqualityExpression '==' RelationalExpression
+       // EqualityExpression ::= EqualityExpression '!=' RelationalExpression
+
+       //optimize the push/pop
+
+       this.expressionPtr--;
+       this.expressionLengthPtr--;
+       this.expressionStack[this.expressionPtr] =
+               new EqualExpression(
+                       this.expressionStack[this.expressionPtr],
+                       this.expressionStack[this.expressionPtr + 1],
+                       op);
+}
+protected void consumeExitTryBlock() {
+       //ExitTryBlock ::= $empty
+       if(this.currentElement != null) {
+               this.restartRecovery = true;
+       }
+}
+protected void consumeExitVariableWithInitialization() {
+       // ExitVariableWithInitialization ::= $empty
+       // do nothing by default
+       this.expressionLengthPtr--;
+       AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
+       variableDecl.initialization = this.expressionStack[this.expressionPtr--];
+       // we need to update the declarationSourceEnd of the local variable declaration to the
+       // source end position of the initialization expression
+       variableDecl.declarationSourceEnd = variableDecl.initialization.sourceEnd;
+       variableDecl.declarationEnd = variableDecl.initialization.sourceEnd;
+       
+       this.recoveryExitFromVariable();
+}
+protected void consumeExitVariableWithoutInitialization() {
+       // ExitVariableWithoutInitialization ::= $empty
+       // do nothing by default
+       
+       AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) this.astStack[this.astPtr];
+       variableDecl.declarationSourceEnd = variableDecl.declarationEnd;
+       
+       this.recoveryExitFromVariable();
+}
+protected void consumeExplicitConstructorInvocation(int flag, int recFlag) {
+
+       /* flag allows to distinguish 3 cases :
+       (0) :   
+       ExplicitConstructorInvocation ::= 'this' '(' ArgumentListopt ')' ';'
+       ExplicitConstructorInvocation ::= 'super' '(' ArgumentListopt ')' ';'
+       (1) :
+       ExplicitConstructorInvocation ::= Primary '.' 'super' '(' ArgumentListopt ')' ';'
+       ExplicitConstructorInvocation ::= Primary '.' 'this' '(' ArgumentListopt ')' ';'
+       (2) :
+       ExplicitConstructorInvocation ::= Name '.' 'super' '(' ArgumentListopt ')' ';'
+       ExplicitConstructorInvocation ::= Name '.' '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);
+       }
+       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--;
+       pushOnAstStack(this.expressionStack[this.expressionPtr--]);
+}
+protected void consumeFieldAccess(boolean isSuperAccess) {
+       // FieldAccess ::= Primary '.' 'Identifier'
+       // FieldAccess ::= 'super' '.' 'Identifier'
+
+       FieldReference fr =
+               new FieldReference(
+                       this.identifierStack[this.identifierPtr],
+                       this.identifierPositionStack[this.identifierPtr--]);
+       this.identifierLengthPtr--;
+       if (isSuperAccess) {
+               //considerates the fieldReference beginning at the 'super' .... 
+               fr.sourceStart = this.intStack[this.intPtr--];
+               fr.receiver = new SuperReference(fr.sourceStart, this.endPosition);
+               pushOnExpressionStack(fr);
+       } else {
+               //optimize push/pop
+               if ((fr.receiver = this.expressionStack[this.expressionPtr]).isThis()) {
+                       //fieldreference begins at the this
+                       fr.sourceStart = fr.receiver.sourceStart;
+               }
+               this.expressionStack[this.expressionPtr] = fr;
+       }
+}
+protected void consumeFieldDeclaration() {
+       // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+       // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+
+       /*
+       astStack : 
+       expressionStack: Expression Expression ...... Expression
+       identifierStack : type  identifier identifier ...... identifier
+       intStack : typeDim      dim        dim               dim
+        ==>
+       astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
+       expressionStack :
+       identifierStack : 
+       intStack : 
+         
+       */
+       int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
+
+       for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) {
+               FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr - i];
+               fieldDeclaration.declarationSourceEnd = this.endStatementPosition; 
+               fieldDeclaration.declarationEnd = this.endStatementPosition;    // semi-colon included
+       }
+       
+       updateSourceDeclarationParts(variableDeclaratorsCounter);
+       int endPos = flushCommentsDefinedPriorTo(this.endStatementPosition);
+       if (endPos != this.endStatementPosition) {
+               for (int i = 0; i < variableDeclaratorsCounter; i++) {
+                       FieldDeclaration fieldDeclaration = (FieldDeclaration) this.astStack[this.astPtr - i];
+                       fieldDeclaration.declarationSourceEnd = endPos;
+               }
+       }
+       // update the astStack, astPtr and astLengthStack
+       int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
+       System.arraycopy(
+               this.astStack, 
+               startIndex, 
+               this.astStack, 
+               startIndex - 1, 
+               variableDeclaratorsCounter); 
+       this.astPtr--; // remove the type reference
+       this.astLengthStack[--this.astLengthPtr] = variableDeclaratorsCounter;
+
+       // recovery
+       if (this.currentElement != null) {
+               this.lastCheckPoint = endPos + 1;
+               if (this.currentElement.parent != null && this.currentElement instanceof RecoveredField){
+                       if (!(this.currentElement instanceof RecoveredInitializer)) {
+                               this.currentElement = this.currentElement.parent;
+                       }
+               }
+               this.restartRecovery = true;
+       }
+       this.variablesCounter[this.nestedType] = 0;
+}
+protected void consumeForceNoDiet() {
+       // ForceNoDiet ::= $empty
+       this.dietInt++;
+}
+protected void consumeForInit() {
+       // ForInit ::= StatementExpressionList
+       pushOnAstLengthStack(-1);
+}
+protected void consumeFormalParameter() {
+       // FormalParameter ::= Type VariableDeclaratorId ==> false
+       // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
+       /*
+       astStack : 
+       identifierStack : type identifier
+       intStack : dim dim
+        ==>
+       astStack : Argument
+       identifierStack :  
+       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 modifierPositions = this.intStack[this.intPtr--];
+       this.intPtr--;
+       Argument arg = 
+               new Argument(
+                       identifierName, 
+                       namePositions, 
+                       type, 
+                       this.intStack[this.intPtr + 1] & ~AccDeprecated); // modifiers
+       arg.declarationSourceStart = modifierPositions;
+       pushOnAstStack(arg);
+
+       /* if incomplete method header, listLength counter will not have been reset,
+               indicating that some arguments are available on the stack */
+       this.listLength++;      
+}
+protected void consumeFormalParameterList() {
+       // FormalParameterList ::= FormalParameterList ',' FormalParameter
+       optimizedConcatNodeLists();
+}
+protected void consumeFormalParameterListopt() {
+       // FormalParameterListopt ::= $empty
+       pushOnAstLengthStack(0);
+}
+protected void consumeImportDeclarations() {
+       // ImportDeclarations ::= ImportDeclarations ImportDeclaration 
+       optimizedConcatNodeLists();
+}
+protected void consumeImportDeclarationsopt() {
+       // ImportDeclarationsopt ::= ImportDeclarations
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               this.astPtr -= length;
+               System.arraycopy(
+                       this.astStack,
+                       this.astPtr + 1,
+                       this.compilationUnit.imports = new ImportReference[length],
+                       0,
+                       length);
+       }
+}
+protected void consumeInsideCastExpression() {
+       // InsideCastExpression ::= $empty
+}
+protected void consumeInsideCastExpressionLL1() {
+       // InsideCastExpressionLL1 ::= $empty
+}
+
+protected void consumeInstanceOfExpression(int op) {
+       // RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType
+       //optimize the push/pop
+
+       //by construction, no base type may be used in getTypeReference
+       Expression exp;
+       this.expressionStack[this.expressionPtr] = exp =
+               new InstanceOfExpression(
+                       this.expressionStack[this.expressionPtr],
+                       getTypeReference(this.intStack[this.intPtr--]),
+                       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
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               //there are length declarations
+               //dispatch.....according to the type of the declarations
+               dispatchDeclarationInto(length);
+       }
+
+       TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+       
+       // mark initializers with local type mark if needed
+       markInitializersWithLocalType(typeDecl);
+
+       //convert constructor that do not have the type's name into methods
+       typeDecl.checkConstructors(this);
+       
+       //always add <clinit> (will be remove at code gen time if empty)
+       if (this.scanner.containsAssertKeyword) {
+               typeDecl.bits |= ASTNode.AddAssertionMASK;
+       }
+       typeDecl.addClinit();
+       typeDecl.bodyEnd = this.endStatementPosition;
+       if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
+               typeDecl.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+       }
+       typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition); 
+}
+protected void consumeInterfaceHeader() {
+       // InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt
+
+       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 interface header
+       this.scanner.commentPtr = -1;   
+}
+protected void consumeInterfaceHeaderExtends() {
+       // InterfaceHeaderExtends ::= 'extends' InterfaceTypeList
+       int length = this.astLengthStack[this.astLengthPtr--];
+       //super interfaces
+       this.astPtr -= length;
+       TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+       System.arraycopy(
+               this.astStack, 
+               this.astPtr + 1, 
+               typeDecl.superInterfaces = new TypeReference[length], 
+               0, 
+               length); 
+       typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;          
+       this.listLength = 0; // reset after having read super-interfaces                
+       // recovery
+       if (this.currentElement != null) { 
+               this.lastCheckPoint = typeDecl.bodyStart;
+       }
+}
+protected void consumeInterfaceHeaderName() {
+       // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
+       TypeDeclaration typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+
+       if (this.nestedMethod[this.nestedType] == 0) {
+               if (this.nestedType != 0) {
+                       typeDecl.bits |= ASTNode.IsMemberTypeMASK;
+               }
+       } else {
+               // Record that the block has a declaration for local types
+               typeDecl.bits |= ASTNode.IsLocalTypeMASK;
+               markEnclosingMemberWithLocalType();
+               blockReal();
+       }
+
+       //highlight the name of the type
+       long pos = this.identifierPositionStack[this.identifierPtr];
+       typeDecl.sourceEnd = (int) pos;
+       typeDecl.sourceStart = (int) (pos >>> 32);
+       typeDecl.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.
+       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--];
+       if (typeDecl.modifiersSourceStart >= 0) {
+               typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
+       }
+       typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+       pushOnAstStack(typeDecl);
+       this.listLength = 0; // will be updated when reading super-interfaces
+       // recovery
+       if (this.currentElement != null){ // is recovering
+               this.lastCheckPoint = typeDecl.bodyStart;
+               this.currentElement = this.currentElement.add(typeDecl, 0);
+               this.lastIgnoredToken = -1;             
+       }
+       // javadoc
+       typeDecl.javadoc = this.javadoc;
+       this.javadoc = null;
+}
+protected void consumeInterfaceMemberDeclarations() {
+       // InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration
+       concatNodeLists();
+}
+protected void consumeInterfaceMemberDeclarationsopt() {
+       // InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations
+       this.nestedType--;
+}
+protected void consumeInterfaceType() {
+       // InterfaceType ::= ClassOrInterfaceType
+       pushOnAstStack(getTypeReference(0));
+       /* if incomplete type header, listLength counter will not have been reset,
+               indicating that some interfaces are available on the stack */
+       this.listLength++;      
+}
+protected void consumeInterfaceTypeList() {
+       // InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType
+       optimizedConcatNodeLists();
+}
+protected void consumeLeftParen() {
+       // PushLPAREN ::= '('
+       pushOnIntStack(this.lParenPos);
+}
+protected void consumeLocalVariableDeclaration() {
+       // LocalVariableDeclaration ::= Modifiers Type VariableDeclarators ';'
+
+       /*
+       astStack : 
+       expressionStack: Expression Expression ...... Expression
+       identifierStack : type  identifier identifier ...... identifier
+       intStack : typeDim      dim        dim               dim
+        ==>
+       astStack : FieldDeclaration FieldDeclaration ...... FieldDeclaration
+       expressionStack :
+       identifierStack : 
+       intStack : 
+         
+       */
+       int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
+
+       // update the astStack, astPtr and astLengthStack
+       int startIndex = this.astPtr - this.variablesCounter[this.nestedType] + 1;
+       System.arraycopy(
+               this.astStack, 
+               startIndex, 
+               this.astStack, 
+               startIndex - 1, 
+               variableDeclaratorsCounter); 
+       this.astPtr--; // remove the type reference
+       this.astLengthStack[--this.astLengthPtr] = variableDeclaratorsCounter;
+       this.variablesCounter[this.nestedType] = 0;
+}
+protected void consumeLocalVariableDeclarationStatement() {
+       // LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';'
+       // see blockReal in case of change: duplicated code
+       // increment the amount of declared variables for this block
+       this.realBlockStack[this.realBlockPtr]++;
+       
+       // update source end to include the semi-colon
+       int variableDeclaratorsCounter = this.astLengthStack[this.astLengthPtr];
+       for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) {
+               LocalDeclaration localDeclaration = (LocalDeclaration) this.astStack[this.astPtr - i];
+               localDeclaration.declarationSourceEnd = this.endStatementPosition; 
+               localDeclaration.declarationEnd = this.endStatementPosition;    // semi-colon included
+       }
+
+}
+protected void consumeMethodBody() {
+       // MethodBody ::= NestedMethod '{' BlockStatementsopt '}' 
+       this.nestedMethod[this.nestedType] --;
+}
+protected void consumeMethodDeclaration(boolean isNotAbstract) {
+       // MethodDeclaration ::= MethodHeader MethodBody
+       // AbstractMethodDeclaration ::= MethodHeader ';'
+
+       /*
+       astStack : modifiers arguments throws statements
+       identifierStack : type name
+       intStack : dim dim dim
+        ==>
+       astStack : MethodDeclaration
+       identifierStack :
+       intStack : 
+       */
+
+       int length;
+       if (isNotAbstract) {
+               // pop the position of the {  (body of the method) pushed in block decl
+               this.intPtr--;
+               this.intPtr--;
+       }
+
+       int explicitDeclarations = 0;
+       Statement[] statements = null;
+       if (isNotAbstract) {
+               //statements
+               explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+               if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+                       System.arraycopy(
+                               this.astStack, 
+                               (this.astPtr -= length) + 1, 
+                               statements = new Statement[length], 
+                               0, 
+                               length); 
+               }
+       }
+
+       // now we know that we have a method declaration at the top of the ast stack
+       MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
+       md.statements = statements;
+       md.explicitDeclarations = explicitDeclarations;
+
+       // cannot be done in consumeMethodHeader because we have no idea whether or not there
+       // is a body when we reduce the method header
+       if (!isNotAbstract) { //remember the fact that the method has a semicolon body
+               md.modifiers |= AccSemicolonBody;
+       } else {
+               if (!this.diet && statements == null) {
+                       if (!containsComment(md.bodyStart, this.endPosition)) {
+                               md.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+                       }
+               }
+       }
+       // store the endPosition (position just before the '}') in case there is
+       // a trailing comment behind the end of the method
+       md.bodyEnd = this.endPosition;
+       md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+}
+protected void consumeMethodHeader() {
+       // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+       // retrieve end position of method declarator
+       AbstractMethodDeclaration method = (AbstractMethodDeclaration)this.astStack[this.astPtr];
+
+       if (this.currentToken == TokenNameLBRACE){ 
+               method.bodyStart = this.scanner.currentPosition;
+       }
+       // recovery
+       if (this.currentElement != null){
+               if (this.currentToken == TokenNameSEMICOLON){
+                       method.modifiers |= AccSemicolonBody;                   
+                       method.declarationSourceEnd = this.scanner.currentPosition-1;
+                       method.bodyEnd = this.scanner.currentPosition-1;
+                       if (this.currentElement.parseTree() == method && this.currentElement.parent != null) {
+                               this.currentElement = this.currentElement.parent;
+                       }
+               }               
+               this.restartRecovery = true; // used to avoid branching back into the regular automaton
+       }               
+}
+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 (extendedDims != 0) {
+               TypeReference returnType = md.returnType;
+               md.sourceEnd = this.endPosition;
+               int dims = returnType.dimensions() + extendedDims;
+               int baseType;
+               if ((baseType = this.identifierLengthStack[this.identifierLengthPtr + 1]) < 0) {
+                       //it was a baseType
+                       int sourceStart = returnType.sourceStart;
+                       int sourceEnd =  returnType.sourceEnd;
+                       returnType = TypeReference.baseTypeReference(-baseType, dims);
+                       returnType.sourceStart = sourceStart;
+                       returnType.sourceEnd = sourceEnd;
+                       md.returnType = returnType;
+               } else {
+                       md.returnType = this.copyDims(md.returnType, dims);
+               }
+               if (this.currentToken == TokenNameLBRACE){ 
+                       md.bodyStart = this.endPosition + 1;
+               }
+               // recovery
+               if (this.currentElement != null){
+                       this.lastCheckPoint = md.bodyStart;
+               }               
+       }
+}
+protected void consumeMethodHeaderName() {
+       // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+       MethodDeclaration 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--];
+       // 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 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 consumeMethodHeaderParameters() {
+       // MethodHeaderParameters ::= FormalParameterListopt ')'
+       int length = this.astLengthStack[this.astLengthPtr--];
+       this.astPtr -= length;
+       AbstractMethodDeclaration md = (AbstractMethodDeclaration) this.astStack[this.astPtr];
+       md.sourceEnd =  this.rParenPos;
+       //arguments
+       if (length != 0) {
+               System.arraycopy(
+                       this.astStack, 
+                       this.astPtr + 1, 
+                       md.arguments = new Argument[length], 
+                       0, 
+                       length); 
+       }
+       md.bodyStart = this.rParenPos+1;
+       this.listLength = 0; // reset listLength after having read all parameters
+       // recovery
+       if (this.currentElement != null){
+               this.lastCheckPoint = md.bodyStart;
+               if (this.currentElement.parseTree() == md) return;
+
+               // might not have been attached yet - in some constructor scenarii
+               if (md.isConstructor()){
+                       if ((length != 0)
+                               || (this.currentToken == TokenNameLBRACE) 
+                               || (this.currentToken == TokenNamethrows)){
+                               this.currentElement = this.currentElement.add(md, 0);
+                               this.lastIgnoredToken = -1;
+                       }       
+               }       
+       }       
+}
+protected void consumeMethodHeaderThrowsClause() {
+       // MethodHeaderThrowsClause ::= 'throws' ClassTypeList
+       int length = this.astLengthStack[this.astLengthPtr--];
+       this.astPtr -= length;
+       AbstractMethodDeclaration md = (AbstractMethodDeclaration) this.astStack[this.astPtr];
+       System.arraycopy(
+               this.astStack, 
+               this.astPtr + 1, 
+               md.thrownExceptions = new TypeReference[length], 
+               0, 
+               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        
+       // recovery
+       if (this.currentElement != null){
+               this.lastCheckPoint = md.bodyStart;
+       }               
+}
+protected void consumeMethodInvocationName() {
+       // MethodInvocation ::= Name '(' ArgumentListopt ')'
+
+       // when the name is only an identifier...we have a message send to "this" (implicit)
+
+       MessageSend m = newMessageSend();
+       m.sourceEnd = this.rParenPos;
+       m.sourceStart = 
+               (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); 
+       m.selector = this.identifierStack[this.identifierPtr--];
+       if (this.identifierLengthStack[this.identifierLengthPtr] == 1) {
+               m.receiver = ThisReference.implicitThis();
+               this.identifierLengthPtr--;
+       } else {
+               this.identifierLengthStack[this.identifierLengthPtr]--;
+               m.receiver = getUnspecifiedReference();
+               m.sourceStart = m.receiver.sourceStart;         
+       }
+       pushOnExpressionStack(m);
+}
+protected void consumeMethodInvocationPrimary() {
+       //optimize the push/pop
+       //MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
+
+       MessageSend m = newMessageSend();
+       m.sourceStart = 
+               (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32); 
+       m.selector = this.identifierStack[this.identifierPtr--];
+       this.identifierLengthPtr--;
+       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 ')'
+
+       MessageSend m = newMessageSend();
+       m.sourceStart = this.intStack[this.intPtr--];
+       m.sourceEnd = this.rParenPos;
+       m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
+       m.selector = this.identifierStack[this.identifierPtr--];
+       this.identifierLengthPtr--;
+       m.receiver = new SuperReference(m.sourceStart, this.endPosition);
+       pushOnExpressionStack(m);
+}
+protected void consumeModifiers() {
+       int savedModifiersSourceStart = this.modifiersSourceStart;      
+       checkComment(); // might update modifiers with AccDeprecated
+       pushOnIntStack(this.modifiers); // modifiers
+       if (this.modifiersSourceStart >= savedModifiersSourceStart) {
+               this.modifiersSourceStart = savedModifiersSourceStart;
+       }
+       pushOnIntStack(this.modifiersSourceStart);
+       resetModifiers();
+}
+protected void consumeNestedMethod() {
+       // NestedMethod ::= $empty
+       jumpOverMethodBody();
+       this.nestedMethod[this.nestedType] ++;
+       pushOnIntStack(this.scanner.currentPosition);
+       consumeOpenBlock();
+}
+protected void consumeNestedType() {
+       // NestedType ::= $empty
+       int length = this.nestedMethod.length;
+       if (++this.nestedType >= length) {
+               System.arraycopy(
+                       this.nestedMethod, 0,
+                       this.nestedMethod = new int[length + 30], 0,
+                       length);
+               // increase the size of the variablesCounter as well. It has to be consistent with the size of the nestedMethod collection
+               System.arraycopy(
+                       this.variablesCounter, 0,
+                       this.variablesCounter = new int[length + 30], 0,
+                       length);
+       }
+       this.nestedMethod[this.nestedType] = 0;
+       this.variablesCounter[this.nestedType] = 0;
+}
+protected void consumeOneDimLoop() {
+       // OneDimLoop ::= '[' ']'
+       this.dimensions++;
+}
+protected void consumeOnlySynchronized() {
+       // OnlySynchronized ::= 'synchronized'
+       pushOnIntStack(this.synchronizedBlockSourceStart);
+       resetModifiers();
+}
+protected void consumeOpenBlock() {
+       // OpenBlock ::= $empty
+
+       pushOnIntStack(this.scanner.startPosition);
+       int stackLength = this.realBlockStack.length;
+       if (++this.realBlockPtr >= stackLength) {
+               System.arraycopy(
+                       this.realBlockStack, 0,
+                       this.realBlockStack = new int[stackLength + StackIncrement], 0,
+                       stackLength);
+       }
+       this.realBlockStack[this.realBlockPtr] = 0;
+}
+protected void consumePackageDeclaration() {
+       // PackageDeclaration ::= 'package' Name ';'
+       /* build an ImportRef build from the last name 
+       stored in the identifier stack. */
+
+       ImportReference impt = this.compilationUnit.currentPackage;
+       // flush comments defined prior to import statements
+       impt.declarationEnd = this.endStatementPosition;
+       impt.declarationSourceEnd = this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd);
+}
+protected void consumePackageDeclarationName() {
+       // PackageDeclarationName ::= '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); 
+       this.compilationUnit.currentPackage = 
+               impt = new ImportReference(tokens, positions, true, AccDefault); 
+
+       if (this.currentToken == TokenNameSEMICOLON){
+               impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+       } else {
+               impt.declarationSourceEnd = impt.sourceEnd;
+       }
+       impt.declarationEnd = impt.declarationSourceEnd;
+       //endPosition is just before the ;
+       impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+       // 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 ::= 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(
+               new QualifiedThisReference(
+                       getTypeReference(0),
+                       this.intStack[this.intPtr--],
+                       this.endPosition));
+}
+protected void consumePrimaryNoNewArrayPrimitiveType() {
+       // PrimaryNoNewArray ::= PrimitiveType '.' 'class'
+       this.intPtr--;
+       pushOnExpressionStack(
+               new ClassLiteralAccess(this.intStack[this.intPtr--],
+               getTypeReference(0)));
+}
+protected void consumePrimaryNoNewArrayThis() {
+       // PrimaryNoNewArray ::= 'this'
+       pushOnExpressionStack(new ThisReference(this.intStack[this.intPtr--], this.endPosition));
+}
+protected void consumePrimitiveType() {
+       // Type ::= PrimitiveType
+       pushOnIntStack(0);
+}
+protected void consumePushModifiers() {
+       pushOnIntStack(this.modifiers); // modifiers
+       pushOnIntStack(this.modifiersSourceStart);
+       resetModifiers();
+}
+protected void consumePushPosition() {
+       // for source managment purpose
+       // PushPosition ::= $empty
+       pushOnIntStack(this.endPosition);
+}
+protected void consumeQualifiedName() {
+       // QualifiedName ::= Name '.' SimpleName 
+       /*back from the recursive loop of QualifiedName.
+       Updates identifier length into the length stack*/
+
+       this.identifierLengthStack[--this.identifierLengthPtr]++;
+}
+protected void consumeReferenceType() {
+       // ReferenceType ::= ClassOrInterfaceType
+       pushOnIntStack(0);
+}
+protected void consumeRestoreDiet() {
+       // RestoreDiet ::= $empty
+       this.dietInt--;
+}
+protected void consumeRightParen() {
+       // PushRPAREN ::= ')'
+       pushOnIntStack(this.rParenPos);
+}
+// 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 ;
+
+       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 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 426 : // System.out.println("ForInitopt ::=");  //$NON-NLS-1$
+               consumeEmptyForInitopt();  
+               break ;
+               
+       case 428 : // System.out.println("ForUpdateopt ::=");  //$NON-NLS-1$
+               consumeEmptyForUpdateopt();  
+               break ;
+               
+       case 432 : // System.out.println("Catchesopt ::=");  //$NON-NLS-1$
+               consumeEmptyCatchesopt();  
+               break ;
+               
+       }
+} 
+protected void consumeSimpleAssertStatement() {
+       // AssertStatement ::= 'assert' Expression ';'
+       this.expressionLengthPtr--;
+       pushOnAstStack(new AssertStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));  
+}
+       
+protected void consumeSingleTypeImportDeclaration() {
+       // SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+
+       ImportReference impt = (ImportReference) this.astStack[this.astPtr];
+       // flush comments defined prior to import statements
+       impt.declarationEnd = this.endStatementPosition;
+       impt.declarationSourceEnd = 
+               this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
+
+       // recovery
+       if (this.currentElement != null) {
+               this.lastCheckPoint = impt.declarationSourceEnd + 1;
+               this.currentElement = this.currentElement.add(impt, 0);
+               this.lastIgnoredToken = -1;
+               this.restartRecovery = true; 
+               // used to avoid branching back into the regular automaton
+       }
+}
+protected void consumeSingleTypeImportDeclarationName() {
+       // SingleTypeImportDeclarationName ::= 'import' Name
+       /* push an ImportRef build from the last name 
+       stored in the identifier stack. */
+
+       ImportReference impt;
+       int length;
+       char[][] tokens = new char[length = this.identifierLengthStack[this.identifierLengthPtr--]][];
+       this.identifierPtr -= length;
+       long[] positions = new long[length];
+       System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+       System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+       pushOnAstStack(impt = new ImportReference(tokens, positions, false, AccDefault));
+
+       if (this.currentToken == TokenNameSEMICOLON){
+               impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+       } else {
+               impt.declarationSourceEnd = impt.sourceEnd;
+       }
+       impt.declarationEnd = impt.declarationSourceEnd;
+       //endPosition is just before the ;
+       impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+       // 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 consumeStatementBreak() {
+       // BreakStatement ::= 'break' ';'
+       // break pushs a position on 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
+
+       pushOnAstStack(
+               new BreakStatement(
+                       this.identifierStack[this.identifierPtr--],
+                       this.intStack[this.intPtr--],
+                       this.endPosition)); 
+       this.identifierLengthPtr--;
+}
+protected void consumeStatementCatch() {
+       // CatchClause ::= 'catch' '(' FormalParameter ')'    Block
+
+       //catch are stored directly into the Try
+       //has they always comes two by two....
+       //we remove one entry from the astlengthPtr.
+       //The construction of the try statement must
+       //then fetch the catches using  2*i and 2*i + 1
+
+       this.astLengthPtr--;
+       this.listLength = 0; // reset formalParameter counter (incremented for catch variable)
+}
+protected void consumeStatementContinue() {
+       // ContinueStatement ::= 'continue' ';'
+       // continue pushs a position on intStack in case there is no label
+
+       pushOnAstStack(
+               new ContinueStatement(
+                       null,
+                       this.intStack[this.intPtr--],
+                       this.endPosition));
+}
+protected void consumeStatementContinueWithLabel() {
+       // ContinueStatement ::= 'continue' Identifier ';'
+       // continue pushs a position on intStack in case there is no label
+
+       pushOnAstStack(
+               new ContinueStatement(
+                       this.identifierStack[this.identifierPtr--], 
+                       this.intStack[this.intPtr--], 
+                       this.endPosition)); 
+       this.identifierLengthPtr--;
+}
+protected void consumeStatementDo() {
+       // DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'
+
+       //the 'while' pushes a value on intStack that we need to remove
+       this.intPtr--;
+
+       Statement statement = (Statement) this.astStack[this.astPtr];
+       this.expressionLengthPtr--;
+       this.astStack[this.astPtr] = 
+               new DoStatement(
+                       this.expressionStack[this.expressionPtr--], 
+                       statement, 
+                       this.intStack[this.intPtr--], 
+                       this.endPosition); 
+}
+protected void consumeStatementExpressionList() {
+       // StatementExpressionList ::= StatementExpressionList ',' StatementExpression
+       concatExpressionLists();
+}
+protected void consumeStatementFor() {
+       // ForStatement ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' Statement
+       // ForStatementNoShortIf ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' StatementNoShortIf
+
+       int length;
+       Expression cond = null;
+       Statement[] inits, updates;
+       boolean scope = true;
+
+       //statements
+       this.astLengthPtr--;
+       Statement statement = (Statement) this.astStack[this.astPtr--];
+
+       //updates are on the expresion stack
+       if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) == 0) {
+               updates = null;
+       } else {
+               this.expressionPtr -= length;
+               System.arraycopy(
+                       this.expressionStack, 
+                       this.expressionPtr + 1, 
+                       updates = new Statement[length], 
+                       0, 
+                       length); 
+       }
+
+       if (this.expressionLengthStack[this.expressionLengthPtr--] != 0)
+               cond = this.expressionStack[this.expressionPtr--];
+
+       //inits may be on two different stacks
+       if ((length = this.astLengthStack[this.astLengthPtr--]) == 0) {
+               inits = null;
+               scope = false;
+       } else {
+               if (length == -1) { //on expressionStack
+                       scope = false;
+                       length = this.expressionLengthStack[this.expressionLengthPtr--];
+                       this.expressionPtr -= length;
+                       System.arraycopy(
+                               this.expressionStack, 
+                               this.expressionPtr + 1, 
+                               inits = new Statement[length], 
+                               0, 
+                               length); 
+               } else { //on astStack
+                       this.astPtr -= length;
+                       System.arraycopy(
+                               this.astStack, 
+                               this.astPtr + 1, 
+                               inits = new Statement[length], 
+                               0, 
+                               length); 
+               }
+       }
+       pushOnAstStack(
+               new ForStatement(
+                       inits, 
+                       cond, 
+                       updates, 
+                       statement, 
+                       scope, 
+                       this.intStack[this.intPtr--], 
+                       this.endStatementPosition)); 
+}
+protected void consumeStatementIfNoElse() {
+       // IfThenStatement ::=  'if' '(' Expression ')' Statement
+
+       //optimize the push/pop
+       this.expressionLengthPtr--;
+       Statement thenStatement = (Statement) this.astStack[this.astPtr];
+       this.astStack[this.astPtr] = 
+               new IfStatement(
+                       this.expressionStack[this.expressionPtr--], 
+                       thenStatement, 
+                       this.intStack[this.intPtr--], 
+                       this.endStatementPosition); 
+}
+protected void consumeStatementIfWithElse() {
+       // IfThenElseStatement ::=  'if' '(' Expression ')' StatementNoShortIf 'else' Statement
+       // IfThenElseStatementNoShortIf ::=  'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf
+
+       this.expressionLengthPtr--;
+
+       // optimized {..., Then, Else } ==> {..., If }
+       this.astLengthPtr--;
+
+       //optimize the push/pop
+       this.astStack[--this.astPtr] = 
+               new IfStatement(
+                       this.expressionStack[this.expressionPtr--], 
+                       (Statement) this.astStack[this.astPtr], 
+                       (Statement) this.astStack[this.astPtr + 1], 
+                       this.intStack[this.intPtr--], 
+                       this.endStatementPosition); 
+}
+protected void consumeStatementLabel() {
+       // LabeledStatement ::= 'Identifier' ':' Statement
+       // LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf
+
+       //optimize push/pop
+       Statement stmt = (Statement) this.astStack[this.astPtr];
+       this.astStack[this.astPtr] = 
+               new LabeledStatement(
+                       this.identifierStack[this.identifierPtr], 
+                       stmt, 
+                       (int) (this.identifierPositionStack[this.identifierPtr--] >>> 32), 
+                       this.endStatementPosition); 
+       this.identifierLengthPtr--;
+}
+protected void consumeStatementReturn() {
+       // ReturnStatement ::= 'return' Expressionopt ';'
+       // return pushs a position on intStack in case there is no expression
+
+       if (this.expressionLengthStack[this.expressionLengthPtr--] != 0) {
+               pushOnAstStack(
+                       new ReturnStatement(
+                               this.expressionStack[this.expressionPtr--], 
+                               this.intStack[this.intPtr--], 
+                               this.endPosition)
+               );
+       } else {
+               pushOnAstStack(new ReturnStatement(null, this.intStack[this.intPtr--], this.endPosition));
+       }
+}
+protected void consumeStatementSwitch() {
+       // SwitchStatement ::= 'switch' OpenBlock '(' Expression ')' SwitchBlock
+
+       //OpenBlock just makes the semantic action blockStart()
+       //the block is inlined but a scope need to be created
+       //if some declaration occurs.
+
+       int length;
+       SwitchStatement switchStatement = new SwitchStatement();
+       this.expressionLengthPtr--;
+       switchStatement.expression = this.expressionStack[this.expressionPtr--];
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               this.astPtr -= length;
+               System.arraycopy(
+                       this.astStack, 
+                       this.astPtr + 1, 
+                       switchStatement.statements = new Statement[length], 
+                       0, 
+                       length); 
+       }
+       switchStatement.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+       pushOnAstStack(switchStatement);
+       switchStatement.blockStart = this.intStack[this.intPtr--];
+       switchStatement.sourceStart = this.intStack[this.intPtr--];
+       switchStatement.sourceEnd = this.endStatementPosition;
+       if (length == 0 && !containsComment(switchStatement.blockStart, switchStatement.sourceEnd)) {
+               switchStatement.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+       }
+}
+protected void consumeStatementSynchronized() {
+       // SynchronizedStatement ::= OnlySynchronized '(' Expression ')' Block
+       //optimize the push/pop
+
+       if (this.astLengthStack[this.astLengthPtr] == 0) {
+               this.astLengthStack[this.astLengthPtr] = 1;
+               this.expressionLengthPtr--;
+               this.astStack[++this.astPtr] = 
+                       new SynchronizedStatement(
+                               this.expressionStack[this.expressionPtr--], 
+                               null, 
+                               this.intStack[this.intPtr--], 
+                               this.endStatementPosition); 
+       } else {
+               this.expressionLengthPtr--;
+               this.astStack[this.astPtr] = 
+                       new SynchronizedStatement(
+                               this.expressionStack[this.expressionPtr--], 
+                               (Block) this.astStack[this.astPtr], 
+                               this.intStack[this.intPtr--], 
+                               this.endStatementPosition); 
+       }
+       resetModifiers();
+}
+protected void consumeStatementThrow() {
+       // ThrowStatement ::= 'throw' Expression ';'
+       this.expressionLengthPtr--;
+       pushOnAstStack(new ThrowStatement(this.expressionStack[this.expressionPtr--], this.intStack[this.intPtr--]));
+}
+protected void consumeStatementTry(boolean withFinally) {
+       //TryStatement ::= 'try'  Block Catches
+       //TryStatement ::= 'try'  Block Catchesopt Finally
+
+       int length;
+       TryStatement tryStmt = new TryStatement();
+       //finally
+       if (withFinally) {
+               this.astLengthPtr--;
+               tryStmt.finallyBlock = (Block) this.astStack[this.astPtr--];
+       }
+       //catches are handle by two <argument-block> [see statementCatch]
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               if (length == 1) {
+                       tryStmt.catchBlocks = new Block[] {(Block) this.astStack[this.astPtr--]};
+                       tryStmt.catchArguments = new Argument[] {(Argument) this.astStack[this.astPtr--]};
+               } else {
+                       Block[] bks = (tryStmt.catchBlocks = new Block[length]);
+                       Argument[] args = (tryStmt.catchArguments = new Argument[length]);
+                       while (length-- > 0) {
+                               bks[length] = (Block) this.astStack[this.astPtr--];
+                               args[length] = (Argument) this.astStack[this.astPtr--];
+                       }
+               }
+       }
+       //try
+       this.astLengthPtr--;
+       tryStmt.tryBlock = (Block) this.astStack[this.astPtr--];
+
+       //positions
+       tryStmt.sourceEnd = this.endStatementPosition;
+       tryStmt.sourceStart = this.intStack[this.intPtr--];
+       pushOnAstStack(tryStmt);
+}
+protected void consumeStatementWhile() {
+       // WhileStatement ::= 'while' '(' Expression ')' Statement
+       // WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf
+
+       this.expressionLengthPtr--;
+       Statement statement = (Statement) this.astStack[this.astPtr];
+       this.astStack[this.astPtr] = 
+               new WhileStatement(
+                       this.expressionStack[this.expressionPtr--], 
+                       statement, 
+                       this.intStack[this.intPtr--], 
+                       this.endStatementPosition); 
+}
+protected void consumeStaticInitializer() {
+       // StaticInitializer ::=  StaticOnly Block
+       //push an Initializer
+       //optimize the push/pop
+       Block block = (Block) this.astStack[this.astPtr];
+       if (this.diet) block.bits &= ~ASTNode.UndocumentedEmptyBlockMASK; // clear bit set since was diet
+       Initializer initializer = new Initializer(block, AccStatic);
+       this.astStack[this.astPtr] = initializer;
+       initializer.sourceEnd = this.endStatementPosition;      
+       initializer.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+       this.nestedMethod[this.nestedType] --;
+       initializer.declarationSourceStart = this.intStack[this.intPtr--];
+       initializer.bodyStart = this.intStack[this.intPtr--];
+       initializer.bodyEnd = this.endPosition;
+       // doc comment
+       initializer.javadoc = this.javadoc;
+       this.javadoc = null;
+       
+       // recovery
+       if (this.currentElement != null){
+               this.lastCheckPoint = initializer.declarationSourceEnd;
+               this.currentElement = this.currentElement.add(initializer, 0);
+               this.lastIgnoredToken = -1;
+       }
+}
+protected void consumeStaticOnly() {
+       // StaticOnly ::= 'static'
+       int savedModifiersSourceStart = this.modifiersSourceStart;
+       checkComment(); // might update declaration source start
+       if (this.modifiersSourceStart >= savedModifiersSourceStart) {
+               this.modifiersSourceStart = savedModifiersSourceStart;
+       }
+       pushOnIntStack(this.scanner.currentPosition);
+       pushOnIntStack(
+               this.modifiersSourceStart >= 0 ? this.modifiersSourceStart : this.scanner.startPosition);
+       jumpOverMethodBody();
+       this.nestedMethod[this.nestedType]++;
+       resetModifiers();
+
+       // recovery
+       if (this.currentElement != null){
+               this.recoveredStaticInitializerStart = this.intStack[this.intPtr]; // remember start position only for static initializers
+       }
+}
+protected void consumeSwitchBlock() {
+       // SwitchBlock ::= '{' SwitchBlockStatements SwitchLabels '}'
+       concatNodeLists();
+}
+protected void consumeSwitchBlockStatement() {
+       // SwitchBlockStatement ::= SwitchLabels BlockStatements
+       concatNodeLists();
+}
+protected void consumeSwitchBlockStatements() {
+       // SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement
+       concatNodeLists();
+}
+protected void consumeSwitchLabels() {
+       // SwitchLabels ::= SwitchLabels SwitchLabel
+       optimizedConcatNodeLists();
+}
+protected void consumeToken(int type) {
+       /* remember the last consumed value */
+       /* try to minimize the number of build values */
+       checkNonExternalizedStringLiteral();
+//     // clear the commentPtr of the scanner in case we read something different from a modifier
+//     switch(type) {
+//             case TokenNameabstract :
+//             case TokenNamestrictfp :
+//             case TokenNamefinal :
+//             case TokenNamenative :
+//             case TokenNameprivate :
+//             case TokenNameprotected :
+//             case TokenNamepublic :
+//             case TokenNametransient :
+//             case TokenNamevolatile :
+//             case TokenNamestatic :
+//             case TokenNamesynchronized :
+//                     break;
+//             default:
+//                     this.scanner.commentPtr = -1;
+//     }
+       //System.out.println(this.scanner.toStringAction(type));
+       switch (type) {
+               case TokenNameIdentifier :
+                       pushIdentifier();
+                       if (this.scanner.useAssertAsAnIndentifier) {
+                               long positions = this.identifierPositionStack[this.identifierPtr];
+                               problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions);
+                       }
+//                     this.scanner.commentPtr = -1;
+                       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);
+                       break;
+               case TokenNamestrictfp :
+                       checkAndSetModifiers(AccStrictfp);
+                       break;
+               case TokenNamefinal :
+                       checkAndSetModifiers(AccFinal);
+                       break;
+               case TokenNamenative :
+                       checkAndSetModifiers(AccNative);
+                       break;
+               case TokenNameprivate :
+                       checkAndSetModifiers(AccPrivate);
+                       break;
+               case TokenNameprotected :
+                       checkAndSetModifiers(AccProtected);
+                       break;
+               case TokenNamepublic :
+                       checkAndSetModifiers(AccPublic);
+                       break;
+               case TokenNametransient :
+                       checkAndSetModifiers(AccTransient);
+                       break;
+               case TokenNamevolatile :
+                       checkAndSetModifiers(AccVolatile);
+                       break;
+               case TokenNamestatic :
+                       checkAndSetModifiers(AccStatic);
+                       break;
+               case TokenNamesynchronized :
+                       this.synchronizedBlockSourceStart = this.scanner.startPosition; 
+                       checkAndSetModifiers(AccSynchronized);
+                       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
+               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 :
+                       pushOnExpressionStack(
+                               new IntLiteral(
+                                       this.scanner.getCurrentTokenSource(), 
+                                       this.scanner.startPosition, 
+                                       this.scanner.currentPosition - 1)); 
+//                     this.scanner.commentPtr = -1;
+                       break;
+               case TokenNameLongLiteral :
+                       pushOnExpressionStack(
+                               new LongLiteral(
+                                       this.scanner.getCurrentTokenSource(), 
+                                       this.scanner.startPosition, 
+                                       this.scanner.currentPosition - 1)); 
+//                     this.scanner.commentPtr = -1;
+                       break;
+               case TokenNameFloatingPointLiteral :
+                       pushOnExpressionStack(
+                               new FloatLiteral(
+                                       this.scanner.getCurrentTokenSource(), 
+                                       this.scanner.startPosition, 
+                                       this.scanner.currentPosition - 1)); 
+//                     this.scanner.commentPtr = -1;
+                       break;
+               case TokenNameDoubleLiteral :
+                       pushOnExpressionStack(
+                               new DoubleLiteral(
+                                       this.scanner.getCurrentTokenSource(), 
+                                       this.scanner.startPosition, 
+                                       this.scanner.currentPosition - 1)); 
+//                     this.scanner.commentPtr = -1;
+                       break;
+               case TokenNameCharacterLiteral :
+                       pushOnExpressionStack(
+                               new CharLiteral(
+                                       this.scanner.getCurrentTokenSource(), 
+                                       this.scanner.startPosition, 
+                                       this.scanner.currentPosition - 1)); 
+//                     this.scanner.commentPtr = -1;
+                       break;
+               case TokenNameStringLiteral :
+                       StringLiteral stringLiteral = new StringLiteral(
+                                       this.scanner.getCurrentTokenSourceString(), 
+                                       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(
+                               new TrueLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1)); 
+                       break;
+               case TokenNamenull :
+                       pushOnExpressionStack(
+                               new NullLiteral(this.scanner.startPosition, this.scanner.currentPosition - 1)); 
+                       break;
+                       //============================
+               case TokenNamesuper :
+               case TokenNamethis :
+                       this.endPosition = this.scanner.currentPosition - 1;
+                       pushOnIntStack(this.scanner.startPosition);
+                       break;
+               case TokenNameassert :
+               case TokenNameimport :
+               case TokenNamepackage :
+               case TokenNamethrow :
+               case TokenNamedo :
+               case TokenNameif :
+               case TokenNamefor :
+               case TokenNameswitch :
+               case TokenNametry :
+               case TokenNamewhile :
+               case TokenNamebreak :
+               case TokenNamecontinue :
+               case TokenNamereturn :
+               case TokenNamecase :
+                       pushOnIntStack(this.scanner.startPosition);
+                       break;
+               case TokenNamenew :
+                       // https://bugs.eclipse.org/bugs/show_bug.cgi?id=40954
+                       resetModifiers();
+                       pushOnIntStack(this.scanner.startPosition);
+                       break;
+               case TokenNameclass :
+                       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 :
+               case TokenNamePLUS :
+               case TokenNameMINUS :
+               case TokenNameNOT :
+               case TokenNameTWIDDLE :
+                       this.endPosition = this.scanner.startPosition;
+                       break;
+               case TokenNamePLUS_PLUS :
+               case TokenNameMINUS_MINUS :
+                       this.endPosition = this.scanner.startPosition;
+                       this.endStatementPosition = this.scanner.currentPosition - 1;
+                       break;
+               case TokenNameRBRACE:
+               case TokenNameSEMICOLON :
+                       this.endStatementPosition = this.scanner.currentPosition - 1;
+                       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 :
+                       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 TokenNameCOMMA :
+                       //  case TokenNameCOLON  :
+                       //  case TokenNameEQUAL  :
+                       //  case TokenNameLBRACKET  :
+                       //  case TokenNameDOT :
+                       //  case TokenNameERROR :
+                       //  case TokenNameEOF  :
+                       //  case TokenNamecase  :
+                       //  case TokenNamecatch  :
+                       //  case TokenNameelse  :
+                       //  case TokenNameextends  :
+                       //  case TokenNamefinally  :
+                       //  case TokenNameimplements  :
+                       //  case TokenNamethrows  :
+                       //  case TokenNameinstanceof  :
+                       //  case TokenNameEQUAL_EQUAL  :
+                       //  case TokenNameLESS_EQUAL  :
+                       //  case TokenNameGREATER_EQUAL  :
+                       //  case TokenNameNOT_EQUAL  :
+                       //  case TokenNameLEFT_SHIFT  :
+                       //  case TokenNameRIGHT_SHIFT  :
+                       //  case TokenNameUNSIGNED_RIGHT_SHIFT :
+                       //  case TokenNamePLUS_EQUAL  :
+                       //  case TokenNameMINUS_EQUAL  :
+                       //  case TokenNameMULTIPLY_EQUAL  :
+                       //  case TokenNameDIVIDE_EQUAL  :
+                       //  case TokenNameAND_EQUAL  :
+                       //  case TokenNameOR_EQUAL  :
+                       //  case TokenNameXOR_EQUAL  :
+                       //  case TokenNameREMAINDER_EQUAL  :
+                       //  case TokenNameLEFT_SHIFT_EQUAL  :
+                       //  case TokenNameRIGHT_SHIFT_EQUAL  :
+                       //  case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL  :
+                       //  case TokenNameOR_OR  :
+                       //  case TokenNameAND_AND  :
+                       //  case TokenNameREMAINDER :
+                       //  case TokenNameXOR  :
+                       //  case TokenNameAND  :
+                       //  case TokenNameMULTIPLY :
+                       //  case TokenNameOR  :
+                       //  case TokenNameDIVIDE :
+                       //  case TokenNameGREATER  :
+                       //  case TokenNameLESS  :
+       }
+}
+protected void consumeTypeDeclarations() {
+       // TypeDeclarations ::= TypeDeclarations TypeDeclaration
+       concatNodeLists();
+}
+protected void consumeTypeDeclarationsopt() {
+       // TypeDeclarationsopt ::= TypeDeclarations
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               this.astPtr -= length;
+               System.arraycopy(this.astStack, this.astPtr + 1, this.compilationUnit.types = new TypeDeclaration[length], 0, length);
+       }
+}
+protected void consumeTypeImportOnDemandDeclaration() {
+       // TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'
+
+       ImportReference impt = (ImportReference) this.astStack[this.astPtr];
+       // flush comments defined prior to import statements
+       impt.declarationEnd = this.endStatementPosition;
+       impt.declarationSourceEnd = 
+               this.flushCommentsDefinedPriorTo(impt.declarationSourceEnd); 
+
+       // recovery
+       if (this.currentElement != null) {
+               this.lastCheckPoint = impt.declarationSourceEnd + 1;
+               this.currentElement = this.currentElement.add(impt, 0);
+               this.restartRecovery = true;
+               this.lastIgnoredToken = -1;
+               // used to avoid branching back into the regular automaton
+       }
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+       // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+       /* push an ImportRef build from the last name 
+       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, AccDefault));
+
+       if (this.currentToken == TokenNameSEMICOLON){
+               impt.declarationSourceEnd = this.scanner.currentPosition - 1;
+       } else {
+               impt.declarationSourceEnd = impt.sourceEnd;
+       }
+       impt.declarationEnd = impt.declarationSourceEnd;
+       //endPosition is just before the ;
+       impt.declarationSourceStart = this.intStack[this.intPtr--];
+
+       // 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 consumeUnaryExpression(int op) {
+       // UnaryExpression ::= '+' PushPosition UnaryExpression
+       // UnaryExpression ::= '-' PushPosition UnaryExpression
+       // UnaryExpressionNotPlusMinus ::= '~' PushPosition UnaryExpression
+       // UnaryExpressionNotPlusMinus ::= '!' PushPosition UnaryExpression
+
+       //optimize the push/pop
+
+       //handle manually the -2147483648 while it is not a real
+       //computation of an - and 2147483648 (notice that 2147483648
+       //is Integer.MAX_VALUE+1.....)
+       //Same for -9223372036854775808L ............
+
+       //intStack have the position of the operator
+
+       Expression r, exp = this.expressionStack[this.expressionPtr];
+       if (op == MINUS) {
+               if ((exp instanceof IntLiteral) && (((IntLiteral) exp).mayRepresentMIN_VALUE())) {
+                       r = this.expressionStack[this.expressionPtr] = new IntLiteralMinValue();
+               } else {
+                       if ((exp instanceof LongLiteral) && (((LongLiteral) exp).mayRepresentMIN_VALUE())) {
+                               r = this.expressionStack[this.expressionPtr] = new LongLiteralMinValue();
+                       } else {
+                               r = this.expressionStack[this.expressionPtr] = new UnaryExpression(exp, op);
+                       }
+               }
+       } else {
+               r = this.expressionStack[this.expressionPtr] = new UnaryExpression(exp, op);
+       }
+       r.sourceStart = this.intStack[this.intPtr--];
+       r.sourceEnd = exp.sourceEnd;
+}
+protected void consumeUnaryExpression(int op, boolean post) {
+       // PreIncrementExpression ::= '++' PushPosition UnaryExpression
+       // PreDecrementExpression ::= '--' PushPosition UnaryExpression
+
+       // ++ and -- operators
+       //optimize the push/pop
+
+       //intStack has the position of the operator when prefix
+
+       Expression leftHandSide = this.expressionStack[this.expressionPtr];
+       if (leftHandSide instanceof Reference) {
+               // ++foo()++ is unvalid 
+               if (post) {
+                       this.expressionStack[this.expressionPtr] = 
+                               new PostfixExpression(
+                                       leftHandSide,
+                                       IntLiteral.One,
+                                       op,
+                                       this.endStatementPosition); 
+               } else {
+                       this.expressionStack[this.expressionPtr] = 
+                               new PrefixExpression(
+                                       leftHandSide,
+                                       IntLiteral.One,
+                                       op,
+                                       this.intStack[this.intPtr--]); 
+               }
+       } else {
+               //the ++ or the -- is NOT taken into account if code gen proceeds
+               if (!post) {
+                       this.intPtr--;
+               }
+               problemReporter().invalidUnaryExpression(leftHandSide);
+       }
+}
+protected void consumeVariableDeclarators() {
+       // VariableDeclarators ::= VariableDeclarators ',' VariableDeclarator
+       optimizedConcatNodeLists();
+}
+protected void consumeVariableInitializers() {
+       // VariableInitializers ::= VariableInitializers ',' VariableInitializer
+       concatExpressionLists();
+}
+/**
+ * Given the current comment stack, answer whether some comment is available in a certain exclusive range
+ * 
+ * @param sourceStart int
+ * @param sourceEnd int
+ * @return boolean
+ */
+public boolean containsComment(int sourceStart, int sourceEnd) {
+       int iComment = this.scanner.commentPtr;
+       for (; iComment >= 0; iComment--) {
+               int commentStart = this.scanner.commentStarts[iComment];
+               // ignore comments before start
+               if (commentStart < sourceStart) continue;
+               // ignore comments after end
+               if (commentStart > sourceEnd) continue;
+               return true;
+       }
+       return false;
+}
+public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, CompilationResult compilationResult) {
+       MethodDeclaration m = new MethodDeclaration(compilationResult);
+       m.sourceStart = c.sourceStart;
+       m.sourceEnd = c.sourceEnd;
+       m.bodyStart = c.bodyStart;
+       m.bodyEnd = c.bodyEnd;
+       m.declarationSourceEnd = c.declarationSourceEnd;
+       m.declarationSourceStart = c.declarationSourceStart;
+       m.selector = c.selector;
+       m.statements = c.statements;
+       m.modifiers = c.modifiers;
+       m.arguments = c.arguments;
+       m.thrownExceptions = c.thrownExceptions;
+       m.explicitDeclarations = c.explicitDeclarations;
+       m.returnType = null;
+       return m;
+}
+protected TypeReference copyDims(TypeReference typeRef, int dim) {
+       return typeRef.copyDims(dim);
+}
+protected FieldDeclaration createFieldDeclaration(char[] fieldDeclarationName, int sourceStart, int sourceEnd) {
+       return new FieldDeclaration(fieldDeclarationName, sourceStart, sourceEnd);
+}
+
+protected LocalDeclaration createLocalDeclaration(char[] localDeclarationName, int sourceStart, int sourceEnd) {
+       return new LocalDeclaration(localDeclarationName, sourceStart, sourceEnd);
+}
+
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
+
+       CompilationUnitDeclaration parsedUnit;
+       boolean old = this.diet;
+       try {
+               this.diet = true;
+               parsedUnit = parse(sourceUnit, compilationResult);
+       }
+       finally {
+               this.diet = old;
+       }
+       return parsedUnit;
+}
+protected void dispatchDeclarationInto(int length) {
+       /* they are length on astStack that should go into
+          methods fields constructors lists of the typeDecl
+
+          Return if there is a constructor declaration in the methods declaration */
+          
+       
+       // Looks for the size of each array . 
+
+       if (length == 0)
+               return;
+       int[] flag = new int[length + 1]; //plus one -- see <HERE>
+       int size1 = 0, size2 = 0, size3 = 0;
+       for (int i = length - 1; i >= 0; i--) {
+               ASTNode astNode = this.astStack[this.astPtr--];
+               if (astNode instanceof AbstractMethodDeclaration) {
+                       //methods and constructors have been regrouped into one single list
+                       flag[i] = 3;
+                       size2++;
+               } else {
+                       if (astNode instanceof TypeDeclaration) {
+                               flag[i] = 4;
+                               size3++;
+                       } else {
+                               //field
+                               flag[i] = 1;
+                               size1++;
+                       }
+               }
+       }
+
+       //arrays creation
+       TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+       if (size1 != 0)
+               typeDecl.fields = new FieldDeclaration[size1];
+       if (size2 != 0)
+               typeDecl.methods = new AbstractMethodDeclaration[size2];
+       if (size3 != 0)
+               typeDecl.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, 
+                                               typeDecl.fields, 
+                                               size1 - length2, 
+                                               length2); 
+                                       break;
+                               case 3 :
+                                       size2 += (length2 = end - start);
+                                       System.arraycopy(
+                                               this.astStack, 
+                                               this.astPtr + start + 1, 
+                                               typeDecl.methods, 
+                                               size2 - length2, 
+                                               length2); 
+                                       break;
+                               case 4 :
+                                       size3 += (length2 = end - start);
+                                       System.arraycopy(
+                                               this.astStack, 
+                                               this.astPtr + start + 1, 
+                                               typeDecl.memberTypes, 
+                                               size3 - length2, 
+                                               length2); 
+                                       break;
+                       }
+                       flagI = flag[start = end];
+               }
+       }
+
+       if (typeDecl.memberTypes != null) {
+               for (int i = typeDecl.memberTypes.length - 1; i >= 0; i--) {
+                       typeDecl.memberTypes[i].enclosingType = typeDecl;
+               }
+       }
+}
+protected CompilationUnitDeclaration endParse(int act) {
+
+       this.lastAct = act;
+
+       if (this.currentElement != null){
+               this.currentElement.topElement().updateParseTree();
+               if (VERBOSE_RECOVERY){
+                       System.out.print(Util.bind("parser.syntaxRecovery")); //$NON-NLS-1$
+                       System.out.println("--------------------------");                //$NON-NLS-1$
+                       System.out.println(this.compilationUnit);               
+                       System.out.println("----------------------------------"); //$NON-NLS-1$
+               }               
+       } else {
+               if (this.diet & VERBOSE_RECOVERY){
+                       System.out.print(Util.bind("parser.regularParse"));      //$NON-NLS-1$
+                       System.out.println("--------------------------");        //$NON-NLS-1$
+                       System.out.println(this.compilationUnit);               
+                       System.out.println("----------------------------------"); //$NON-NLS-1$
+               }
+       }
+       persistLineSeparatorPositions();
+       for (int i = 0; i < this.scanner.foundTaskCount; i++){
+               problemReporter().task(
+                       new String(this.scanner.foundTaskTags[i]), 
+                       new String(this.scanner.foundTaskMessages[i]),
+                       this.scanner.foundTaskPriorities[i] == null ? null : new String(this.scanner.foundTaskPriorities[i]), 
+                       this.scanner.foundTaskPositions[i][0], 
+                       this.scanner.foundTaskPositions[i][1]);
+       }
+       return this.compilationUnit;
+}
+/*
+ * Flush comments defined prior to a given positions.
+ *
+ * Note: comments are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line 
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+public int flushCommentsDefinedPriorTo(int position) {
+
+       int lastCommentIndex = this.scanner.commentPtr;
+       if (lastCommentIndex < 0) return position; // no comment
+
+       // compute the index of the first obsolete comment
+       int index = lastCommentIndex;
+       int validCount = 0;
+       while (index >= 0){
+               int commentEnd = this.scanner.commentStops[index];
+               if (commentEnd < 0) commentEnd = -commentEnd; // negative end position for non-javadoc comments
+               if (commentEnd <= position){
+                       break;
+               }
+               index--;
+               validCount++;
+       }
+       // if the source at <position> is immediately followed by a line comment, then
+       // flush this comment and shift <position> to the comment end.
+       if (validCount > 0){
+               int immediateCommentEnd = -this.scanner.commentStops[index+1]; //non-javadoc comment end positions are negative
+               if (immediateCommentEnd > 0){ // only tolerating non-javadoc comments
+                       // is there any line break until the end of the immediate comment ? (thus only tolerating line comment)
+                       immediateCommentEnd--; // comment end in one char too far
+                       if (this.scanner.getLineNumber(position) == this.scanner.getLineNumber(immediateCommentEnd)){
+                               position = immediateCommentEnd;
+                               validCount--; // flush this comment
+                               index++;
+                       }
+               }
+       }
+
+       if (index < 0) return position; // no obsolete comment
+
+       if (validCount > 0){ // move valid comment infos, overriding obsolete comment infos
+               System.arraycopy(this.scanner.commentStarts, index + 1, this.scanner.commentStarts, 0, validCount);
+               System.arraycopy(this.scanner.commentStops, index + 1, this.scanner.commentStops, 0, validCount);               
+       }
+       this.scanner.commentPtr = validCount - 1;
+       return position;
+}
+public final int getFirstToken() {
+       // the first token is a virtual token that
+       // allows the parser to parse several goals
+       // even if they aren't LALR(1)....
+       // Goal ::= '++' CompilationUnit
+       // Goal ::= '--' MethodBody
+       // Goal ::= '==' ConstructorBody
+       // -- Initializer
+       // Goal ::= '>>' StaticInitializer
+       // Goal ::= '>>' Block
+       // -- error recovery
+       // Goal ::= '>>>' Headers
+       // Goal ::= '*' BlockStatements
+       // Goal ::= '*' MethodPushModifiersHeader
+       // -- JDOM
+       // Goal ::= '&&' FieldDeclaration
+       // Goal ::= '||' ImportDeclaration
+       // Goal ::= '?' PackageDeclaration
+       // Goal ::= '+' TypeDeclaration
+       // Goal ::= '/' GenericMethodDeclaration
+       // Goal ::= '&' ClassBodyDeclaration
+       // -- code snippet
+       // Goal ::= '%' Expression
+       // -- completion parser
+       // Goal ::= '!' ConstructorBlockStatementsopt
+       // Goal ::= '~' BlockStatementsopt
+       
+       return this.firstToken;
+}
+/*
+ * Answer back an array of sourceStart/sourceEnd positions of the available JavaDoc comments.
+ * The array is a flattened structure: 2*n entries with consecutives start and end positions.
+ *
+ * If no JavaDoc is available, then null is answered instead of an empty array.
+ *
+ * e.g. { 10, 20, 25, 45 }  --> javadoc1 from 10 to 20, javadoc2 from 25 to 45
+ */
+public int[] getJavaDocPositions() {
+
+       int javadocCount = 0;
+       for (int i = 0, max = this.scanner.commentPtr; i <= max; i++){
+               // javadoc only (non javadoc comment have negative end positions.)
+               if (this.scanner.commentStops[i] > 0){
+                       javadocCount++;
+               }
+       }
+       if (javadocCount == 0) return null;
+
+       int[] positions = new int[2*javadocCount];
+       int index = 0;
+       for (int i = 0, max = this.scanner.commentPtr; i <= max; i++){
+               // javadoc only (non javadoc comment have negative end positions.)
+               if (this.scanner.commentStops[i] > 0){
+                       positions[index++] = this.scanner.commentStarts[i];
+                       positions[index++] = this.scanner.commentStops[i]-1; //stop is one over                 
+               }
+       }
+       return positions;
+}
+       public void getMethodBodies(CompilationUnitDeclaration unit) {
+               //fill the methods bodies in order for the code to be generated
+
+               if (unit == null) return;
+               
+               if (unit.ignoreMethodBodies) {
+                       unit.ignoreFurtherInvestigation = true;
+                       return;
+                       // if initial diet parse did not work, no need to dig into method bodies.
+               }
+
+               if ((unit.bits & ASTNode.HasAllMethodBodies) != 0)
+                       return; //work already done ...
+
+               //real parse of the method....
+               char[] contents = unit.compilationResult.compilationUnit.getContents();
+               this.scanner.setSource(contents);
+               
+               // save existing values to restore them at the end of the parsing process
+               // see bug 47079 for more details
+               int[] oldLineEnds = this.scanner.lineEnds;
+               int oldLinePtr = this.scanner.linePtr;
+
+               final int[] lineSeparatorPositions = unit.compilationResult.lineSeparatorPositions;
+               this.scanner.lineEnds = lineSeparatorPositions;
+               this.scanner.linePtr = lineSeparatorPositions.length - 1;
+
+               if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+                       this.javadocParser.scanner.setSource(contents);
+               }
+               if (unit.types != null) {
+                       for (int i = unit.types.length; --i >= 0;)
+                               unit.types[i].parseMethod(this, unit);
+               }
+               
+               // tag unit has having read bodies
+               unit.bits |= ASTNode.HasAllMethodBodies;
+
+               // this is done to prevent any side effects on the compilation unit result
+               // line separator positions array.
+               this.scanner.lineEnds = oldLineEnds;
+               this.scanner.linePtr = oldLinePtr;
+       }
+protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
+This variable is a type reference and dim will be its dimensions*/
+
+       int length;
+       TypeReference ref;
+       if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
+               // single variable reference
+               if (dim == 0) {
+                       ref = 
+                               new SingleTypeReference(
+                                       this.identifierStack[this.identifierPtr], 
+                                       this.identifierPositionStack[this.identifierPtr--]); 
+               } else {
+                       ref = 
+                               new ArrayTypeReference(
+                                       this.identifierStack[this.identifierPtr], 
+                                       dim, 
+                                       this.identifierPositionStack[this.identifierPtr--]); 
+                       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--];
+                       if (dim == 0) {
+                               ref.sourceEnd = this.intStack[this.intPtr--];
+                       } else {
+                               this.intPtr--;
+                               ref.sourceEnd = this.endPosition;
+                       }
+               } else { //Qualified variable reference
+                       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); 
+                       if (dim == 0) {
+                               ref = new QualifiedTypeReference(tokens, positions);
+                       } else {
+                               ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+                               ref.sourceEnd = this.endPosition;
+                       }
+               }
+       }
+       return ref;
+}
+protected Expression getTypeReference(Expression exp) {
+       
+       exp.bits &= ~ASTNode.RestrictiveFlagMASK;
+       exp.bits |= TYPE;
+       return exp;
+}
+protected NameReference getUnspecifiedReference() {
+       /* build a (unspecified) NameReference which may be qualified*/
+
+       int length;
+       NameReference ref;
+       if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1)
+               // single variable reference
+               ref = 
+                       new SingleNameReference(
+                               this.identifierStack[this.identifierPtr], 
+                               this.identifierPositionStack[this.identifierPtr--]); 
+       else
+               //Qualified variable reference
+               {
+               char[][] tokens = new char[length][];
+               this.identifierPtr -= length;
+               System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+               long[] positions = new long[length];
+               System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+               ref = 
+                       new QualifiedNameReference(tokens, 
+                               positions,
+                               (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
+                               (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
+       }
+       return ref;
+}
+protected NameReference getUnspecifiedReferenceOptimized() {
+       /* build a (unspecified) NameReference which may be qualified
+       The optimization occurs for qualified reference while we are
+       certain in this case the last item of the qualified name is
+       a field access. This optimization is IMPORTANT while it results
+       that when a NameReference is build, the type checker should always
+       look for that it is not a type reference */
+
+       int length;
+       NameReference ref;
+       if ((length = this.identifierLengthStack[this.identifierLengthPtr--]) == 1) {
+               // single variable reference
+               ref = 
+                       new SingleNameReference(
+                               this.identifierStack[this.identifierPtr], 
+                               this.identifierPositionStack[this.identifierPtr--]); 
+               ref.bits &= ~ASTNode.RestrictiveFlagMASK;
+               ref.bits |= LOCAL | FIELD;
+               return ref;
+       }
+
+       //Qualified-variable-reference
+       //In fact it is variable-reference DOT field-ref , but it would result in a type
+       //conflict tha can be only reduce by making a superclass (or inetrface ) between
+       //nameReference and FiledReference or putting FieldReference under NameReference
+       //or else..........This optimisation is not really relevant so just leave as it is
+
+       char[][] tokens = new char[length][];
+       this.identifierPtr -= length;
+       System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
+       long[] positions = new long[length];
+       System.arraycopy(this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
+       ref = new QualifiedNameReference(
+                       tokens,
+                       positions, 
+                       (int) (this.identifierPositionStack[this.identifierPtr + 1] >> 32), // sourceStart
+                       (int) this.identifierPositionStack[this.identifierPtr + length]); // sourceEnd
+       ref.bits &= ~ASTNode.RestrictiveFlagMASK;
+       ref.bits |= LOCAL | FIELD;
+       return ref;
+}
+public void goForBlockStatementsopt() {
+       //tells the scanner to go for block statements opt parsing
+
+       this.firstToken = TokenNameTWIDDLE;
+       this.scanner.recordLineSeparator = false;
+}
+public void goForBlockStatementsOrCatchHeader() {
+       //tells the scanner to go for block statements or method headers parsing 
+
+       this.firstToken = TokenNameMULTIPLY;
+       this.scanner.recordLineSeparator = false;
+}
+public void goForClassBodyDeclarations() {
+       //tells the scanner to go for any body declarations parsing
+
+       this.firstToken = TokenNameAND;
+       this.scanner.recordLineSeparator = true;
+}
+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;
+}
+public void goForExpression() {
+       //tells the scanner to go for an expression parsing
+
+       this.firstToken = TokenNameREMAINDER;
+       this.scanner.recordLineSeparator = true; // recovery goals must record line separators
+}
+public void goForFieldDeclaration(){
+       //tells the scanner to go for field declaration parsing
+
+       this.firstToken = TokenNameAND_AND ;
+       this.scanner.recordLineSeparator = true;
+}
+public void goForGenericMethodDeclaration(){
+       //tells the scanner to go for generic method declarations parsing
+
+       this.firstToken = TokenNameDIVIDE;
+       this.scanner.recordLineSeparator = true;
+}
+public void goForHeaders(){
+       //tells the scanner to go for headers only parsing
+
+       this.firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
+       this.scanner.recordLineSeparator = true; // recovery goals must record line separators
+}
+public void goForImportDeclaration(){
+       //tells the scanner to go for import declaration parsing
+
+       this.firstToken = TokenNameOR_OR ;
+       this.scanner.recordLineSeparator = true;
+}
+public void goForInitializer(){
+       //tells the scanner to go for initializer parsing
+
+       this.firstToken = TokenNameRIGHT_SHIFT ;
+       this.scanner.recordLineSeparator = false;
+}
+public void goForMethodBody(){
+       //tells the scanner to go for method body parsing
+
+       this.firstToken = TokenNameMINUS_MINUS ;
+       this.scanner.recordLineSeparator = false;
+}
+public void goForPackageDeclaration() {
+       //tells the scanner to go for package declaration parsing
+
+       this.firstToken = TokenNameQUESTION;
+       this.scanner.recordLineSeparator = true;
+}
+public void goForTypeDeclaration() {
+       //tells the scanner to go for type (interface or class) declaration parsing
+
+       this.firstToken = TokenNamePLUS;
+       this.scanner.recordLineSeparator = true;
+}
+protected void ignoreExpressionAssignment() {
+       // Assignment ::= InvalidArrayInitializerAssignement
+       // encoded operator would be: this.intStack[this.intPtr]
+       this.intPtr--;
+       ArrayInitializer arrayInitializer = (ArrayInitializer) this.expressionStack[this.expressionPtr--];
+       this.expressionLengthPtr -- ;
+       // report a syntax error and abort parsing
+       problemReporter().arrayConstantsOnlyInArrayInitializers(arrayInitializer.sourceStart, arrayInitializer.sourceEnd);      
+}
+protected void ignoreInterfaceDeclaration() {
+       // BlockStatement ::= InvalidInterfaceDeclaration
+       //InterfaceDeclaration ::= Modifiersopt 'interface' 'Identifier' ExtendsInterfacesopt InterfaceHeader InterfaceBody
+
+       // length declarations
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               //there are length declarations
+               //dispatch according to the type of the declarations
+               dispatchDeclarationInto(length);
+       }
+       
+       flushCommentsDefinedPriorTo(this.endStatementPosition);
+
+       // report the problem and continue parsing
+       TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+       typeDecl.bodyEnd = this.endStatementPosition;
+       problemReporter().cannotDeclareLocalInterface(typeDecl.name, typeDecl.sourceStart, typeDecl.sourceEnd);
+
+       // mark initializers with local type mark if needed
+       markInitializersWithLocalType(typeDecl);
+
+       // remove the ast node created in interface header
+       this.astPtr--;
+       pushOnAstLengthStack(-1);
+       concatNodeLists();
+}
+protected void ignoreInvalidConstructorDeclaration(boolean hasBody) {
+       // InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody ==> true
+       // InvalidConstructorDeclaration ::= ConstructorHeader ';' ==> false
+
+       /*
+       astStack : modifiers arguments throws statements
+       identifierStack : name
+        ==>
+       astStack : MethodDeclaration
+       identifierStack :
+       */
+       if (hasBody) {
+               // pop the position of the {  (body of the method) pushed in block decl
+               this.intPtr--;
+       }
+
+       //statements
+       if (hasBody) {
+               this.realBlockPtr--;
+       }
+
+       int length;
+       if (hasBody && ((length = this.astLengthStack[this.astLengthPtr--]) != 0)) {
+               this.astPtr -= length;
+       }
+       ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) this.astStack[this.astPtr];
+       constructorDeclaration.bodyEnd = this.endStatementPosition;
+       constructorDeclaration.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+       if (!hasBody) {
+               constructorDeclaration.modifiers |= AccSemicolonBody;
+       }
+}
+protected void ignoreMethodBody() {
+       // InterfaceMemberDeclaration ::= InvalidMethodDeclaration
+
+       /*
+       astStack : modifiers arguments throws statements
+       identifierStack : type name
+       intStack : dim dim dim
+        ==>
+       astStack : MethodDeclaration
+       identifierStack :
+       intStack : 
+       */
+
+       // pop the position of the {  (body of the method) pushed in block decl
+       this.intPtr--;
+       // retrieve end position of method declarator
+
+       //statements
+       this.realBlockPtr--;
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               this.astPtr -= length;
+       }
+
+       //watch for } that could be given as a unicode ! ( u007D is '}' )
+       MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
+       md.bodyEnd = this.endPosition;
+       md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+
+       // report the problem and continue the parsing - narrowing the problem onto the method
+       problemReporter().abstractMethodNeedingNoBody(md);
+}
+public void initialize() {
+       //positionning the parser for a new compilation unit
+       //avoiding stack reallocation and all that....
+       this.astPtr = -1;
+       this.astLengthPtr = -1;
+       this.expressionPtr = -1;
+       this.expressionLengthPtr = -1;
+       this.identifierPtr = -1;        
+       this.identifierLengthPtr        = -1;
+       this.intPtr = -1;
+       this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
+       this.variablesCounter[this.nestedType] = 0;
+       this.dimensions = 0 ;
+       this.realBlockPtr = -1;
+       this.compilationUnit = null;
+       this.referenceContext = null;
+       this.endStatementPosition = 0;
+
+       //remove objects from stack too, while the same parser/compiler couple is
+       //re-used between two compilations ....
+       
+       int astLength = this.astStack.length;
+       if (this.noAstNodes.length < astLength){
+               this.noAstNodes = new ASTNode[astLength];
+               //System.out.println("Resized AST stacks : "+ astLength);
+               
+       }
+       System.arraycopy(this.noAstNodes, 0, this.astStack, 0, astLength);
+
+       int expressionLength = this.expressionStack.length;
+       if (this.noExpressions.length < expressionLength){
+               this.noExpressions = new Expression[expressionLength];
+               //System.out.println("Resized EXPR stacks : "+ expressionLength);
+       }
+       System.arraycopy(this.noExpressions, 0, this.expressionStack, 0, expressionLength);
+
+       // reset scanner state
+       this.scanner.commentPtr = -1;
+       this.scanner.foundTaskCount = 0;
+       this.scanner.eofPosition = Integer.MAX_VALUE;
+       this.scanner.wasNonExternalizedStringLiteral = false;
+       this.scanner.nonNLSStrings = null;
+       this.scanner.currentLine = null;        
+
+       resetModifiers();
+
+       // recovery
+       this.lastCheckPoint = -1;
+       this.currentElement = null;
+       this.restartRecovery = false;
+       this.hasReportedError = false;
+       this.recoveredStaticInitializerStart = 0;
+       this.lastIgnoredToken = -1;
+       this.lastErrorEndPosition = -1;
+       this.listLength = 0;
+       
+       this.rBraceStart = 0;
+       this.rBraceEnd = 0;
+       this.rBraceSuccessorStart = 0;
+}
+public void initializeScanner(){
+       this.scanner = new Scanner(
+               false /*comment*/, 
+               false /*whitespace*/, 
+               this.options.getSeverity(CompilerOptions.NonExternalizedString) != ProblemSeverities.Ignore /*nls*/, 
+               this.options.sourceLevel /*sourceLevel*/, 
+               this.options.taskTags/*taskTags*/,
+               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() {
+       //on diet parsing.....do not buffer method statements
+
+       //the scanner.diet is reinitialized to false
+       //automatically by the scanner once it has jumped over
+       //the statements
+
+       if (this.diet && (this.dietInt == 0))
+               this.scanner.diet = true;
+}
+protected void markEnclosingMemberWithLocalType() {
+       if (this.currentElement != null) return; // this is already done in the recovery code
+       for (int i = this.astPtr; i >= 0; i--) {
+               ASTNode node = this.astStack[i];
+               if (node instanceof AbstractMethodDeclaration 
+                               || node instanceof FieldDeclaration
+                               || node instanceof TypeDeclaration) { // mark type for now: all initializers will be marked when added to this type
+                       node.bits |= ASTNode.HasLocalTypeMASK;
+                       return;
+               }
+       }
+       // default to reference context (case of parse method body)
+       if (this.referenceContext instanceof AbstractMethodDeclaration
+                       || this.referenceContext instanceof TypeDeclaration) {
+               ((ASTNode)this.referenceContext).bits |= ASTNode.HasLocalTypeMASK;
+       }
+}
+protected void markInitializersWithLocalType(TypeDeclaration type) {
+       if (type.fields == null || (type.bits & ASTNode.HasLocalTypeMASK) == 0) return;
+       for (int i = 0, length = type.fields.length; i < length; i++) {
+               FieldDeclaration field = type.fields[i];
+               if (field instanceof Initializer) {
+                       field.bits |= ASTNode.HasLocalTypeMASK;
+               }
+       }
+}
+/*
+ * Move checkpoint location (current implementation is moving it by one token)
+ *
+ * Answers true if successfully moved checkpoint (in other words, it did not attempt to move it
+ * beyond end of file).
+ */
+protected boolean moveRecoveryCheckpoint() {
+
+       int pos = this.lastCheckPoint;
+       /* reset scanner, and move checkpoint by one token */
+       this.scanner.startPosition = pos;
+       this.scanner.currentPosition = pos;
+       this.scanner.diet = false; // quit jumping over method bodies
+       
+       /* if about to restart, then no need to shift token */
+       if (this.restartRecovery){
+               this.lastIgnoredToken = -1;
+               this.scanner.currentLine = null;
+               return true;
+       }
+       
+       /* protect against shifting on an invalid token */
+       this.lastIgnoredToken = this.nextIgnoredToken;
+       this.nextIgnoredToken = -1;
+       do {
+               try {
+                       this.nextIgnoredToken = this.scanner.getNextToken();
+                       if(this.scanner.currentPosition == this.scanner.startPosition){
+                               this.scanner.currentPosition++; // on fake completion identifier
+                               this.nextIgnoredToken = -1;
+                       }
+                       
+               } catch(InvalidInputException e){
+                       pos = this.scanner.currentPosition;
+               }
+       } while (this.nextIgnoredToken < 0);
+       
+       if (this.nextIgnoredToken == TokenNameEOF) { // no more recovery after this point
+               if (this.currentToken == TokenNameEOF) { // already tried one iteration on EOF
+                       this.scanner.currentLine = null;
+                       return false;
+               }
+       }
+       this.lastCheckPoint = this.scanner.currentPosition;
+       
+       /* reset scanner again to previous checkpoint location*/
+       this.scanner.startPosition = pos;
+       this.scanner.currentPosition = pos;
+       this.scanner.commentPtr = -1;
+       this.scanner.foundTaskCount = 0;
+       this.scanner.currentLine = null;
+
+       return true;
+
+/*
+       The following implementation moves the checkpoint location by one line:
+        
+       int pos = this.lastCheckPoint;
+       // reset scanner, and move checkpoint by one token
+       this.scanner.startPosition = pos;
+       this.scanner.currentPosition = pos;
+       this.scanner.diet = false; // quit jumping over method bodies
+       
+       // if about to restart, then no need to shift token
+       if (this.restartRecovery){
+               this.lastIgnoredToken = -1;
+               return true;
+       }
+       
+       // protect against shifting on an invalid token
+       this.lastIgnoredToken = this.nextIgnoredToken;
+       this.nextIgnoredToken = -1;
+       
+       boolean wasTokenizingWhiteSpace = this.scanner.tokenizeWhiteSpace;
+       this.scanner.tokenizeWhiteSpace = true;
+       checkpointMove: 
+               do {
+                       try {
+                               this.nextIgnoredToken = this.scanner.getNextToken();
+                               switch(this.nextIgnoredToken){
+                                       case Scanner.TokenNameWHITESPACE :
+                                               if(this.scanner.getLineNumber(this.scanner.startPosition)
+                                                       == this.scanner.getLineNumber(this.scanner.currentPosition)){
+                                                       this.nextIgnoredToken = -1;
+                                                       }
+                                               break;
+                                       case TokenNameSEMICOLON :
+                                       case TokenNameLBRACE :
+                                       case TokenNameRBRACE :
+                                               break;
+                                       case TokenNameIdentifier :
+                                               if(this.scanner.currentPosition == this.scanner.startPosition){
+                                                       this.scanner.currentPosition++; // on fake completion identifier
+                                               }
+                                       default:                                                
+                                               this.nextIgnoredToken = -1;
+                                               break;
+                                       case TokenNameEOF :
+                                               break checkpointMove;
+                               }
+                       } catch(InvalidInputException e){
+                               pos = this.scanner.currentPosition;
+                       }
+               } while (this.nextIgnoredToken < 0);
+       this.scanner.tokenizeWhiteSpace = wasTokenizingWhiteSpace;
+       
+       if (this.nextIgnoredToken == TokenNameEOF) { // no more recovery after this point
+               if (this.currentToken == TokenNameEOF) { // already tried one iteration on EOF
+                       return false;
+               }
+       }
+       this.lastCheckPoint = this.scanner.currentPosition;
+       
+       // reset scanner again to previous checkpoint location
+       this.scanner.startPosition = pos;
+       this.scanner.currentPosition = pos;
+       this.scanner.commentPtr = -1;
+
+       return true;
+*/
+}
+protected MessageSend newMessageSend() {
+       // '(' ArgumentListopt ')'
+       // the arguments are on the expression stack
+
+       MessageSend m = new MessageSend();
+       int length;
+       if ((length = this.expressionLengthStack[this.expressionLengthPtr--]) != 0) {
+               this.expressionPtr -= length;
+               System.arraycopy(
+                       this.expressionStack, 
+                       this.expressionPtr + 1, 
+                       m.arguments = new Expression[length], 
+                       0, 
+                       length); 
+       }
+       return m;
+}
+public static int nasi(int state) {
+       return nasb[original_state(state)];
+}
+public static int ntAction(int state, int sym) {
+       return base_action[state + sym];
+}
+private final void optimizedConcatNodeLists() {
+       /*back from a recursive loop. Virtualy group the
+       astNode into an array using 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
+        * 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.
+        * 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 
+called in order to remember (when needed) the consumed token */
+// (int)asr[asi(act)]
+// name[symbol_index[currentKind]]
+protected void parse() {
+       boolean isDietParse = this.diet;
+       int oldFirstToken = getFirstToken();
+       this.hasError = false;
+       
+       this.hasReportedError = false;
+       int act = START_STATE;
+       this.stateStackTop = -1;
+       this.currentToken = getFirstToken();
+       ProcessTerminals : for (;;) {
+               int stackLength = this.stack.length;
+               if (++this.stateStackTop >= stackLength) {
+                       System.arraycopy(
+                               this.stack, 0,
+                               this.stack = new int[stackLength + StackIncrement], 0,
+                               stackLength);
+               }
+               this.stack[this.stateStackTop] = act;
+
+               act = tAction(act, this.currentToken);
+
+               if (act == ERROR_ACTION || this.restartRecovery) {
+                       int errorPos = this.scanner.currentPosition;
+                       if (!this.hasReportedError){
+                               this.hasError = true;
+                       }
+                       if (resumeOnSyntaxError()) {
+                               if (act == ERROR_ACTION) this.lastErrorEndPosition = errorPos;
+                               act = START_STATE;
+                               this.stateStackTop = -1;
+                               this.currentToken = getFirstToken();
+                               continue ProcessTerminals;
+                       }
+                       act = ERROR_ACTION;
+                       break ProcessTerminals;
+               }
+               if (act <= NUM_RULES) {
+                       this.stateStackTop--;
+                       
+               } else if (act > ERROR_ACTION) { /* shift-reduce */
+                       consumeToken(this.currentToken);
+                       if (this.currentElement != null) this.recoveryTokenCheck();
+                       try {
+                               this.currentToken = this.scanner.getNextToken();
+                       } catch(InvalidInputException e){
+                               if (!this.hasReportedError){
+                                       this.problemReporter().scannerError(this, e.getMessage());
+                                       this.hasReportedError = true;
+                               }
+                               this.lastCheckPoint = this.scanner.currentPosition;
+                               this.restartRecovery = true;
+                       }                                       
+                       act -= ERROR_ACTION;
+                       
+               } else {
+                   if (act < ACCEPT_ACTION) { /* shift */
+                               consumeToken(this.currentToken);
+                               if (this.currentElement != null) this.recoveryTokenCheck();
+                               try{
+                                       this.currentToken = this.scanner.getNextToken();
+                               } catch(InvalidInputException e){
+                                       if (!this.hasReportedError){
+                                               this.problemReporter().scannerError(this, e.getMessage());
+                                               this.hasReportedError = true;
+                                       }
+                                       this.lastCheckPoint = this.scanner.currentPosition;
+                                       this.restartRecovery = true;
+                               }                                       
+                               continue ProcessTerminals;
+                       }
+                       break ProcessTerminals;
+               }
+               ProcessNonTerminals : do { /* reduce */
+                       consumeRule(act);
+                       this.stateStackTop -= (rhs[act] - 1);
+                       act = ntAction(this.stack[this.stateStackTop], lhs[act]);
+               } while (act <= NUM_RULES);
+       }
+       endParse(act);
+       
+       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();
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
+       parse(cd, unit, false);
+}
+public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit, boolean recordLineSeparator) {
+       //only parse the method body of cd
+       //fill out its statements
+
+       //convert bugs into parse error
+
+       initialize();
+       goForBlockStatementsopt();
+       if (recordLineSeparator) {
+               this.scanner.recordLineSeparator = true;
+       }
+       this.nestedMethod[this.nestedType]++;
+       pushOnRealBlockStack(0);
+       
+       this.referenceContext = cd;
+       this.compilationUnit = unit;
+
+       this.scanner.resetTo(cd.bodyStart, cd.bodyEnd);
+       try {
+               parse();
+       } catch (AbortCompilation ex) {
+               this.lastAct = ERROR_ACTION;
+       } finally {
+               this.nestedMethod[this.nestedType]--;
+       }
+
+       checkNonNLSAfterBodyEnd(cd.declarationSourceEnd);
+       
+       if (this.lastAct == ERROR_ACTION) {
+               initialize();
+               return;
+       }
+
+       //statements
+       cd.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               this.astPtr -= length;
+               if (this.astStack[this.astPtr + 1] instanceof ExplicitConstructorCall)
+                       //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+                       {
+                       System.arraycopy(
+                               this.astStack, 
+                               this.astPtr + 2, 
+                               cd.statements = new Statement[length - 1], 
+                               0, 
+                               length - 1); 
+                       cd.constructorCall = (ExplicitConstructorCall) this.astStack[this.astPtr + 1];
+               } else { //need to add explicitly the super();
+                       System.arraycopy(
+                               this.astStack, 
+                               this.astPtr + 1, 
+                               cd.statements = new Statement[length], 
+                               0, 
+                               length); 
+                       cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+               }
+       } else {
+               cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+               if (!containsComment(cd.bodyStart, cd.bodyEnd)) {
+                       cd.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+               }               
+       }
+
+       if (cd.constructorCall.sourceEnd == 0) {
+               cd.constructorCall.sourceEnd = cd.sourceEnd;
+               cd.constructorCall.sourceStart = cd.sourceStart;
+       }
+}
+// A P I
+
+public void parse(
+       FieldDeclaration field, 
+       TypeDeclaration type, 
+       CompilationUnitDeclaration unit,
+       char[] initializationSource) {
+       //only parse the initializationSource of the given field
+
+       //convert bugs into parse error
+
+       initialize();
+       goForExpression();
+       this.nestedMethod[this.nestedType]++;
+
+       this.referenceContext = type;
+       this.compilationUnit = unit;
+
+       this.scanner.setSource(initializationSource);
+       this.scanner.resetTo(0, initializationSource.length-1);
+       try {
+               parse();
+       } catch (AbortCompilation ex) {
+               this.lastAct = ERROR_ACTION;
+       } finally {
+               this.nestedMethod[this.nestedType]--;
+       }
+
+       if (this.lastAct == ERROR_ACTION) {
+               return;
+       }
+
+       field.initialization = this.expressionStack[this.expressionPtr];
+       
+       // mark field with local type if one was found during parsing
+       if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
+               field.bits |= ASTNode.HasLocalTypeMASK;
+       }       
+}
+// A P I
+
+public void parse(
+       Initializer initializer, 
+       TypeDeclaration type, 
+       CompilationUnitDeclaration unit) {
+       //only parse the method body of md
+       //fill out method statements
+
+       //convert bugs into parse error
+
+       initialize();
+       goForBlockStatementsopt();
+       this.nestedMethod[this.nestedType]++;
+       pushOnRealBlockStack(0);
+       
+       this.referenceContext = type;
+       this.compilationUnit = unit;
+
+       this.scanner.resetTo(initializer.bodyStart, initializer.bodyEnd); // just on the beginning {
+       try {
+               parse();
+       } catch (AbortCompilation ex) {
+               this.lastAct = ERROR_ACTION;
+       } finally {
+               this.nestedMethod[this.nestedType]--;
+       }
+
+       checkNonNLSAfterBodyEnd(initializer.declarationSourceEnd);
+       
+       if (this.lastAct == ERROR_ACTION) {
+               return;
+       }
+       
+       //refill statements
+       initializer.block.explicitDeclarations = this.realBlockStack[this.realBlockPtr--];
+       int length;
+       if ((length = this.astLengthStack[this.astLengthPtr--]) > 0) {
+               System.arraycopy(this.astStack, (this.astPtr -= length) + 1, initializer.block.statements = new Statement[length], 0, length); 
+       } else {
+               // check whether this block at least contains some comment in it
+               if (!containsComment(initializer.block.sourceStart, initializer.block.sourceEnd)) {
+                       initializer.block.bits |= ASTNode.UndocumentedEmptyBlockMASK;
+               }
+       }
+       
+       // mark initializer with local type if one was found during parsing
+       if ((type.bits & ASTNode.HasLocalTypeMASK) != 0) {
+               initializer.bits |= ASTNode.HasLocalTypeMASK;
+       }       
+}
+// A P I
+
+public void parse(MethodDeclaration md, CompilationUnitDeclaration unit) {
+       //only parse the method body of md
+       //fill out method statements
+
+       //convert bugs into parse error
+
+       if (md.isAbstract())
+               return;
+       if (md.isNative())
+               return;
+       if ((md.modifiers & AccSemicolonBody) != 0)
+               return;
+
+       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 */
+               parse();
+       } finally {
+               unit = this.compilationUnit;
+               this.compilationUnit = null; // reset parser
+               // tag unit has having read bodies
+               if (!this.diet) unit.bits |= ASTNode.HasAllMethodBodies;                
+       }
+       return unit;
+}
+public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
+       /* automaton initialization */
+       initialize();
+       goForClassBodyDeclarations();
+       /* scanner initialization */
+       this.scanner.setSource(source);
+       this.scanner.resetTo(offset, offset + length - 1);
+       if (this.javadocParser != null && this.javadocParser.checkDocComment) {
+               this.javadocParser.scanner.setSource(source);
+               this.javadocParser.scanner.resetTo(offset, offset + length - 1);
+       }
+
+       /* type declaration should be parsed as member type declaration */      
+       this.nestedType = 1;
+
+       /* unit creation */
+       this.referenceContext = unit;
+       this.compilationUnit = unit;
+
+       /* run automaton */
+       try {
+               parse();
+       } catch (AbortCompilation ex) {
+               this.lastAct = ERROR_ACTION;
+       }
+
+       if (this.lastAct == ERROR_ACTION) {
+               return null;
+       }
+       int astLength;
+       if ((astLength = this.astLengthStack[this.astLengthPtr--]) != 0) {
+               ASTNode[] result = new ASTNode[astLength];
+               this.astPtr -= astLength;
+               System.arraycopy(this.astStack, this.astPtr + 1, result, 0, astLength);
+               return result;
+       }
+       return null;
+}
+public Expression parseExpression(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
+
+       initialize();
+       goForExpression();
+       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();
+       }
+}
+/**
+ * Returns this parser's problem reporter initialized with its reference context.
+ * Also it is assumed that a problem is going to be reported, so initializes
+ * the compilation result's line positions.
+ * 
+ * @return ProblemReporter
+ */
+public ProblemReporter problemReporter(){
+       if (this.scanner.recordLineSeparator) {
+               this.compilationUnit.compilationResult.lineSeparatorPositions = this.scanner.getLineEnds();
+       }
+       this.problemReporter.referenceContext = this.referenceContext;
+       return this.problemReporter;
+}
+protected void pushIdentifier() {
+       /*push the consumeToken on the identifier stack.
+       Increase the total number of identifier in the stack.
+       identifierPtr points on the next top */
+
+       int stackLength = this.identifierStack.length;
+       if (++this.identifierPtr >= stackLength) {
+               System.arraycopy(
+                       this.identifierStack, 0,
+                       this.identifierStack = new char[stackLength + 20][], 0,
+                       stackLength);
+               System.arraycopy(
+                       this.identifierPositionStack, 0,
+                       this.identifierPositionStack = new long[stackLength + 20], 0,
+                       stackLength);
+       }
+       this.identifierStack[this.identifierPtr] = this.scanner.getCurrentIdentifierSource();
+       this.identifierPositionStack[this.identifierPtr] =
+               (((long) this.scanner.startPosition) << 32) + (this.scanner.currentPosition - 1); 
+
+       stackLength = this.identifierLengthStack.length;
+       if (++this.identifierLengthPtr >= stackLength) {
+               System.arraycopy(
+                       this.identifierLengthStack, 0,
+                       this.identifierLengthStack = new int[stackLength + 10], 0,
+                       stackLength);
+       }
+       this.identifierLengthStack[this.identifierLengthPtr] = 1;
+}
+protected void pushIdentifier(int flag) {
+       /*push a special flag on the stack :
+       -zero stands for optional Name
+       -negative number for direct ref to base types.
+       identifierLengthPtr points on the top */
+
+       int stackLength = this.identifierLengthStack.length;
+       if (++this.identifierLengthPtr >= stackLength) {
+               System.arraycopy(
+                       this.identifierLengthStack, 0,
+                       this.identifierLengthStack = new int[stackLength + 10], 0,
+                       stackLength);
+       }
+       this.identifierLengthStack[this.identifierLengthPtr] = flag;
+}
+protected void pushOnAstLengthStack(int pos) {
+
+       int stackLength = this.astLengthStack.length;
+       if (++this.astLengthPtr >= stackLength) {
+               System.arraycopy(
+                       this.astLengthStack, 0,
+                       this.astLengthStack = new int[stackLength + StackIncrement], 0,
+                       stackLength);
+       }
+       this.astLengthStack[this.astLengthPtr] = pos;
+}
+protected void pushOnAstStack(ASTNode node) {
+       /*add a new obj on top of the ast stack
+       astPtr points on the top*/
+
+       int stackLength = this.astStack.length;
+       if (++this.astPtr >= stackLength) {
+               System.arraycopy(
+                       this.astStack, 0,
+                       this.astStack = new ASTNode[stackLength + AstStackIncrement], 0,
+                       stackLength);
+               this.astPtr = stackLength;
+       }
+       this.astStack[this.astPtr] = node;
+
+       stackLength = this.astLengthStack.length;
+       if (++this.astLengthPtr >= stackLength) {
+               System.arraycopy(
+                       this.astLengthStack, 0,
+                       this.astLengthStack = new int[stackLength + AstStackIncrement], 0,
+                       stackLength);
+       }
+       this.astLengthStack[this.astLengthPtr] = 1;
+}
+protected void pushOnExpressionStack(Expression expr) {
+
+       int stackLength = this.expressionStack.length;
+       if (++this.expressionPtr >= stackLength) {
+               System.arraycopy(
+                       this.expressionStack, 0,
+                       this.expressionStack = new Expression[stackLength + ExpressionStackIncrement], 0,
+                       stackLength);
+       }
+       this.expressionStack[this.expressionPtr] = expr;
+
+       stackLength = this.expressionLengthStack.length;
+       if (++this.expressionLengthPtr >= stackLength) {
+               System.arraycopy(
+                       this.expressionLengthStack, 0,
+                       this.expressionLengthStack = new int[stackLength + ExpressionStackIncrement], 0,
+                       stackLength);
+       }
+       this.expressionLengthStack[this.expressionLengthPtr] = 1;
+}
+protected void pushOnExpressionStackLengthStack(int pos) {
+
+       int stackLength = this.expressionLengthStack.length;
+       if (++this.expressionLengthPtr >= stackLength) {
+               System.arraycopy(
+                       this.expressionLengthStack, 0,
+                       this.expressionLengthStack = new int[stackLength + StackIncrement], 0,
+                       stackLength);
+       }
+       this.expressionLengthStack[this.expressionLengthPtr] = pos;
+}
+protected void pushOnIntStack(int pos) {
+
+       int stackLength = this.intStack.length;
+       if (++this.intPtr >= stackLength) {
+               System.arraycopy(
+                       this.intStack, 0,
+                       this.intStack = new int[stackLength + StackIncrement], 0,
+                       stackLength);
+       }
+       this.intStack[this.intPtr] = pos;
+}
+protected void pushOnRealBlockStack(int i){
+       
+       int stackLength = this.realBlockStack.length;
+       if (++this.realBlockPtr >= stackLength) {
+               System.arraycopy(
+                       this.realBlockStack, 0,
+                       this.realBlockStack = new int[stackLength + StackIncrement], 0,
+                       stackLength);
+       }
+       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) {
+                       
+                       int end = ((RecoveredLocalVariable)this.currentElement).localDeclaration.sourceEnd;
+                       this.currentElement.updateSourceEndIfNecessary(end);
+                       this.currentElement = this.currentElement.parent;
+               } else if(this.currentElement instanceof RecoveredField
+                       && !(this.currentElement instanceof RecoveredInitializer)) {
+                               
+                       int end = ((RecoveredField)this.currentElement).fieldDeclaration.sourceEnd;
+                       this.currentElement.updateSourceEndIfNecessary(end);
+                       this.currentElement = this.currentElement.parent;
+               }
+       }
+}
+/* Token check performed on every token shift once having entered
+ * recovery mode.
+ */
+public void recoveryTokenCheck() {
+       switch (this.currentToken) {
+               case TokenNameLBRACE : 
+                       RecoveredElement newElement = null;
+                       if(!this.ignoreNextOpeningBrace) {
+                               newElement = this.currentElement.updateOnOpeningBrace(this.scanner.startPosition - 1, this.scanner.currentPosition - 1);
+                       }
+                       this.lastCheckPoint = this.scanner.currentPosition;                             
+                       if (newElement != null){ // null means nothing happened
+                               this.restartRecovery = true; // opening brace detected
+                               this.currentElement = newElement;
+                       }
+                       break;
+               
+               case TokenNameRBRACE : 
+                       this.rBraceStart = this.scanner.startPosition - 1;
+                       this.rBraceEnd = this.scanner.currentPosition - 1;
+                       this.endPosition = this.flushCommentsDefinedPriorTo(this.rBraceEnd);
+                       newElement =
+                               this.currentElement.updateOnClosingBrace(this.scanner.startPosition, this.rBraceEnd);
+                               this.lastCheckPoint = this.scanner.currentPosition;
+                       if (newElement != this.currentElement){
+                               this.currentElement = newElement;
+                       }
+                       break;
+               case TokenNameSEMICOLON :
+                       this.endStatementPosition = this.scanner.currentPosition - 1;
+                       this.endPosition = this.scanner.startPosition - 1; 
+                       // fall through
+               default : {
+                       if (this.rBraceEnd > this.rBraceSuccessorStart && this.scanner.currentPosition != this.scanner.startPosition){
+                               this.rBraceSuccessorStart = this.scanner.startPosition;
+                       }
+                       break;
+               }
+       }
+       this.ignoreNextOpeningBrace = false;
+}
+protected void resetModifiers() {
+       this.modifiers = AccDefault;
+       this.modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+       this.scanner.commentPtr = -1;
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ */
+protected void resetStacks() {
+
+       this.astPtr = -1;
+       this.astLengthPtr = -1;
+       this.expressionPtr = -1;
+       this.expressionLengthPtr = -1;
+       this.identifierPtr = -1;        
+       this.identifierLengthPtr        = -1;
+       this.intPtr = -1;
+       this.nestedMethod[this.nestedType = 0] = 0; // need to reset for further reuse
+       this.variablesCounter[this.nestedType] = 0;
+       this.dimensions = 0 ;
+       this.realBlockStack[this.realBlockPtr = 0] = 0;
+       this.recoveredStaticInitializerStart = 0;
+       this.listLength = 0;
+       // Fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=29365
+       if (this.scanner != null) this.scanner.currentLine = null;
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ * If unable to reset for resuming, answers false.
+ *
+ * Move checkpoint location, reset internal stacks and
+ * decide which grammar goal is activated.
+ */
+protected boolean resumeAfterRecovery() {
+
+       // Reset javadoc before restart parsing after recovery
+       this.javadoc = null;
+
+       // reset internal stacks 
+       this.resetStacks();
+       
+       /* attempt to move checkpoint location */
+       if (!this.moveRecoveryCheckpoint()) {
+               return false;
+       }
+
+       // only look for headers
+       if (this.referenceContext instanceof CompilationUnitDeclaration){
+               goForHeaders();
+               this.diet = true; // passed this point, will not consider method bodies
+               return true;
+       }
+       // 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
+       }
+       /* do not investigate deeper in recovery when no recovered element */
+       if (this.currentElement == null) return false;
+       
+       /* manual forced recovery restart - after headers */
+       if (this.restartRecovery){
+               this.restartRecovery = false;
+       }
+       /* update recovery state with current error state of the parser */
+       this.updateRecoveryState();
+       
+       /* 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$
+       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$
+       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$
+       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$
+       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$
+       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 + "\n\n\n----------------Scanner--------------\n" + this.scanner.toString(); //$NON-NLS-1$
+       return s;
+
+}
+/*
+ * Update recovery state based on current parser/scanner state
+ */
+protected void updateRecoveryState() {
+
+       /* expose parser state to recovery state */
+       this.currentElement.updateFromParserState();
+
+       /* check and update recovered state based on current token,
+               this action is also performed when shifting token after recovery
+               got activated once. 
+       */
+       this.recoveryTokenCheck();
+}
+protected void updateSourceDeclarationParts(int variableDeclaratorsCounter) {
+       //fields is a definition of fields that are grouped together like in
+       //public int[] a, b[], c
+       //which results into 3 fields.
+
+       FieldDeclaration field;
+       int endTypeDeclarationPosition = 
+               -1 + this.astStack[this.astPtr - variableDeclaratorsCounter + 1].sourceStart; 
+       for (int i = 0; i < variableDeclaratorsCounter - 1; i++) {
+               //last one is special(see below)
+               field = (FieldDeclaration) this.astStack[this.astPtr - i - 1];
+               field.endPart1Position = endTypeDeclarationPosition;
+               field.endPart2Position = -1 + this.astStack[this.astPtr - i].sourceStart;
+       }
+       //last one
+       (field = (FieldDeclaration) this.astStack[this.astPtr]).endPart1Position = 
+               endTypeDeclarationPosition; 
+       field.endPart2Position = field.declarationSourceEnd;
+
+}
+protected void updateSourcePosition(Expression exp) {
+       //update the source Position of the expression
+
+       //intStack : int int
+       //-->
+       //intStack : 
+
+       exp.sourceEnd = this.intStack[this.intPtr--];
+       exp.sourceStart = this.intStack[this.intPtr--];
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/src/java/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
new file mode 100644 (file)
index 0000000..bdb077b
--- /dev/null
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/*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;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java
new file mode 100644 (file)
index 0000000..9917bd9
--- /dev/null
@@ -0,0 +1,330 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal block structure for parsing recovery 
+ */
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+
+public class RecoveredBlock extends RecoveredStatement implements CompilerModifiers, TerminalTokens, BaseTypes {
+
+       public Block blockDeclaration;
+       public RecoveredStatement[] statements;
+       public int statementCount;
+       public boolean preserveContent = false;
+       public RecoveredLocalVariable pendingArgument;
+       
+public RecoveredBlock(Block block, RecoveredElement parent, int bracketBalance){
+       super(block, parent, bracketBalance);
+       this.blockDeclaration = block;
+       this.foundOpeningBrace = true;
+}
+/*
+ * Record a nested block declaration 
+ */
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
+
+       /* do not consider a nested block starting passed the block end (if set)
+               it must be belonging to an enclosing block */
+       if (this.blockDeclaration.sourceEnd != 0 
+               && nestedBlockDeclaration.sourceStart > this.blockDeclaration.sourceEnd){
+               return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
+       }
+                       
+       RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
+
+       // if we have a pending Argument, promote it into the new block
+       if (this.pendingArgument != null){
+               element.attach(this.pendingArgument);
+               this.pendingArgument = null;
+       }
+       this.attach(element);
+       if (nestedBlockDeclaration.sourceEnd == 0) return element;
+       return this;    
+}
+/*
+ * Record a local declaration 
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
+       return this.add(localDeclaration, bracketBalanceValue, false);
+}
+/*
+ * Record a local declaration 
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue, boolean delegatedByParent) {
+
+       /* local variables inside method can only be final and non void */
+/*     
+       char[][] localTypeName; 
+       if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final 
+               || (localDeclaration.type == null) // initializer
+               || ((localTypeName = localDeclaration.type.getTypeName()).length == 1 // non void
+                       && CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){ 
+
+               if (delegatedByParent){
+                       return this; //ignore
+               } else {
+                       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));
+                       return this.parent.add(localDeclaration, bracketBalance);
+               }
+       }
+*/     
+               /* do not consider a local variable starting passed the block end (if set)
+               it must be belonging to an enclosing block */
+       if (this.blockDeclaration.sourceEnd != 0 
+                       && localDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
+               if (delegatedByParent) return this; //ignore
+               return this.parent.add(localDeclaration, bracketBalanceValue);
+       }
+
+       RecoveredLocalVariable element = new RecoveredLocalVariable(localDeclaration, this, bracketBalanceValue);
+
+       if (localDeclaration instanceof Argument){
+               this.pendingArgument = element;
+               return this;
+       }
+       
+       this.attach(element);
+       if (localDeclaration.declarationSourceEnd == 0) return element;
+       return this;    
+}
+/*
+ * Record a statement declaration 
+ */
+public RecoveredElement add(Statement stmt, int bracketBalanceValue) {
+       return this.add(stmt, bracketBalanceValue, false);
+}
+
+/*
+ * Record a statement declaration 
+ */
+public RecoveredElement add(Statement stmt, int bracketBalanceValue, boolean delegatedByParent) {
+
+       /* do not consider a nested block starting passed the block end (if set)
+               it must be belonging to an enclosing block */
+       if (this.blockDeclaration.sourceEnd != 0 
+                       && stmt.sourceStart > this.blockDeclaration.sourceEnd){
+               if (delegatedByParent) return this; //ignore
+               return this.parent.add(stmt, bracketBalanceValue);
+       }
+                       
+       RecoveredStatement element = new RecoveredStatement(stmt, this, bracketBalanceValue);
+       this.attach(element);
+       if (stmt.sourceEnd == 0) return element;
+       return this;    
+}
+/*
+ * Addition of a type to an initializer (act like inside method body)
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
+       return this.add(typeDeclaration, bracketBalanceValue, false);
+}
+/*
+ * Addition of a type to an initializer (act like inside method body)
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue, boolean delegatedByParent) {
+
+       /* do not consider a type starting passed the block end (if set)
+               it must be belonging to an enclosing block */
+       if (this.blockDeclaration.sourceEnd != 0 
+                       && typeDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
+               if (delegatedByParent) return this; //ignore
+               return this.parent.add(typeDeclaration, bracketBalanceValue);
+       }
+                       
+       RecoveredStatement element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
+       this.attach(element);
+       if (typeDeclaration.declarationSourceEnd == 0) return element;
+       return this;
+}
+/*
+ * Attach a recovered statement
+ */
+void attach(RecoveredStatement recoveredStatement) {
+
+       if (this.statements == null) {
+               this.statements = new RecoveredStatement[5];
+               this.statementCount = 0;
+       } else {
+               if (this.statementCount == this.statements.length) {
+                       System.arraycopy(
+                               this.statements, 
+                               0, 
+                               (this.statements = new RecoveredStatement[2 * this.statementCount]), 
+                               0, 
+                               this.statementCount); 
+               }
+       }
+       this.statements[this.statementCount++] = recoveredStatement;
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return this.blockDeclaration;
+}
+public String toString(int tab) {
+       StringBuffer result = new StringBuffer(tabString(tab));
+       result.append("Recovered block:\n"); //$NON-NLS-1$
+       this.blockDeclaration.print(tab + 1, result);
+       if (this.statements != null) {
+               for (int i = 0; i < this.statementCount; i++) {
+                       result.append("\n"); //$NON-NLS-1$
+                       result.append(this.statements[i].toString(tab + 1));
+               }
+       }
+       return result.toString();
+}
+/*
+ * Rebuild a block from the nested structure which is in scope
+ */
+public Block updatedBlock(){
+
+       // if block was not marked to be preserved or empty, then ignore it
+       if (!this.preserveContent || this.statementCount == 0) return null;
+
+       Statement[] updatedStatements = new Statement[this.statementCount];
+       int updatedCount = 0;
+       
+       // only collect the non-null updated statements
+       for (int i = 0; i < this.statementCount; i++){
+               Statement updatedStatement = this.statements[i].updatedStatement();
+               if (updatedStatement != null){
+                       updatedStatements[updatedCount++] = updatedStatement;
+               }
+       }
+       if (updatedCount == 0) return null; // not interesting block
+
+       // resize statement collection if necessary
+       if (updatedCount != this.statementCount){
+               this.blockDeclaration.statements = new Statement[updatedCount];
+               System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount);
+       } else {
+               this.blockDeclaration.statements = updatedStatements;
+       }
+
+       return this.blockDeclaration;
+}
+/*
+ * Rebuild a statement from the nested structure which is in scope
+ */
+public Statement updatedStatement(){
+
+       return this.updatedBlock();
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited
+ */
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+       if ((--this.bracketBalance <= 0) && (this.parent != null)){
+               this.updateSourceEndIfNecessary(braceStart, braceEnd);
+
+               /* if the block is the method body, then it closes the method too */
+               RecoveredMethod method = enclosingMethod();
+               if (method != null && method.methodBody == this){
+                       return this.parent.updateOnClosingBrace(braceStart, braceEnd);
+               }
+               RecoveredInitializer initializer = enclosingInitializer();
+               if (initializer != null && initializer.initializerBody == this){
+                       return this.parent.updateOnClosingBrace(braceStart, braceEnd);
+               }
+               return this.parent;
+       }
+       return this;
+}
+/*
+ * An opening brace got consumed, might be the expected opening one of the current element,
+ * in which case the bodyStart is updated.
+ */
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+
+       // create a nested block
+       Block block = new Block(0);
+       block.sourceStart = parser().scanner.startPosition;
+       return this.add(block, 1);
+}
+/*
+ * Final update the corresponding parse node
+ */
+public void updateParseTree(){
+
+       this.updatedBlock();
+}
+/*
+ * Rebuild a flattened block from the nested structure which is in scope
+ */
+public Statement updateStatement(){
+
+       // if block was closed or empty, then ignore it
+       if (this.blockDeclaration.sourceEnd != 0 || this.statementCount == 0) return null;
+
+       Statement[] updatedStatements = new Statement[this.statementCount];
+       int updatedCount = 0;
+       
+       // only collect the non-null updated statements
+       for (int i = 0; i < this.statementCount; i++){
+               Statement updatedStatement = this.statements[i].updatedStatement();
+               if (updatedStatement != null){
+                       updatedStatements[updatedCount++] = updatedStatement;
+               }
+       }
+       if (updatedCount == 0) return null; // not interesting block
+
+       // resize statement collection if necessary
+       if (updatedCount != this.statementCount){
+               this.blockDeclaration.statements = new Statement[updatedCount];
+               System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount);
+       } else {
+               this.blockDeclaration.statements = updatedStatements;
+       }
+
+       return this.blockDeclaration;
+}
+
+/*
+ * Record a field declaration 
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
+
+       /* local variables inside method can only be final and non void */
+       char[][] fieldTypeName; 
+       if ((fieldDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final 
+               || (fieldDeclaration.type == null) // initializer
+               || ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 // non void
+                       && CharOperation.equals(fieldTypeName[0], VoidBinding.sourceName()))){ 
+               this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));
+               return this.parent.add(fieldDeclaration, bracketBalanceValue);
+       }
+       
+       /* do not consider a local variable starting passed the block end (if set)
+               it must be belonging to an enclosing block */
+       if (this.blockDeclaration.sourceEnd != 0 
+               && fieldDeclaration.declarationSourceStart > this.blockDeclaration.sourceEnd){
+               return this.parent.add(fieldDeclaration, bracketBalanceValue);
+       }
+
+       // ignore the added field, since indicates a local variable behind recovery point
+       // which thus got parsed as a field reference. This can happen if restarting after
+       // having reduced an assistNode to get the following context (see 1GEK7SG)
+       return this;    
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java
new file mode 100644 (file)
index 0000000..bea72d2
--- /dev/null
@@ -0,0 +1,308 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal structure for parsing recovery 
+ */
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+
+public class RecoveredElement {
+
+       public RecoveredElement parent;
+       public int bracketBalance;
+       public boolean foundOpeningBrace;
+       protected Parser recoveringParser;
+public RecoveredElement(RecoveredElement parent, int bracketBalance){
+       this(parent, bracketBalance, null);
+}
+public RecoveredElement(RecoveredElement parent, int bracketBalance, Parser parser){
+       this.parent = parent;
+       this.bracketBalance = bracketBalance;
+       this.recoveringParser = parser;
+}
+/*
+ *     Record a method declaration
+ */
+public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(methodDeclaration.declarationSourceStart - 1));   
+       return this.parent.add(methodDeclaration, bracketBalanceValue);
+}
+/*
+ * Record a nested block declaration
+ */
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(nestedBlockDeclaration.sourceStart - 1)); 
+       return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
+}
+/*
+ * Record a field declaration
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));    
+       return this.parent.add(fieldDeclaration, bracketBalanceValue);
+}
+/*
+ *     Record an import reference
+ */
+public RecoveredElement add(ImportReference importReference, int bracketBalanceValue){
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(importReference.declarationSourceStart - 1));     
+       return this.parent.add(importReference, bracketBalanceValue);
+}
+/*
+ * Record a local declaration
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));    
+       return this.parent.add(localDeclaration, bracketBalanceValue);
+}
+/*
+ * Record a statement
+ */
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(statement.sourceStart - 1));      
+       return this.parent.add(statement, bracketBalanceValue);
+}
+/*
+ *     Record a type declaration
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue){
+
+       /* default behavior is to delegate recording to parent if any */
+       if (this.parent == null) return this; // ignore
+       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));     
+       return this.parent.add(typeDeclaration, bracketBalanceValue);
+}
+/*
+ * Answer the depth of this element, considering the parent link.
+ */
+public int depth(){
+       int depth = 0;
+       RecoveredElement current = this;
+       while ((current = current.parent) != null) depth++;
+       return depth;
+}
+/*
+ * Answer the enclosing method node, or null if none
+ */
+public RecoveredInitializer enclosingInitializer(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredInitializer){
+                       return (RecoveredInitializer) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Answer the enclosing method node, or null if none
+ */
+public RecoveredMethod enclosingMethod(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredMethod){
+                       return (RecoveredMethod) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Answer the enclosing type node, or null if none
+ */
+public RecoveredType enclosingType(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredType){
+                       return (RecoveredType) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Answer the closest specified parser
+ */
+public Parser parser(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current.recoveringParser != null){
+                       return current.recoveringParser;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return null;
+}
+/*
+ * Iterate the enclosing blocks and tag them so as to preserve their content
+ */
+public void preserveEnclosingBlocks(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredBlock){
+                       ((RecoveredBlock)current).preserveContent = true;
+               }
+               if (current instanceof RecoveredType){ // for anonymous types
+                       ((RecoveredType)current).preserveContent = true;
+               }
+               current = current.parent;
+       }
+}
+/*
+ * Answer the position of the previous line end if
+ * there is nothing but spaces in between it and the
+ * line end. Used to trim spaces on unclosed elements.
+ */
+public int previousAvailableLineEnd(int position){
+
+       Parser parser = this.parser();
+       if (parser == null) return position;
+       
+       Scanner scanner = parser.scanner;
+       if (scanner.lineEnds == null) return position;
+       
+       int index = scanner.getLineNumber(position);
+       if (index < 2) return position;
+       int previousLineEnd = scanner.lineEnds[index-2];
+
+       char[] source = scanner.source;
+       for (int i = previousLineEnd+1; i < position; i++){
+               if (!(source[i] == ' ' || source[i] == '\t')) return position;
+       }
+       return previousLineEnd;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return 0;
+}
+protected String tabString(int tab) {
+       StringBuffer result = new StringBuffer();
+       for (int i = tab; i > 0; i--) {
+               result.append("  "); //$NON-NLS-1$
+       }
+       return result.toString();
+}
+/*
+ * Answer the top node
+ */
+public RecoveredElement topElement(){
+       RecoveredElement current = this;
+       while (current.parent != null){
+               current = current.parent;
+       }
+       return current;
+}
+public String toString() {
+       return toString(0);
+}
+public String toString(int tab) {
+       return super.toString();
+}
+/*
+ * Answer the enclosing type node, or null if none
+ */
+public RecoveredType type(){
+       RecoveredElement current = this;
+       while (current != null){
+               if (current instanceof RecoveredType){
+                       return (RecoveredType) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void updateBodyStart(int bodyStart){
+       this.foundOpeningBrace = true;  
+}
+/*
+ * Update the corresponding parse node from parser state which
+ * is about to disappear because of restarting recovery
+ */
+public void updateFromParserState(){
+       // default implementation: do nothing
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited
+ */
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+       if ((--this.bracketBalance <= 0) && (this.parent != null)){
+               this.updateSourceEndIfNecessary(braceStart, braceEnd);
+               return this.parent;
+       }
+       return this;
+}
+/*
+ * An opening brace got consumed, might be the expected opening one of the current element,
+ * in which case the bodyStart is updated.
+ */
+/*public RecoveredElement updateOnOpeningBrace(int braceEnd){return null;}*/
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+
+       if (this.bracketBalance++ == 0){
+               this.updateBodyStart(braceEnd + 1);
+               return this;
+       }
+       return null; // no update is necessary
+}
+/*
+ * Final update the corresponding parse node
+ */
+public void updateParseTree(){
+       // default implementation: do nothing
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
+       // default implementation: do nothing
+}
+public void updateSourceEndIfNecessary(int sourceEnd){
+       this.updateSourceEndIfNecessary(sourceEnd + 1, sourceEnd);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredField.java
new file mode 100644 (file)
index 0000000..4133b61
--- /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.parser;
+
+/**
+ * Internal field structure for parsing recovery 
+ */
+import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+
+public class RecoveredField extends RecoveredElement {
+
+       public FieldDeclaration fieldDeclaration;
+       boolean alreadyCompletedFieldInitialization;
+       
+       public RecoveredType[] anonymousTypes;
+       public int anonymousTypeCount;
+public RecoveredField(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance){
+       this(fieldDeclaration, parent, bracketBalance, null);
+}
+public RecoveredField(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){
+       super(parent, bracketBalance, parser);
+       this.fieldDeclaration = fieldDeclaration;
+       this.alreadyCompletedFieldInitialization = fieldDeclaration.initialization != null;
+}
+/*
+ * Record an expression statement if field is expecting an initialization expression,
+ * used for completion inside field initializers.
+ */
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
+
+       if (this.alreadyCompletedFieldInitialization || !(statement instanceof Expression)) {
+               return super.add(statement, bracketBalanceValue);
+       } else {
+               this.alreadyCompletedFieldInitialization = true;
+               this.fieldDeclaration.initialization = (Expression)statement;
+               this.fieldDeclaration.declarationSourceEnd = statement.sourceEnd;
+               this.fieldDeclaration.declarationEnd = statement.sourceEnd;
+               return this;
+       }
+}
+/*
+ * Record a type declaration if this field is expecting an initialization expression 
+ * and the type is an anonymous type.
+ * Used for completion inside field initializers.
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
+
+       if (this.alreadyCompletedFieldInitialization 
+                       || ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) == 0)
+                       || (this.fieldDeclaration.declarationSourceEnd != 0 && typeDeclaration.sourceStart > this.fieldDeclaration.declarationSourceEnd)) {
+               return super.add(typeDeclaration, bracketBalanceValue);
+       } else { 
+               // Prepare anonymous type list
+               if (this.anonymousTypes == null) {
+                       this.anonymousTypes = new RecoveredType[5];
+                       this.anonymousTypeCount = 0;
+               } else {
+                       if (this.anonymousTypeCount == this.anonymousTypes.length) {
+                               System.arraycopy(
+                                       this.anonymousTypes, 
+                                       0, 
+                                       (this.anonymousTypes = new RecoveredType[2 * this.anonymousTypeCount]), 
+                                       0, 
+                                       this.anonymousTypeCount); 
+                       }
+               }
+               // Store type declaration as an anonymous type
+               RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
+               this.anonymousTypes[this.anonymousTypeCount++] = element;
+               return element;
+       }
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return fieldDeclaration;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return this.fieldDeclaration.declarationSourceEnd;
+}
+public String toString(int tab){
+       StringBuffer buffer = new StringBuffer(tabString(tab));
+       buffer.append("Recovered field:\n"); //$NON-NLS-1$
+       fieldDeclaration.print(tab + 1, buffer);
+       if (this.anonymousTypes != null) {
+               for (int i = 0; i < this.anonymousTypeCount; i++){
+                       buffer.append("\n"); //$NON-NLS-1$
+                       buffer.append(anonymousTypes[i].toString(tab + 1));
+               }
+       }
+       return buffer.toString();
+}
+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.anonymousTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
+       }
+       return fieldDeclaration;
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited.
+ *
+ * Fields have no associated braces, thus if matches, then update parent.
+ */
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+       if (bracketBalance > 0){ // was an array initializer
+               bracketBalance--;
+               if (bracketBalance == 0) alreadyCompletedFieldInitialization = true;
+               return this;
+       } else if (bracketBalance == 0) {
+               alreadyCompletedFieldInitialization = true;
+               updateSourceEndIfNecessary(braceEnd - 1);
+       }
+       if (parent != null){
+               return parent.updateOnClosingBrace(braceStart, braceEnd);
+       }
+       return this;
+}
+/*
+ * An opening brace got consumed, might be the expected opening one of the current element,
+ * in which case the bodyStart is updated.
+ */
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+       if (fieldDeclaration.declarationSourceEnd == 0 
+               && fieldDeclaration.type instanceof ArrayTypeReference
+               && !alreadyCompletedFieldInitialization){
+               bracketBalance++;
+               return null; // no update is necessary  (array initializer)
+       }
+       // might be an array initializer
+       this.updateSourceEndIfNecessary(braceStart - 1, braceEnd - 1);  
+       return this.parent.updateOnOpeningBrace(braceStart, braceEnd);  
+}
+public void updateParseTree(){
+       this.updatedFieldDeclaration();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+       if (this.fieldDeclaration.declarationSourceEnd == 0) {
+               this.fieldDeclaration.declarationSourceEnd = bodyEnd;
+               this.fieldDeclaration.declarationEnd = bodyEnd;
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredImport.java
new file mode 100644 (file)
index 0000000..a86c81a
--- /dev/null
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal import structure for parsing recovery 
+ */
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+
+public class RecoveredImport extends RecoveredElement {
+
+       public ImportReference importReference;
+public RecoveredImport(ImportReference importReference, RecoveredElement parent, int bracketBalance){
+       super(parent, bracketBalance);
+       this.importReference = importReference;
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return importReference;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return this.importReference.declarationSourceEnd;
+}
+public String toString(int tab) {
+       return tabString(tab) + "Recovered import: " + importReference.toString(); //$NON-NLS-1$
+}
+public ImportReference updatedImportReference(){
+
+       return importReference;
+}
+public void updateParseTree(){
+       this.updatedImportReference();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+       if (this.importReference.declarationSourceEnd == 0) {
+               this.importReference.declarationSourceEnd = bodyEnd;
+               this.importReference.declarationEnd = bodyEnd;
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredInitializer.java
new file mode 100644 (file)
index 0000000..66d1aae
--- /dev/null
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal initializer structure for parsing recovery 
+ */
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.BaseTypes;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+
+public class RecoveredInitializer extends RecoveredField implements CompilerModifiers, TerminalTokens, BaseTypes {
+
+       public RecoveredType[] localTypes;
+       public int localTypeCount;
+
+       public RecoveredBlock initializerBody;  
+
+public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance){
+       this(fieldDeclaration, parent, bracketBalance, null);
+}
+public RecoveredInitializer(FieldDeclaration fieldDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){
+       super(fieldDeclaration, parent, bracketBalance, parser);
+       this.foundOpeningBrace = true;
+}
+/*
+ * Record a nested block declaration
+ */
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any,
+       do not consider elements passed the known end (if set)
+       it must be belonging to an enclosing element 
+       */
+       if (fieldDeclaration.declarationSourceEnd > 0
+                       && nestedBlockDeclaration.sourceStart > fieldDeclaration.declarationSourceEnd){
+               if (this.parent == null) return this; // ignore
+               return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
+       }
+       /* consider that if the opening brace was not found, it is there */
+       if (!foundOpeningBrace){
+               foundOpeningBrace = true;
+               this.bracketBalance++;
+       }
+       initializerBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
+       if (nestedBlockDeclaration.sourceEnd == 0) return initializerBody;
+       return this;
+}
+/*
+ * Record a field declaration (act like inside method body)
+ */
+public RecoveredElement add(FieldDeclaration newFieldDeclaration, int bracketBalanceValue) {
+
+       /* local variables inside initializer can only be final and non void */
+       char[][] fieldTypeName;
+       if ((newFieldDeclaration.modifiers & ~AccFinal) != 0 /* local var can only be final */
+                       || (newFieldDeclaration.type == null) // initializer
+                       || ((fieldTypeName = newFieldDeclaration.type.getTypeName()).length == 1 // non void
+                               && CharOperation.equals(fieldTypeName[0], VoidBinding.sourceName()))){ 
+               if (this.parent == null) return this; // ignore
+               this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(newFieldDeclaration.declarationSourceStart - 1));
+               return this.parent.add(newFieldDeclaration, bracketBalanceValue);
+       }
+
+       /* default behavior is to delegate recording to parent if any,
+       do not consider elements passed the known end (if set)
+       it must be belonging to an enclosing element 
+       */
+       if (this.fieldDeclaration.declarationSourceEnd > 0
+                       && newFieldDeclaration.declarationSourceStart > this.fieldDeclaration.declarationSourceEnd){
+               if (this.parent == null) return this; // ignore
+               return this.parent.add(newFieldDeclaration, bracketBalanceValue);
+       }
+       // still inside initializer, treat as local variable
+       return this; // ignore
+}
+/*
+ * Record a local declaration - regular method should have been created a block body
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
+
+       /* do not consider a type starting passed the type end (if set)
+               it must be belonging to an enclosing type */
+       if (fieldDeclaration.declarationSourceEnd != 0 
+                       && localDeclaration.declarationSourceStart > fieldDeclaration.declarationSourceEnd){
+               if (parent == null) return this; // ignore
+               return this.parent.add(localDeclaration, bracketBalanceValue);
+       }
+       /* method body should have been created */
+       Block block = new Block(0);
+       block.sourceStart = ((Initializer)fieldDeclaration).sourceStart;
+       RecoveredElement element = this.add(block, 1);
+       return element.add(localDeclaration, bracketBalanceValue);      
+}
+/*
+ * Record a statement - regular method should have been created a block body
+ */
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
+
+       /* do not consider a statement starting passed the initializer end (if set)
+               it must be belonging to an enclosing type */
+       if (fieldDeclaration.declarationSourceEnd != 0 
+                       && statement.sourceStart > fieldDeclaration.declarationSourceEnd){
+               if (parent == null) return this; // ignore
+               return this.parent.add(statement, bracketBalanceValue);
+       }
+       /* initializer body should have been created */
+       Block block = new Block(0);
+       block.sourceStart = ((Initializer)fieldDeclaration).sourceStart;
+       RecoveredElement element = this.add(block, 1);
+       return element.add(statement, bracketBalanceValue);     
+}
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
+
+       /* do not consider a type starting passed the type end (if set)
+               it must be belonging to an enclosing type */
+       if (fieldDeclaration.declarationSourceEnd != 0 
+                       && typeDeclaration.declarationSourceStart > fieldDeclaration.declarationSourceEnd){
+               if (parent == null) return this; // ignore
+               return this.parent.add(typeDeclaration, bracketBalanceValue);
+       }
+       if ((typeDeclaration.bits & ASTNode.IsLocalTypeMASK) != 0){
+               /* method body should have been created */
+               Block block = new Block(0);
+               block.sourceStart = ((Initializer)fieldDeclaration).sourceStart;
+               RecoveredElement element = this.add(block, 1);
+               return element.add(typeDeclaration, bracketBalanceValue);       
+       }       
+       if (localTypes == null) {
+               localTypes = new RecoveredType[5];
+               localTypeCount = 0;
+       } else {
+               if (localTypeCount == localTypes.length) {
+                       System.arraycopy(
+                               localTypes, 
+                               0, 
+                               (localTypes = new RecoveredType[2 * localTypeCount]), 
+                               0, 
+                               localTypeCount); 
+               }
+       }
+       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;
+               this.bracketBalance++;
+       }
+       return element;
+}
+public String toString(int tab) {
+       StringBuffer result = new StringBuffer(tabString(tab));
+       result.append("Recovered initializer:\n"); //$NON-NLS-1$
+       this.fieldDeclaration.print(tab + 1, result);
+       if (this.initializerBody != null) {
+               result.append("\n"); //$NON-NLS-1$
+               result.append(this.initializerBody.toString(tab + 1));
+       }
+       return result.toString();
+}
+public FieldDeclaration updatedFieldDeclaration(){
+
+       if (initializerBody != null){
+               Block block = initializerBody.updatedBlock();
+               if (block != null){
+                       ((Initializer)fieldDeclaration).block = block;
+               }
+               if (this.localTypeCount > 0) fieldDeclaration.bits |= ASTNode.HasLocalTypeMASK;
+
+       }       
+       if (fieldDeclaration.sourceEnd == 0){
+               fieldDeclaration.sourceEnd = fieldDeclaration.declarationSourceEnd;
+       }
+       return fieldDeclaration;
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited
+ */
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+       if ((--bracketBalance <= 0) && (parent != null)){
+               this.updateSourceEndIfNecessary(braceStart, braceEnd);
+               return parent;
+       }
+       return this;
+}
+/*
+ * An opening brace got consumed, might be the expected opening one of the current element,
+ * in which case the bodyStart is updated.
+ */
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+       bracketBalance++;
+       return this; // request to restart
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
+       if (this.fieldDeclaration.declarationSourceEnd == 0) {
+               Initializer initializer = (Initializer)fieldDeclaration;
+               if(parser().rBraceSuccessorStart >= braceEnd) {
+                       if (initializer.bodyStart < parser().rBraceEnd) {
+                               initializer.declarationSourceEnd = parser().rBraceEnd;
+                       } else {
+                               initializer.declarationSourceEnd = initializer.bodyStart;
+                       }
+                       if (initializer.bodyStart < parser().rBraceStart) {
+                               initializer.bodyEnd = parser().rBraceStart;
+                       } else {
+                               initializer.bodyEnd = initializer.bodyStart;
+                       }
+               } else {
+                       initializer.declarationSourceEnd = braceEnd;
+                       initializer.bodyEnd  = braceStart - 1;
+               }
+               if(initializer.block != null) {
+                       initializer.block.sourceEnd = initializer.declarationSourceEnd;
+               }
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredLocalVariable.java
new file mode 100644 (file)
index 0000000..27b2fb2
--- /dev/null
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal local variable structure for parsing recovery 
+ */
+import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+
+public class RecoveredLocalVariable extends RecoveredStatement {
+
+       public LocalDeclaration localDeclaration;
+       boolean alreadyCompletedLocalInitialization;
+public RecoveredLocalVariable(LocalDeclaration localDeclaration, RecoveredElement parent, int bracketBalance){
+       super(localDeclaration, parent, bracketBalance);
+       this.localDeclaration = localDeclaration;
+       this.alreadyCompletedLocalInitialization = localDeclaration.initialization != null;
+}
+/*
+ * Record an expression statement if local variable is expecting an initialization expression. 
+ */
+public RecoveredElement add(Statement stmt, int bracketBalanceValue) {
+
+       if (this.alreadyCompletedLocalInitialization || !(stmt instanceof Expression)) {
+               return super.add(stmt, bracketBalanceValue);
+       } else {
+               this.alreadyCompletedLocalInitialization = true;
+               this.localDeclaration.initialization = (Expression)stmt;
+               this.localDeclaration.declarationSourceEnd = stmt.sourceEnd;
+               this.localDeclaration.declarationEnd = stmt.sourceEnd;
+               return this;
+       }
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return localDeclaration;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return this.localDeclaration.declarationSourceEnd;
+}
+public String toString(int tab) {
+       return tabString(tab) + "Recovered local variable:\n" + localDeclaration.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$
+}
+public Statement updatedStatement(){
+       return localDeclaration;
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited.
+ *
+ * Fields have no associated braces, thus if matches, then update parent.
+ */
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+       if (bracketBalance > 0){ // was an array initializer
+               bracketBalance--;
+               if (bracketBalance == 0) alreadyCompletedLocalInitialization = true;
+               return this;
+       }
+       if (parent != null){
+               return parent.updateOnClosingBrace(braceStart, braceEnd);
+       }
+       return this;
+}
+/*
+ * An opening brace got consumed, might be the expected opening one of the current element,
+ * in which case the bodyStart is updated.
+ */
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+       if (localDeclaration.declarationSourceEnd == 0 
+               && localDeclaration.type instanceof ArrayTypeReference
+               && !alreadyCompletedLocalInitialization){
+               bracketBalance++;
+               return null; // no update is necessary  (array initializer)
+       }
+       // might be an array initializer
+       this.updateSourceEndIfNecessary(braceStart - 1, braceEnd - 1);  
+       return this.parent.updateOnOpeningBrace(braceStart, braceEnd);  
+}
+public void updateParseTree(){
+       this.updatedStatement();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+       if (this.localDeclaration.declarationSourceEnd == 0) {
+               this.localDeclaration.declarationSourceEnd = bodyEnd;
+               this.localDeclaration.declarationEnd = bodyEnd; 
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
new file mode 100644 (file)
index 0000000..b76bf04
--- /dev/null
@@ -0,0 +1,447 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.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.lookup.BaseTypes;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+
+/**
+ * Internal method structure for parsing recovery 
+ */
+
+public class RecoveredMethod extends RecoveredElement implements CompilerModifiers, TerminalTokens, BaseTypes {
+
+       public AbstractMethodDeclaration methodDeclaration;
+
+       public RecoveredType[] localTypes;
+       public int localTypeCount;
+
+       public RecoveredBlock methodBody;
+       public boolean discardBody = true;
+
+public RecoveredMethod(AbstractMethodDeclaration methodDeclaration, RecoveredElement parent, int bracketBalance, Parser parser){
+       super(parent, bracketBalance, parser);
+       this.methodDeclaration = methodDeclaration;
+       this.foundOpeningBrace = !bodyStartsAtHeaderEnd();
+       if(this.foundOpeningBrace) {
+               this.bracketBalance++;
+       }
+}
+/*
+ * Record a nested block declaration
+ */
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
+
+       /* default behavior is to delegate recording to parent if any,
+       do not consider elements passed the known end (if set)
+       it must be belonging to an enclosing element 
+       */
+       if (methodDeclaration.declarationSourceEnd > 0
+               && nestedBlockDeclaration.sourceStart
+                       > methodDeclaration.declarationSourceEnd){
+                               if (this.parent == null){
+                                       return this; // ignore
+                               } else {
+                                       return this.parent.add(nestedBlockDeclaration, bracketBalanceValue);
+                               }
+       }
+       /* consider that if the opening brace was not found, it is there */
+       if (!foundOpeningBrace){
+               foundOpeningBrace = true;
+               this.bracketBalance++;
+       }
+
+       methodBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalanceValue);
+       if (nestedBlockDeclaration.sourceEnd == 0) return methodBody;
+       return this;
+}
+/*
+ * Record a field declaration
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
+
+       /* local variables inside method can only be final and non void */
+       char[][] fieldTypeName; 
+       if ((fieldDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final 
+               || (fieldDeclaration.type == null) // initializer
+               || ((fieldTypeName = fieldDeclaration.type.getTypeName()).length == 1 // non void
+                       && CharOperation.equals(fieldTypeName[0], VoidBinding.sourceName()))){ 
+
+               if (this.parent == null){
+                       return this; // ignore
+               } else {
+                       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));
+                       return this.parent.add(fieldDeclaration, bracketBalanceValue);
+               }
+       }
+       /* default behavior is to delegate recording to parent if any,
+       do not consider elements passed the known end (if set)
+       it must be belonging to an enclosing element 
+       */
+       if (methodDeclaration.declarationSourceEnd > 0
+               && fieldDeclaration.declarationSourceStart
+                       > methodDeclaration.declarationSourceEnd){
+               if (this.parent == null){
+                       return this; // ignore
+               } else {
+                       return this.parent.add(fieldDeclaration, bracketBalanceValue);
+               }
+       }
+       /* consider that if the opening brace was not found, it is there */
+       if (!foundOpeningBrace){
+               foundOpeningBrace = true;
+               this.bracketBalance++;
+       }
+       // still inside method, treat as local variable
+       return this; // ignore
+}
+/*
+ * Record a local declaration - regular method should have been created a block body
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
+
+       /* local variables inside method can only be final and non void */
+/*     
+       char[][] localTypeName; 
+       if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final 
+               || (localDeclaration.type == null) // initializer
+               || ((localTypeName = localDeclaration.type.getTypeName()).length == 1 // non void
+                       && CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){ 
+
+               if (this.parent == null){
+                       return this; // ignore
+               } else {
+                       this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));
+                       return this.parent.add(localDeclaration, bracketBalance);
+               }
+       }
+*/
+       /* do not consider a type starting passed the type end (if set)
+               it must be belonging to an enclosing type */
+       if (methodDeclaration.declarationSourceEnd != 0 
+               && localDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd){
+                       
+               if (this.parent == null) {
+                       return this; // ignore
+               } else {
+                       return this.parent.add(localDeclaration, bracketBalanceValue);
+               }
+       }
+       if (methodBody == null){
+               Block block = new Block(0);
+               block.sourceStart = methodDeclaration.bodyStart;
+               RecoveredElement currentBlock = this.add(block, 1);
+               if (this.bracketBalance > 0){
+                       for (int i = 0; i < this.bracketBalance - 1; i++){
+                               currentBlock = currentBlock.add(new Block(0), 1);
+                       }
+                       this.bracketBalance = 1;
+               }
+               return currentBlock.add(localDeclaration, bracketBalanceValue);
+       }
+       return methodBody.add(localDeclaration, bracketBalanceValue, true);
+}
+/*
+ * Record a statement - regular method should have been created a block body
+ */
+public RecoveredElement add(Statement statement, int bracketBalanceValue) {
+
+       /* do not consider a type starting passed the type end (if set)
+               it must be belonging to an enclosing type */
+       if (methodDeclaration.declarationSourceEnd != 0 
+               && statement.sourceStart > methodDeclaration.declarationSourceEnd){
+
+               if (this.parent == null) {
+                       return this; // ignore
+               } else {
+                       return this.parent.add(statement, bracketBalanceValue);
+               }
+       }
+       if (methodBody == null){
+               Block block = new Block(0);
+               block.sourceStart = methodDeclaration.bodyStart;
+               RecoveredElement currentBlock = this.add(block, 1);
+               if (this.bracketBalance > 0){
+                       for (int i = 0; i < this.bracketBalance - 1; i++){
+                               currentBlock = currentBlock.add(new Block(0), 1);
+                       }
+                       this.bracketBalance = 1;
+               }
+               return currentBlock.add(statement, bracketBalanceValue);
+       }
+       return methodBody.add(statement, bracketBalanceValue, true);    
+}
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
+
+       /* do not consider a type starting passed the type end (if set)
+               it must be belonging to an enclosing type */
+       if (methodDeclaration.declarationSourceEnd != 0 
+               && typeDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd){
+                       
+               if (this.parent == null) {
+                       return this; // ignore
+               }
+               return this.parent.add(typeDeclaration, bracketBalanceValue);
+       }
+       if ((typeDeclaration.bits & ASTNode.IsLocalTypeMASK) != 0){
+               if (methodBody == null){
+                       Block block = new Block(0);
+                       block.sourceStart = methodDeclaration.bodyStart;
+                       this.add(block, 1);
+               }
+               return methodBody.add(typeDeclaration, bracketBalanceValue, true);      
+       }
+       if (typeDeclaration.isInterface()) {
+               this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));
+               if (this.parent == null) {
+                       return this; // ignore
+               }
+               // close the constructor
+               return this.parent.add(typeDeclaration, bracketBalanceValue);
+       }
+       if (localTypes == null) {
+               localTypes = new RecoveredType[5];
+               localTypeCount = 0;
+       } else {
+               if (localTypeCount == localTypes.length) {
+                       System.arraycopy(
+                               localTypes, 
+                               0, 
+                               (localTypes = new RecoveredType[2 * localTypeCount]), 
+                               0, 
+                               localTypeCount); 
+               }
+       }
+       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;
+               this.bracketBalance++;
+       }
+       return element;
+}
+public boolean bodyStartsAtHeaderEnd(){
+       return methodDeclaration.bodyStart == methodDeclaration.sourceEnd+1;
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return methodDeclaration;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return this.methodDeclaration.declarationSourceEnd;
+}
+public String toString(int tab) {
+       StringBuffer result = new StringBuffer(tabString(tab));
+       result.append("Recovered method:\n"); //$NON-NLS-1$
+       this.methodDeclaration.print(tab + 1, result);
+       if (this.localTypes != null) {
+               for (int i = 0; i < this.localTypeCount; i++) {
+                       result.append("\n"); //$NON-NLS-1$
+                       result.append(this.localTypes[i].toString(tab + 1));
+               }
+       }
+       if (this.methodBody != null) {
+               result.append("\n"); //$NON-NLS-1$
+               result.append(this.methodBody.toString(tab + 1));
+       }
+       return result.toString();
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void updateBodyStart(int bodyStart){
+       this.foundOpeningBrace = true;          
+       this.methodDeclaration.bodyStart = bodyStart;
+}
+public AbstractMethodDeclaration updatedMethodDeclaration(){
+
+       if (methodBody != null){
+               Block block = methodBody.updatedBlock();
+               if (block != null){
+                       methodDeclaration.statements = block.statements;
+
+                       /* first statement might be an explict constructor call destinated to a special slot */
+                       if (methodDeclaration.isConstructor()) {
+                               ConstructorDeclaration constructor = (ConstructorDeclaration)methodDeclaration;
+                               if (methodDeclaration.statements != null
+                                       && methodDeclaration.statements[0] instanceof ExplicitConstructorCall){
+                                       constructor.constructorCall = (ExplicitConstructorCall)methodDeclaration.statements[0];
+                                       int length = methodDeclaration.statements.length;
+                                       System.arraycopy(
+                                               methodDeclaration.statements, 
+                                               1, 
+                                               (methodDeclaration.statements = new Statement[length-1]),
+                                               0,
+                                               length-1);
+                                       }
+                                       if (constructor.constructorCall == null){ // add implicit constructor call
+                                               constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
+                                       }
+                       }
+               }
+       }
+       if (localTypeCount > 0) methodDeclaration.bits |= ASTNode.HasLocalTypeMASK;
+       return methodDeclaration;
+}
+/*
+ * Update the corresponding parse node from parser state which
+ * is about to disappear because of restarting recovery
+ */
+public void updateFromParserState(){
+
+       if(this.bodyStartsAtHeaderEnd()){
+               Parser parser = this.parser();
+               /* might want to recover arguments or thrown exceptions */
+               if (parser.listLength > 0 && parser.astLengthPtr > 0){ // awaiting interface type references
+                       /* has consumed the arguments - listed elements must be thrown exceptions */
+                       if (methodDeclaration.sourceEnd == parser.rParenPos) {
+                               
+                               // protection for bugs 15142
+                               int length = parser.astLengthStack[parser.astLengthPtr];
+                               int astPtr = parser.astPtr - length;
+                               boolean canConsume = astPtr >= 0;
+                               if(canConsume) {
+                                       if((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) {
+                                               canConsume = false;
+                                       }
+                                       for (int i = 1, max = length + 1; i < max; i++) {
+                                               if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) {
+                                                       canConsume = false;
+                                               }
+                                       }
+                               }
+                               if (canConsume){
+                                       parser.consumeMethodHeaderThrowsClause(); 
+                                       // will reset typeListLength to zero
+                                       // thus this check will only be performed on first errorCheck after void foo() throws X, Y,
+                               } else {
+                                       parser.listLength = 0;
+                               }
+                       } else {
+                               /* has not consumed arguments yet, listed elements must be arguments */
+                               if (parser.currentToken == TokenNameLPAREN || parser.currentToken == TokenNameSEMICOLON){
+                                       /* if currentToken is parenthesis this last argument is a method/field signature */
+                                       parser.astLengthStack[parser.astLengthPtr] --; 
+                                       parser.astPtr --; 
+                                       parser.listLength --;
+                                       parser.currentToken = 0;
+                               }
+                               int argLength = parser.astLengthStack[parser.astLengthPtr];
+                               int argStart = parser.astPtr - argLength + 1;
+                               boolean needUpdateRParenPos = parser.rParenPos < parser.lParenPos; // 12387 : rParenPos will be used
+                               // to compute bodyStart, and thus used to set next checkpoint.
+                               int count;
+                               for (count = 0; count < argLength; count++){
+                                       Argument argument = (Argument)parser.astStack[argStart+count];
+                                       /* cannot be an argument if non final */
+                                       char[][] argTypeName = argument.type.getTypeName();
+                                       if ((argument.modifiers & ~AccFinal) != 0
+                                               || (argTypeName.length == 1
+                                                       && CharOperation.equals(argTypeName[0], VoidBinding.sourceName()))){
+                                               parser.astLengthStack[parser.astLengthPtr] = count; 
+                                               parser.astPtr = argStart+count-1; 
+                                               parser.listLength = count;
+                                               parser.currentToken = 0;
+                                               break;
+                                       }
+                                       if (needUpdateRParenPos) parser.rParenPos = argument.sourceEnd + 1;
+                               }
+                               if (parser.listLength > 0 && parser.astLengthPtr > 0){
+                                       
+                                       // protection for bugs 15142
+                                       int length = parser.astLengthStack[parser.astLengthPtr];
+                                       int astPtr = parser.astPtr - length;
+                                       boolean canConsume = astPtr >= 0;
+                                       if(canConsume) {
+                                               if((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) {
+                                                       canConsume = false;
+                                               }
+                                               for (int i = 1, max = length + 1; i < max; i++) {
+                                                       if(!(parser.astStack[astPtr + i ] instanceof Argument)) {
+                                                               canConsume = false;
+                                                       }
+                                               }
+                                       }
+                                       if(canConsume) {
+                                               parser.consumeMethodHeaderParameters();
+                                               /* 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;
+                                                       methodDeclaration.bodyStart = methodDeclaration.sourceEnd+1;
+                                                       parser.lastCheckPoint = methodDeclaration.bodyStart;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+}
+/*
+ * An opening brace got consumed, might be the expected opening one of the current element,
+ * in which case the bodyStart is updated.
+ */
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+
+       /* in case the opening brace is close enough to the signature */
+       if (bracketBalance == 0){
+               /*
+                       if (parser.scanner.searchLineNumber(methodDeclaration.sourceEnd) 
+                               != parser.scanner.searchLineNumber(braceEnd)){
+                */
+               switch(parser().lastIgnoredToken){
+                       case -1 :
+                       case TokenNamethrows :
+                               break;
+                       default:
+                               this.foundOpeningBrace = true;                          
+                               bracketBalance = 1; // pretend the brace was already there
+               }
+       }       
+       return super.updateOnOpeningBrace(braceStart, braceEnd);
+}
+public void updateParseTree(){
+       this.updatedMethodDeclaration();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int braceStart, int braceEnd){
+       if (this.methodDeclaration.declarationSourceEnd == 0) {
+               if(parser().rBraceSuccessorStart >= braceEnd) {
+                       this.methodDeclaration.declarationSourceEnd = parser().rBraceEnd;
+                       this.methodDeclaration.bodyEnd = parser().rBraceStart;
+               } else {
+                       this.methodDeclaration.declarationSourceEnd = braceEnd;
+                       this.methodDeclaration.bodyEnd  = braceStart - 1;
+               }
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredStatement.java
new file mode 100644 (file)
index 0000000..adbb79e
--- /dev/null
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal statement structure for parsing recovery 
+ */
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+
+public class RecoveredStatement extends RecoveredElement {
+
+       public Statement statement;
+public RecoveredStatement(Statement statement, RecoveredElement parent, int bracketBalance){
+       super(parent, bracketBalance);
+       this.statement = statement;
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return statement;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return this.statement.sourceEnd;
+}
+public String toString(int tab){
+       return tabString(tab) + "Recovered statement:\n" + statement.print(tab + 1, new StringBuffer(10)); //$NON-NLS-1$
+}
+public Statement updatedStatement(){
+       return statement;
+}
+public void updateParseTree(){
+       this.updatedStatement();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+       if (this.statement.sourceEnd == 0)      
+               this.statement.sourceEnd = bodyEnd;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
new file mode 100644 (file)
index 0000000..9ac355e
--- /dev/null
@@ -0,0 +1,479 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+
+/**
+ * Internal type structure for parsing recovery 
+ */
+
+public class RecoveredType extends RecoveredStatement implements TerminalTokens, CompilerModifiers {
+       public TypeDeclaration typeDeclaration;
+
+       public RecoveredType[] memberTypes;
+       public int memberTypeCount;
+       public RecoveredField[] fields;
+       public int fieldCount;
+       public RecoveredMethod[] methods;
+       public int methodCount;
+
+       public boolean preserveContent = false; // only used for anonymous types
+       public int bodyEnd;
+       
+public RecoveredType(TypeDeclaration typeDeclaration, RecoveredElement parent, int bracketBalance){
+       super(typeDeclaration, parent, bracketBalance);
+       this.typeDeclaration = typeDeclaration;
+       this.foundOpeningBrace = !bodyStartsAtHeaderEnd();
+       if(this.foundOpeningBrace) {
+               this.bracketBalance++;
+       }
+}
+public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
+
+       /* do not consider a method starting passed the type end (if set)
+               it must be belonging to an enclosing type */
+       if (typeDeclaration.declarationSourceEnd != 0 
+               && methodDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
+               return this.parent.add(methodDeclaration, bracketBalanceValue);
+       }
+
+       if (methods == null) {
+               methods = new RecoveredMethod[5];
+               methodCount = 0;
+       } else {
+               if (methodCount == methods.length) {
+                       System.arraycopy(
+                               methods, 
+                               0, 
+                               (methods = new RecoveredMethod[2 * methodCount]), 
+                               0, 
+                               methodCount); 
+               }
+       }
+       RecoveredMethod element = new RecoveredMethod(methodDeclaration, this, bracketBalanceValue, this.recoveringParser);
+       methods[methodCount++] = element;
+
+       /* consider that if the opening brace was not found, it is there */
+       if (!foundOpeningBrace){
+               foundOpeningBrace = true;
+               this.bracketBalance++;
+       }
+       /* if method not finished, then method becomes current */
+       if (methodDeclaration.declarationSourceEnd == 0) return element;
+       return this;
+}
+public RecoveredElement add(Block nestedBlockDeclaration,int bracketBalanceValue) {
+       int modifiers = AccDefault;
+       if(this.parser().recoveredStaticInitializerStart != 0) {
+               modifiers = AccStatic;
+       }
+       return this.add(new Initializer(nestedBlockDeclaration, modifiers), bracketBalanceValue);
+}
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
+       
+       /* do not consider a field starting passed the type end (if set)
+       it must be belonging to an enclosing type */
+       if (typeDeclaration.declarationSourceEnd != 0
+               && fieldDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd) {
+               return this.parent.add(fieldDeclaration, bracketBalanceValue);
+       }
+       if (fields == null) {
+               fields = new RecoveredField[5];
+               fieldCount = 0;
+       } else {
+               if (fieldCount == fields.length) {
+                       System.arraycopy(
+                               fields, 
+                               0, 
+                               (fields = new RecoveredField[2 * fieldCount]), 
+                               0, 
+                               fieldCount); 
+               }
+       }
+       RecoveredField element = fieldDeclaration.isField() 
+                                                               ? new RecoveredField(fieldDeclaration, this, bracketBalanceValue)
+                                                               : new RecoveredInitializer(fieldDeclaration, this, bracketBalanceValue);
+       fields[fieldCount++] = element;
+
+       /* consider that if the opening brace was not found, it is there */
+       if (!foundOpeningBrace){
+               foundOpeningBrace = true;
+               this.bracketBalance++;
+       }
+       /* if field not finished, then field becomes current */
+       if (fieldDeclaration.declarationSourceEnd == 0) return element;
+       return this;
+}
+public RecoveredElement add(TypeDeclaration memberTypeDeclaration, int bracketBalanceValue) {
+
+       /* do not consider a type starting passed the type end (if set)
+               it must be belonging to an enclosing type */
+       if (typeDeclaration.declarationSourceEnd != 0 
+               && memberTypeDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
+               return this.parent.add(memberTypeDeclaration, bracketBalanceValue);
+       }
+       
+       if ((memberTypeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
+               if (this.methodCount > 0) {
+                       // add it to the last method body
+                       RecoveredMethod lastMethod = this.methods[this.methodCount-1];
+                       lastMethod.methodDeclaration.bodyEnd = 0; // reopen method
+                       lastMethod.methodDeclaration.declarationSourceEnd = 0; // reopen method
+                       lastMethod.bracketBalance++; // expect one closing brace
+                       return lastMethod.add(memberTypeDeclaration, bracketBalanceValue);
+               } else {
+                       // ignore
+                       return this;
+               }
+       }       
+               
+       if (memberTypes == null) {
+               memberTypes = new RecoveredType[5];
+               memberTypeCount = 0;
+       } else {
+               if (memberTypeCount == memberTypes.length) {
+                       System.arraycopy(
+                               memberTypes, 
+                               0, 
+                               (memberTypes = new RecoveredType[2 * memberTypeCount]), 
+                               0, 
+                               memberTypeCount); 
+               }
+       }
+       RecoveredType element = new RecoveredType(memberTypeDeclaration, this, bracketBalanceValue);
+       memberTypes[memberTypeCount++] = element;
+
+       /* consider that if the opening brace was not found, it is there */
+       if (!foundOpeningBrace){
+               foundOpeningBrace = true;
+               this.bracketBalance++;
+       }
+       /* if member type not finished, then member type becomes current */
+       if (memberTypeDeclaration.declarationSourceEnd == 0) return element;
+       return this;
+}
+/*
+ * Answer the body end of the corresponding parse node
+ */
+public int bodyEnd(){
+       if (bodyEnd == 0) return typeDeclaration.declarationSourceEnd;
+       return bodyEnd;
+}
+public boolean bodyStartsAtHeaderEnd(){
+       if (typeDeclaration.superInterfaces == null){
+               if (typeDeclaration.superclass == null){
+                       return typeDeclaration.bodyStart == typeDeclaration.sourceEnd+1;
+               } else {
+                       return typeDeclaration.bodyStart == typeDeclaration.superclass.sourceEnd+1;
+               }
+       } else {
+               return typeDeclaration.bodyStart 
+                               == typeDeclaration.superInterfaces[typeDeclaration.superInterfaces.length-1].sourceEnd+1;
+       }
+}
+/*
+ * Answer the enclosing type node, or null if none
+ */
+public RecoveredType enclosingType(){
+       RecoveredElement current = parent;
+       while (current != null){
+               if (current instanceof RecoveredType){
+                       return (RecoveredType) current;
+               }
+               current = current.parent;
+       }
+       return null;
+}
+public char[] name(){
+       return typeDeclaration.name;
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return typeDeclaration;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return this.typeDeclaration.declarationSourceEnd;
+}
+public String toString(int tab) {
+       StringBuffer result = new StringBuffer(tabString(tab));
+       result.append("Recovered type:\n"); //$NON-NLS-1$
+       if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0) {
+               result.append(tabString(tab));
+               result.append(" "); //$NON-NLS-1$
+       }
+       typeDeclaration.print(tab + 1, result);
+       if (this.memberTypes != null) {
+               for (int i = 0; i < this.memberTypeCount; i++) {
+                       result.append("\n"); //$NON-NLS-1$
+                       result.append(this.memberTypes[i].toString(tab + 1));
+               }
+       }
+       if (this.fields != null) {
+               for (int i = 0; i < this.fieldCount; i++) {
+                       result.append("\n"); //$NON-NLS-1$
+                       result.append(this.fields[i].toString(tab + 1));
+               }
+       }
+       if (this.methods != null) {
+               for (int i = 0; i < this.methodCount; i++) {
+                       result.append("\n"); //$NON-NLS-1$
+                       result.append(this.methods[i].toString(tab + 1));
+               }
+       }
+       return result.toString();
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void updateBodyStart(int bodyStart){
+       this.foundOpeningBrace = true;
+       this.typeDeclaration.bodyStart = bodyStart;
+}
+public Statement updatedStatement(){
+
+       // ignore closed anonymous type
+       if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0 && !this.preserveContent){
+               return null;
+       }
+               
+       TypeDeclaration updatedType = this.updatedTypeDeclaration();
+       if ((updatedType.bits & ASTNode.IsAnonymousTypeMASK) != 0){
+               /* in presence of an anonymous type, we want the full allocation expression */
+               return updatedType.allocation;
+       }
+       return updatedType;
+}
+public TypeDeclaration updatedTypeDeclaration(){
+
+       /* update member types */
+       if (memberTypeCount > 0){
+               int existingCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length;
+               TypeDeclaration[] memberTypeDeclarations = new TypeDeclaration[existingCount + memberTypeCount];
+               if (existingCount > 0){
+                       System.arraycopy(typeDeclaration.memberTypes, 0, memberTypeDeclarations, 0, existingCount);
+               }
+               // may need to update the declarationSourceEnd of the last type
+               if (memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd == 0){
+                       int bodyEndValue = bodyEnd();
+                       memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEndValue;
+                       memberTypes[memberTypeCount - 1].typeDeclaration.bodyEnd =  bodyEndValue;
+               }
+               for (int i = 0; i < memberTypeCount; i++){
+                       memberTypeDeclarations[existingCount + i] = memberTypes[i].updatedTypeDeclaration();
+               }
+               typeDeclaration.memberTypes = memberTypeDeclarations;
+       }
+       /* update fields */
+       if (fieldCount > 0){
+               int existingCount = typeDeclaration.fields == null ? 0 : typeDeclaration.fields.length;
+               FieldDeclaration[] fieldDeclarations = new FieldDeclaration[existingCount + fieldCount];
+               if (existingCount > 0){
+                       System.arraycopy(typeDeclaration.fields, 0, fieldDeclarations, 0, existingCount);
+               }
+               // may need to update the declarationSourceEnd of the last field
+               if (fields[fieldCount - 1].fieldDeclaration.declarationSourceEnd == 0){
+                       int temp = bodyEnd();
+                       fields[fieldCount - 1].fieldDeclaration.declarationSourceEnd = temp;
+                       fields[fieldCount - 1].fieldDeclaration.declarationEnd = temp;
+               }
+               for (int i = 0; i < fieldCount; i++){
+                       fieldDeclarations[existingCount + i] = fields[i].updatedFieldDeclaration();
+               }
+               typeDeclaration.fields = fieldDeclarations;
+       }
+       /* update methods */
+       int existingCount = typeDeclaration.methods == null ? 0 : typeDeclaration.methods.length;
+       boolean hasConstructor = false, hasRecoveredConstructor = 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;
+                       methodDeclarations[i] = m;
+               }
+               // may need to update the declarationSourceEnd of the last method
+               if (methods[methodCount - 1].methodDeclaration.declarationSourceEnd == 0){
+                       int bodyEndValue = bodyEnd();
+                       methods[methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEndValue;
+                       methods[methodCount - 1].methodDeclaration.bodyEnd = bodyEndValue;
+               }
+               for (int i = 0; i < methodCount; i++){
+                       AbstractMethodDeclaration updatedMethod = methods[i].updatedMethodDeclaration();                        
+                       if (updatedMethod.isConstructor()) hasRecoveredConstructor = true;
+                       methodDeclarations[existingCount + i] = updatedMethod;                  
+               }
+               typeDeclaration.methods = methodDeclarations;
+               hasConstructor = typeDeclaration.checkConstructors(this.parser());
+       } else {
+               for (int i = 0; i < existingCount; i++){
+                       if (typeDeclaration.methods[i].isConstructor()) hasConstructor = true;
+               }               
+       }
+       /* add clinit ? */
+       if (typeDeclaration.needClassInitMethod()){
+               boolean alreadyHasClinit = false;
+               for (int i = 0; i < existingCount; i++){
+                       if (typeDeclaration.methods[i].isClinit()){
+                               alreadyHasClinit = true;
+                               break;
+                       }
+               }
+               if (!alreadyHasClinit) typeDeclaration.addClinit();
+       }
+       /* add default constructor ? */
+       if (defaultConstructorIndex >= 0 && hasRecoveredConstructor){
+               /* should discard previous default construtor */
+               AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[typeDeclaration.methods.length - 1];
+               if (defaultConstructorIndex != 0){
+                       System.arraycopy(typeDeclaration.methods, 0, methodDeclarations, 0, defaultConstructorIndex);
+               }
+               if (defaultConstructorIndex != typeDeclaration.methods.length-1){
+                       System.arraycopy(
+                               typeDeclaration.methods, 
+                               defaultConstructorIndex+1, 
+                               methodDeclarations, 
+                               defaultConstructorIndex, 
+                               typeDeclaration.methods.length - defaultConstructorIndex - 1);
+               }
+               typeDeclaration.methods = methodDeclarations;
+       } else {
+               if (!hasConstructor && !typeDeclaration.isInterface()) {// if was already reduced, then constructor
+                       boolean insideFieldInitializer = false;
+                       RecoveredElement parentElement = this.parent; 
+                       while (parentElement != null){
+                               if (parentElement instanceof RecoveredField){
+                                               insideFieldInitializer = true;
+                                               break; 
+                               }
+                               parentElement = parentElement.parent;
+                       }
+                       typeDeclaration.createsInternalConstructor(!parser().diet || insideFieldInitializer, true);
+               } 
+       }
+       if (parent instanceof RecoveredType){
+               typeDeclaration.bits |= ASTNode.IsMemberTypeMASK;
+       } else if (parent instanceof RecoveredMethod){
+               typeDeclaration.bits |= ASTNode.IsLocalTypeMASK;
+       }
+       return typeDeclaration;
+}
+/*
+ * Update the corresponding parse node from parser state which
+ * is about to disappear because of restarting recovery
+ */
+public void updateFromParserState(){
+
+       if(this.bodyStartsAtHeaderEnd()){
+               Parser parser = this.parser();
+               /* might want to recover implemented interfaces */
+               // protection for bugs 15142
+               if (parser.listLength > 0 && parser.astLengthPtr > 0){ // awaiting interface type references
+                       int length = parser.astLengthStack[parser.astLengthPtr];
+                       int astPtr = parser.astPtr - length;
+                       boolean canConsume = astPtr >= 0;
+                       if(canConsume) {
+                               if((!(parser.astStack[astPtr] instanceof TypeDeclaration))) {
+                                       canConsume = false;
+                               }
+                               for (int i = 1, max = length + 1; i < max; i++) {
+                                       if(!(parser.astStack[astPtr + i ] instanceof TypeReference)) {
+                                               canConsume = false;
+                                       }
+                               }
+                       }
+                       if(canConsume) {
+                               parser.consumeClassHeaderImplements(); 
+                               // will reset typeListLength to zero
+                               // thus this check will only be performed on first errorCheck after class X implements Y,Z,
+                       }
+               }
+       }
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited
+ */
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+       if ((--bracketBalance <= 0) && (parent != null)){
+               this.updateSourceEndIfNecessary(braceStart, braceEnd);
+               this.bodyEnd = braceStart - 1;
+               return parent;
+       }
+       return this;
+}
+/*
+ * An opening brace got consumed, might be the expected opening one of the current element,
+ * in which case the bodyStart is updated.
+ */
+public RecoveredElement updateOnOpeningBrace(int braceStart, int braceEnd){
+       /* in case the opening brace is not close enough to the signature, ignore it */
+       if (bracketBalance == 0){
+               /*
+                       if (parser.scanner.searchLineNumber(typeDeclaration.sourceEnd) 
+                               != parser.scanner.searchLineNumber(braceEnd)){
+                */
+               Parser parser = this.parser();
+               switch(parser.lastIgnoredToken){
+                       case -1 :
+                       case TokenNameextends :
+                       case TokenNameimplements :
+                               if (parser.recoveredStaticInitializerStart == 0) break;
+                       default:
+                               this.foundOpeningBrace = true;                          
+                               bracketBalance = 1; // pretend the brace was already there
+               }
+       }       
+       // might be an initializer
+       if (this.bracketBalance == 1){
+               Block block = new Block(0);
+               Parser parser = this.parser();
+               block.sourceStart = parser.scanner.startPosition;
+               Initializer init;
+               if (parser.recoveredStaticInitializerStart == 0){
+                       init = new Initializer(block, AccDefault);
+               } else {
+                       init = new Initializer(block, AccStatic);
+                       init.declarationSourceStart = parser.recoveredStaticInitializerStart;
+               }
+               init.bodyStart = parser.scanner.currentPosition;
+               return this.add(init, 1);
+       }
+       return super.updateOnOpeningBrace(braceStart, braceEnd);
+}
+public void updateParseTree(){
+       this.updatedTypeDeclaration();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int start, int end){
+       if (this.typeDeclaration.declarationSourceEnd == 0){
+               this.bodyEnd = 0;
+               this.typeDeclaration.declarationSourceEnd = end;
+               this.typeDeclaration.bodyEnd = end;
+       }
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java b/src/java/org/eclipse/jdt/internal/compiler/parser/RecoveredUnit.java
new file mode 100644 (file)
index 0000000..61b1f53
--- /dev/null
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+/**
+ * Internal field structure for parsing recovery 
+ */
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ImportReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+
+public class RecoveredUnit extends RecoveredElement {
+
+       public CompilationUnitDeclaration unitDeclaration;
+       
+       public RecoveredImport[] imports;
+       public int importCount;
+       public RecoveredType[] types;
+       public int typeCount;
+public RecoveredUnit(CompilationUnitDeclaration unitDeclaration, int bracketBalance, Parser parser){
+       super(null, bracketBalance, parser);
+       this.unitDeclaration = unitDeclaration;
+}
+/*
+ *     Record a method declaration: should be attached to last type
+ */
+public RecoveredElement add(AbstractMethodDeclaration methodDeclaration, int bracketBalanceValue) {
+
+       /* attach it to last type - if any */
+       if (this.typeCount > 0){
+               RecoveredType type = this.types[this.typeCount -1];
+               type.bodyEnd = 0; // reset position
+               type.typeDeclaration.declarationSourceEnd = 0; // reset position
+               type.typeDeclaration.bodyEnd = 0;
+               return type.add(methodDeclaration, bracketBalanceValue);
+       }
+       return this; // ignore
+}
+/*
+ *     Record a field declaration: should be attached to last type
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
+
+       /* attach it to last type - if any */
+       if (this.typeCount > 0){
+               RecoveredType type = this.types[this.typeCount -1];
+               type.bodyEnd = 0; // reset position
+               type.typeDeclaration.declarationSourceEnd = 0; // reset position
+               type.typeDeclaration.bodyEnd = 0;
+               return type.add(fieldDeclaration, bracketBalanceValue);
+       }
+       return this; // ignore
+}
+public RecoveredElement add(ImportReference importReference, int bracketBalanceValue) {
+       if (this.imports == null) {
+               this.imports = new RecoveredImport[5];
+               this.importCount = 0;
+       } else {
+               if (this.importCount == this.imports.length) {
+                       System.arraycopy(
+                               this.imports, 
+                               0, 
+                               (this.imports = new RecoveredImport[2 * this.importCount]), 
+                               0, 
+                               this.importCount); 
+               }
+       }
+       RecoveredImport element = new RecoveredImport(importReference, this, bracketBalanceValue);
+       this.imports[this.importCount++] = element;
+
+       /* if import not finished, then import becomes current */
+       if (importReference.declarationSourceEnd == 0) return element;
+       return this;            
+}
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {
+       
+       if ((typeDeclaration.bits & ASTNode.IsAnonymousTypeMASK) != 0){
+               if (this.typeCount > 0) {
+                       // add it to the last type
+                       RecoveredType lastType = this.types[this.typeCount-1];
+                       lastType.bodyEnd = 0; // reopen type
+                       lastType.typeDeclaration.bodyEnd = 0; // reopen type
+                       lastType.typeDeclaration.declarationSourceEnd = 0; // reopen type
+                       lastType.bracketBalance++; // expect one closing brace
+                       return lastType.add(typeDeclaration, bracketBalanceValue);
+               }
+       }
+       if (this.types == null) {
+               this.types = new RecoveredType[5];
+               this.typeCount = 0;
+       } else {
+               if (this.typeCount == this.types.length) {
+                       System.arraycopy(
+                               this.types, 
+                               0, 
+                               (this.types = new RecoveredType[2 * this.typeCount]), 
+                               0, 
+                               this.typeCount); 
+               }
+       }
+       RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
+       this.types[this.typeCount++] = element;
+
+       /* if type not finished, then type becomes current */
+       if (typeDeclaration.declarationSourceEnd == 0) return element;
+       return this;    
+}
+/* 
+ * Answer the associated parsed structure
+ */
+public ASTNode parseTree(){
+       return this.unitDeclaration;
+}
+/*
+ * Answer the very source end of the corresponding parse node
+ */
+public int sourceEnd(){
+       return this.unitDeclaration.sourceEnd;
+}
+public String toString(int tab) {
+       StringBuffer result = new StringBuffer(tabString(tab));
+       result.append("Recovered unit: [\n"); //$NON-NLS-1$
+       this.unitDeclaration.print(tab + 1, result);
+       result.append(tabString(tab + 1));
+       result.append("]"); //$NON-NLS-1$
+       if (this.imports != null) {
+               for (int i = 0; i < this.importCount; i++) {
+                       result.append("\n"); //$NON-NLS-1$
+                       result.append(this.imports[i].toString(tab + 1));
+               }
+       }
+       if (this.types != null) {
+               for (int i = 0; i < this.typeCount; i++) {
+                       result.append("\n"); //$NON-NLS-1$
+                       result.append(this.types[i].toString(tab + 1));
+               }
+       }
+       return result.toString();
+}
+public CompilationUnitDeclaration updatedCompilationUnitDeclaration(){
+
+       /* update imports */
+       if (this.importCount > 0){
+               ImportReference[] importRefences = new ImportReference[this.importCount];
+               for (int i = 0; i < this.importCount; i++){
+                       importRefences[i] = this.imports[i].updatedImportReference();
+               }
+               this.unitDeclaration.imports = importRefences;
+       }
+       /* update types */
+       if (this.typeCount > 0){
+               int existingCount = this.unitDeclaration.types == null ? 0 : this.unitDeclaration.types.length;
+               TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + this.typeCount];
+               if (existingCount > 0){
+                       System.arraycopy(this.unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
+               }
+               // may need to update the declarationSourceEnd of the last type
+               if (this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
+                       this.types[this.typeCount - 1].typeDeclaration.declarationSourceEnd = this.unitDeclaration.sourceEnd;
+                       this.types[this.typeCount - 1].typeDeclaration.bodyEnd = this.unitDeclaration.sourceEnd;
+               }
+               int actualCount = existingCount;
+               for (int i = 0; i < this.typeCount; i++){
+                       TypeDeclaration typeDecl = this.types[i].updatedTypeDeclaration();
+                       // filter out local types (12454)
+                       if ((typeDecl.bits & ASTNode.IsLocalTypeMASK) == 0){
+                               typeDeclarations[actualCount++] = typeDecl;
+                       }
+               }
+               if (actualCount != this.typeCount){
+                       System.arraycopy(
+                               typeDeclarations, 
+                               0, 
+                               typeDeclarations = new TypeDeclaration[existingCount+actualCount], 
+                               0, 
+                               existingCount+actualCount);
+               }
+               this.unitDeclaration.types = typeDeclarations;
+       }
+       return this.unitDeclaration;
+}
+public void updateParseTree(){
+       this.updatedCompilationUnitDeclaration();
+}
+/*
+ * Update the sourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int bodyStart, int bodyEnd){
+       if (this.unitDeclaration.sourceEnd == 0)
+               this.unitDeclaration.sourceEnd = bodyEnd;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/src/java/org/eclipse/jdt/internal/compiler/parser/Scanner.java
new file mode 100644 (file)
index 0000000..70e8242
--- /dev/null
@@ -0,0 +1,3432 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser;
+
+import java.util.Iterator;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+
+/**
+ * IMPORTANT NOTE: Internal Scanner implementation. It is mirrored in 
+ * org.eclipse.jdt.core.compiler public package where it is API. 
+ * The mirror implementation is using the backward compatible ITerminalSymbols constant 
+ * definitions (stable with 2.0), whereas the internal implementation uses TerminalTokens 
+ * which constant values reflect the latest parser generation state.
+ */
+public class Scanner implements TerminalTokens {
+
+       /* APIs ares
+        - getNextToken() which return the current type of the token
+          (this value is not memorized by the scanner)
+        - getCurrentTokenSource() which provides with the token "REAL" source
+          (aka all unicode have been transformed into a correct char)
+        - sourceStart gives the position into the stream
+        - currentPosition-1 gives the sourceEnd position into the stream 
+       */
+
+       // 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; 
+       
+       public boolean recordLineSeparator = false;
+       public char currentCharacter;
+       public int startPosition;
+       public int currentPosition;
+       public int initialPosition, eofPosition;
+       // after this position eof are generated instead of real token from the source
+
+       public boolean tokenizeComments = false;
+       public boolean tokenizeWhiteSpace = false;
+
+       //source should be viewed as a window (aka a part)
+       //of a entire very large stream
+       public char source[];
+
+       //unicode support
+       public char[] withoutUnicodeBuffer;
+       public int withoutUnicodePtr; //when == 0 ==> no unicode in the current token
+       public boolean unicodeAsBackSlash = false;
+
+       public boolean scanningFloatLiteral = false;
+
+       //support for /** comments
+       public int[] commentStops = new int[10];
+       public int[] commentStarts = new int[10];
+       public int commentPtr = -1; // no comment test with commentPtr value -1
+       protected int lastCommentLinePosition = -1;
+       
+       // task tag support
+       public char[][] foundTaskTags = null;
+       public char[][] foundTaskMessages;
+       public char[][] foundTaskPriorities = null;
+       public int[][] foundTaskPositions;
+       public int foundTaskCount = 0;
+       public char[][] taskTags = null;
+       public char[][] taskPriorities = null;
+       public boolean isTaskCaseSensitive = true;
+       
+       //diet parsing support - jump over some method body when requested
+       public boolean diet = false;
+
+       //support for the  poor-line-debuggers ....
+       //remember the position of the cr/lf
+       public int[] lineEnds = new int[250];
+       public int linePtr = -1;
+       public boolean wasAcr = false;
+
+       public static final String END_OF_SOURCE = "End_Of_Source"; //$NON-NLS-1$
+
+       public static final String INVALID_HEXA = "Invalid_Hexa_Literal"; //$NON-NLS-1$
+       public static final String INVALID_OCTAL = "Invalid_Octal_Literal"; //$NON-NLS-1$
+       public static final String INVALID_CHARACTER_CONSTANT = "Invalid_Character_Constant";  //$NON-NLS-1$
+       public static final String INVALID_ESCAPE = "Invalid_Escape"; //$NON-NLS-1$
+       public static final String INVALID_INPUT = "Invalid_Input"; //$NON-NLS-1$
+       public static final String INVALID_UNICODE_ESCAPE = "Invalid_Unicode_Escape"; //$NON-NLS-1$
+       public static final String INVALID_FLOAT = "Invalid_Float_Literal"; //$NON-NLS-1$
+
+       public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$
+       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$
+
+       //----------------optimized identifier managment------------------
+       static final char[] charArray_a = new char[] {'a'}, 
+               charArray_b = new char[] {'b'}, 
+               charArray_c = new char[] {'c'}, 
+               charArray_d = new char[] {'d'}, 
+               charArray_e = new char[] {'e'}, 
+               charArray_f = new char[] {'f'}, 
+               charArray_g = new char[] {'g'}, 
+               charArray_h = new char[] {'h'}, 
+               charArray_i = new char[] {'i'}, 
+               charArray_j = new char[] {'j'}, 
+               charArray_k = new char[] {'k'}, 
+               charArray_l = new char[] {'l'}, 
+               charArray_m = new char[] {'m'}, 
+               charArray_n = new char[] {'n'}, 
+               charArray_o = new char[] {'o'}, 
+               charArray_p = new char[] {'p'}, 
+               charArray_q = new char[] {'q'}, 
+               charArray_r = new char[] {'r'}, 
+               charArray_s = new char[] {'s'}, 
+               charArray_t = new char[] {'t'}, 
+               charArray_u = new char[] {'u'}, 
+               charArray_v = new char[] {'v'}, 
+               charArray_w = new char[] {'w'}, 
+               charArray_x = new char[] {'x'}, 
+               charArray_y = new char[] {'y'}, 
+               charArray_z = new char[] {'z'}; 
+
+       static final char[] initCharArray = 
+               new char[] {'\u0000', '\u0000', '\u0000', '\u0000', '\u0000', '\u0000'}; 
+       static final int TableSize = 30, InternalTableSize = 6; //30*6 = 180 entries
+       public static final int OptimizedLength = 6;
+       public /*static*/ final char[][][][] charArray_length = 
+               new char[OptimizedLength][TableSize][InternalTableSize][]; 
+       // support for detecting non-externalized string literals
+       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$
+       public static final int TAG_POSTFIX_LENGTH= TAG_POSTFIX.length();
+       public StringLiteral[] nonNLSStrings = null;
+       public boolean checkNonExternalizedStringLiterals = false;
+       public boolean wasNonExternalizedStringLiteral = false;
+       
+       /*static*/ {
+               for (int i = 0; i < 6; i++) {
+                       for (int j = 0; j < TableSize; j++) {
+                               for (int k = 0; k < InternalTableSize; k++) {
+                                       this.charArray_length[i][j][k] = initCharArray;
+                               }
+                       }
+               }
+       }
+       static int newEntry2 = 0, 
+               newEntry3 = 0, 
+               newEntry4 = 0, 
+               newEntry5 = 0, 
+               newEntry6 = 0;
+
+       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 Scanner() {
+       this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
+}
+
+public Scanner(
+       boolean tokenizeComments, 
+       boolean tokenizeWhiteSpace, 
+       boolean checkNonExternalizedStringLiterals, 
+       long sourceLevel,
+       char[][] taskTags,
+       char[][] taskPriorities,
+       boolean isTaskCaseSensitive) {
+
+       this.eofPosition = Integer.MAX_VALUE;
+       this.tokenizeComments = tokenizeComments;
+       this.tokenizeWhiteSpace = tokenizeWhiteSpace;
+       this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
+       this.assertMode = sourceLevel >= ClassFileConstants.JDK1_4;
+       this.taskTags = taskTags;
+       this.taskPriorities = taskPriorities;
+       this.isTaskCaseSensitive = isTaskCaseSensitive;
+}
+
+public  final boolean atEnd() {
+       // This code is not relevant if source is 
+       // Only a part of the real stream input
+
+       return this.source.length == this.currentPosition;
+}
+
+private void checkNonExternalizedString() {
+       if (this.currentLine == null) 
+               return;
+       parseTags(this.currentLine);
+}
+
+// chech presence of task: tags
+// TODO (frederic) see if we need to take unicode characters into account...
+public void checkTaskTag(int commentStart, int commentEnd) {
+       char[] src = this.source;
+       
+       // only look for newer task: tags
+       if (this.foundTaskCount > 0
+               && this.foundTaskPositions[this.foundTaskCount - 1][0] >= commentStart) {
+               return;
+       }
+       int foundTaskIndex = this.foundTaskCount;
+       char previous = src[commentStart+1]; // should be '*' or '/'
+       nextChar : for (
+               int i = commentStart + 2; i < commentEnd && i < this.eofPosition; i++) {
+               char[] tag = null;
+               char[] priority = null;
+               // check for tag occurrence only if not ambiguous with javadoc tag
+               if (previous != '@') {
+                       nextTag : for (int itag = 0; itag < this.taskTags.length; itag++) {
+                               tag = this.taskTags[itag];
+                               int tagLength = tag.length;
+                               if (tagLength == 0) continue nextTag;
+       
+                               // ensure tag is not leaded with letter if tag starts with a letter
+                               if (Character.isJavaIdentifierStart(tag[0])) {
+                                       if (Character.isJavaIdentifierPart(previous)) {
+                                               continue nextTag;
+                                       }
+                               }
+       
+                               for (int t = 0; t < tagLength; t++) {
+                                       char sc, tc;
+                                       int x = i+t;
+                                       if (x >= this.eofPosition || x >= commentEnd) continue nextTag;
+                                       if ((sc = src[i + t]) != (tc = tag[t])) {                                                                                                                                                                       // case sensitive check
+                                               if (this.isTaskCaseSensitive || (Character.toLowerCase(sc) != Character.toLowerCase(tc))) {     // case insensitive check
+                                                       continue nextTag;
+                                               }
+                                       }
+                               }
+                               // ensure tag is not followed with letter if tag finishes with a letter
+                               if (i+tagLength < commentEnd && Character.isJavaIdentifierPart(src[i+tagLength-1])) {
+                                       if (Character.isJavaIdentifierPart(src[i + tagLength]))
+                                               continue nextTag;
+                               }
+                               if (this.foundTaskTags == null) {
+                                       this.foundTaskTags = new char[5][];
+                                       this.foundTaskMessages = new char[5][];
+                                       this.foundTaskPriorities = new char[5][];
+                                       this.foundTaskPositions = new int[5][];
+                               } else if (this.foundTaskCount == this.foundTaskTags.length) {
+                                       System.arraycopy(this.foundTaskTags, 0, this.foundTaskTags = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+                                       System.arraycopy(this.foundTaskMessages, 0, this.foundTaskMessages = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+                                       System.arraycopy(this.foundTaskPriorities, 0, this.foundTaskPriorities = new char[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+                                       System.arraycopy(this.foundTaskPositions, 0, this.foundTaskPositions = new int[this.foundTaskCount * 2][], 0, this.foundTaskCount);
+                               }
+                               
+                               priority = this.taskPriorities != null && itag < this.taskPriorities.length
+                                                       ? this.taskPriorities[itag]
+                                                       : null;
+                               
+                               this.foundTaskTags[this.foundTaskCount] = tag;
+                               this.foundTaskPriorities[this.foundTaskCount] = priority;
+                               this.foundTaskPositions[this.foundTaskCount] = new int[] { i, i + tagLength - 1 };
+                               this.foundTaskMessages[this.foundTaskCount] = CharOperation.NO_CHAR;
+                               this.foundTaskCount++;
+                               i += tagLength - 1; // will be incremented when looping
+                               break nextTag;
+                       }
+               }
+               previous = src[i];
+       }
+       for (int i = foundTaskIndex; i < this.foundTaskCount; i++) {
+               // retrieve message start and end positions
+               int msgStart = this.foundTaskPositions[i][0] + this.foundTaskTags[i].length;
+               int max_value = i + 1 < this.foundTaskCount
+                               ? this.foundTaskPositions[i + 1][0] - 1
+                               : commentEnd - 1;
+               // at most beginning of next task
+               if (max_value < msgStart) {
+                       max_value = msgStart; // would only occur if tag is before EOF.
+               }
+               int end = -1;
+               char c;
+               for (int j = msgStart; j < max_value; j++) {
+                       if ((c = src[j]) == '\n' || c == '\r') {
+                               end = j - 1;
+                               break;
+                       }
+               }
+               if (end == -1) {
+                       for (int j = max_value; j > msgStart; j--) {
+                               if ((c = src[j]) == '*') {
+                                       end = j - 1;
+                                       break;
+                               }
+                       }
+                       if (end == -1)
+                               end = max_value;
+               }
+               if (msgStart == end)
+                       continue; // empty
+               // trim the message
+               while (CharOperation.isWhitespace(src[end]) && msgStart <= end)
+                       end--;
+               while (CharOperation.isWhitespace(src[msgStart]) && msgStart <= end)
+                       msgStart++;
+               // update the end position of the task
+               this.foundTaskPositions[i][1] = end;
+               // get the message source
+               final int messageLength = end - msgStart + 1;
+               char[] message = new char[messageLength];
+               System.arraycopy(src, msgStart, message, 0, messageLength);
+               this.foundTaskMessages[i] = message;
+       }
+}
+public char[] getCurrentIdentifierSource() {
+       //return the token REAL source (aka unicodes are precomputed)
+
+       char[] result;
+       if (this.withoutUnicodePtr != 0) {
+               //0 is used as a fast test flag so the real first char is in position 1
+               System.arraycopy(
+                       this.withoutUnicodeBuffer, 
+                       1, 
+                       result = new char[this.withoutUnicodePtr], 
+                       0, 
+                       this.withoutUnicodePtr); 
+       } else {
+               int length = this.currentPosition - this.startPosition;
+               if (length == this.source.length) return this.source;
+               switch (length) { // see OptimizedLength
+                       case 1 :
+                               return optimizedCurrentTokenSource1();
+                       case 2 :
+                               return optimizedCurrentTokenSource2();
+                       case 3 :
+                               return optimizedCurrentTokenSource3();
+                       case 4 :
+                               return optimizedCurrentTokenSource4();
+                       case 5 :
+                               return optimizedCurrentTokenSource5();
+                       case 6 :
+                               return optimizedCurrentTokenSource6();
+               }
+               //no optimization
+               System.arraycopy(this.source, this.startPosition, result = new char[length], 0, length);
+       }
+       return result;
+}
+public int getCurrentTokenEndPosition(){
+       return this.currentPosition - 1;
+}
+public final char[] getCurrentTokenSource() {
+       // Return the token REAL source (aka unicodes are precomputed)
+
+       char[] result;
+       if (this.withoutUnicodePtr != 0)
+               // 0 is used as a fast test flag so the real first char is in position 1
+               System.arraycopy(
+                       this.withoutUnicodeBuffer, 
+                       1, 
+                       result = new char[this.withoutUnicodePtr], 
+                       0, 
+                       this.withoutUnicodePtr); 
+       else {
+               int length;
+               System.arraycopy(
+                       this.source, 
+                       this.startPosition, 
+                       result = new char[length = this.currentPosition - this.startPosition], 
+                       0, 
+                       length); 
+       }
+       return result;
+}
+public final char[] getCurrentTokenSourceString() {
+       //return the token REAL source (aka unicodes are precomputed).
+       //REMOVE the two " that are at the beginning and the end.
+
+       char[] result;
+       if (this.withoutUnicodePtr != 0)
+               //0 is used as a fast test flag so the real first char is in position 1
+               System.arraycopy(this.withoutUnicodeBuffer, 2,
+               //2 is 1 (real start) + 1 (to jump over the ")
+               result = new char[this.withoutUnicodePtr - 2], 0, this.withoutUnicodePtr - 2);
+       else {
+               int length;
+               System.arraycopy(
+                       this.source, 
+                       this.startPosition + 1, 
+                       result = new char[length = this.currentPosition - this.startPosition - 2], 
+                       0, 
+                       length); 
+       }
+       return result;
+}
+
+public final char[] getRawTokenSource() {
+       int length = this.currentPosition - this.startPosition;
+       char[] tokenSource = new char[length];
+       System.arraycopy(this.source, this.startPosition, tokenSource, 0, length);
+       return tokenSource;     
+}
+       
+public final char[] getRawTokenSourceEnd() {
+       int length = this.eofPosition - this.currentPosition - 1;
+       char[] sourceEnd = new char[length];
+       System.arraycopy(this.source, this.currentPosition, sourceEnd, 0, length);
+       return sourceEnd;       
+}
+       
+public int getCurrentTokenStartPosition(){
+       return this.startPosition;
+}
+/*
+ * Search the source position corresponding to the end of a given line number
+ *
+ * Line numbers are 1-based, and relative to the scanner initialPosition. 
+ * Character positions are 0-based.
+ *
+ * In case the given line number is inconsistent, answers -1.
+ */
+public final int getLineEnd(int lineNumber) {
+
+       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.eofPosition;
+       return this.lineEnds[lineNumber-1]; // next line start one character behind the lineEnd of the previous line
+}
+
+public final int[] getLineEnds() {
+       //return a bounded copy of this.lineEnds 
+
+       int[] copy;
+       System.arraycopy(this.lineEnds, 0, copy = new int[this.linePtr + 1], 0, this.linePtr + 1);
+       return copy;
+}
+
+/**
+ * Search the source position corresponding to the beginning of a given line number
+ *
+ * Line numbers are 1-based, and relative to the scanner initialPosition. 
+ * Character positions are 0-based.
+ *
+ * e.g.        getLineStart(1) --> 0   indicates that the first line starts at character 0.
+ *
+ * In case the given line number is inconsistent, answers -1.
+ * 
+ * @param lineNumber int
+ * @return int
+ */
+public final int getLineStart(int lineNumber) {
+
+       if (this.lineEnds == null) 
+               return -1;
+       if (lineNumber > this.lineEnds.length + 1) 
+               return -1;
+       if (lineNumber <= 0) 
+               return -1;
+       
+       if (lineNumber == 1) 
+               return this.initialPosition;
+       return this.lineEnds[lineNumber-2]+1; // next line start one character behind the lineEnd of the previous line
+}
+public final int getNextChar() {
+       try {
+               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                       && (this.source[this.currentPosition] == 'u')) {
+                       //-------------unicode traitement ------------
+                       int c1, c2, c3, c4;
+                       int unicodeSize = 6;
+                       this.currentPosition++;
+                       while (this.source[this.currentPosition] == 'u') {
+                               this.currentPosition++;
+                               unicodeSize++;
+                       }
+
+                       if (((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                               || c1 < 0)
+                               || ((c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c2 < 0)
+                               || ((c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c3 < 0)
+                               || ((c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c4 < 0)) {
+                               return -1;
+                       }
+
+                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+
+                       this.unicodeAsBackSlash = this.currentCharacter == '\\';
+
+                       //need the unicode buffer
+                       if (this.withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                           unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+                       }
+                       //fill the buffer with the char
+                       unicodeStoreAt(++this.withoutUnicodePtr);
+                       return this.currentCharacter;
+
+               } //-------------end unicode traitement--------------
+               else {
+                       this.unicodeAsBackSlash = false;
+                       if (this.withoutUnicodePtr != 0) {
+                           unicodeStoreAt(++this.withoutUnicodePtr);
+                       }
+                       return this.currentCharacter;
+               }
+       } catch (IndexOutOfBoundsException e) {
+               return -1;
+       }
+}
+public final boolean getNextChar(char testedChar) {
+       //BOOLEAN
+       //handle the case of unicode.
+       //when a unicode appears then we must use a buffer that holds char internal values
+       //At the end of this method currentCharacter holds the new visited char
+       //and currentPosition points right next after it
+       //Both previous lines are true if the currentCharacter is == to the testedChar
+       //On false, no side effect has occured.
+
+       //ALL getNextChar.... ARE OPTIMIZED COPIES 
+
+       if (this.currentPosition >= this.source.length) { // handle the obvious case upfront
+               this.unicodeAsBackSlash = false;
+               return false;
+       }
+
+       int temp = this.currentPosition;
+       try {
+               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                       && (this.source[this.currentPosition] == 'u')) {
+                       //-------------unicode traitement ------------
+                       int c1, c2, c3, c4;
+                       int unicodeSize = 6;
+                       this.currentPosition++;
+                       while (this.source[this.currentPosition] == 'u') {
+                               this.currentPosition++;
+                               unicodeSize++;
+                       }
+
+                       if (((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                               || c1 < 0)
+                               || ((c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c2 < 0)
+                               || ((c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c3 < 0)
+                               || ((c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c4 < 0)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       if (this.currentCharacter != testedChar) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+                       this.unicodeAsBackSlash = this.currentCharacter == '\\';
+
+                       //need the unicode buffer
+                       if (this.withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                           unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+                       }
+                       //fill the buffer with the char
+                       unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+
+               } //-------------end unicode traitement--------------
+               else {
+                       if (this.currentCharacter != testedChar) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+                       this.unicodeAsBackSlash = false;
+                       if (this.withoutUnicodePtr != 0)
+                               unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+               }
+       } catch (IndexOutOfBoundsException e) {
+               this.unicodeAsBackSlash = false;
+               this.currentPosition = temp;
+               return false;
+       }
+}
+public final int getNextChar(char testedChar1, char testedChar2) {
+       //INT 0 : testChar1 \\\\///\\\\ 1 : testedChar2 \\\\///\\\\ -1 : others
+       //test can be done with (x==0) for the first and (x>0) for the second
+       //handle the case of unicode.
+       //when a unicode appears then we must use a buffer that holds char internal values
+       //At the end of this method currentCharacter holds the new visited char
+       //and currentPosition points right next after it
+       //Both previous lines are true if the currentCharacter is == to the testedChar1/2
+       //On false, no side effect has occured.
+
+       //ALL getNextChar.... ARE OPTIMIZED COPIES 
+       if (this.currentPosition >= this.source.length) // handle the obvious case upfront
+               return -1;
+
+       int temp = this.currentPosition;
+       try {
+               int result;
+               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                       && (this.source[this.currentPosition] == 'u')) {
+                       //-------------unicode traitement ------------
+                       int c1, c2, c3, c4;
+                       int unicodeSize = 6;
+                       this.currentPosition++;
+                       while (this.source[this.currentPosition] == 'u') {
+                               this.currentPosition++;
+                               unicodeSize++;
+                       }
+
+                       if (((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                               || c1 < 0)
+                               || ((c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c2 < 0)
+                               || ((c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c3 < 0)
+                               || ((c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c4 < 0)) {
+                               this.currentPosition = temp;
+                               return 2;
+                       }
+
+                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       if (this.currentCharacter == testedChar1)
+                               result = 0;
+                       else
+                               if (this.currentCharacter == testedChar2)
+                                       result = 1;
+                               else {
+                                       this.currentPosition = temp;
+                                       return -1;
+                               }
+
+                       //need the unicode buffer
+                       if (this.withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                               unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+                       }
+                       //fill the buffer with the char
+                       unicodeStoreAt(++this.withoutUnicodePtr);
+                       return result;
+               } //-------------end unicode traitement--------------
+               else {
+                       if (this.currentCharacter == testedChar1)
+                               result = 0;
+                       else
+                               if (this.currentCharacter == testedChar2)
+                                       result = 1;
+                               else {
+                                       this.currentPosition = temp;
+                                       return -1;
+                               }
+
+                       if (this.withoutUnicodePtr != 0)
+                               unicodeStoreAt(++this.withoutUnicodePtr);
+                       return result;
+               }
+       } catch (IndexOutOfBoundsException e) {
+               this.currentPosition = temp;
+               return -1;
+       }
+}
+public final boolean getNextCharAsDigit() throws InvalidInputException {
+       //BOOLEAN
+       //handle the case of unicode.
+       //when a unicode appears then we must use a buffer that holds char internal values
+       //At the end of this method currentCharacter holds the new visited char
+       //and currentPosition points right next after it
+       //Both previous lines are true if the currentCharacter is a digit
+       //On false, no side effect has occured.
+
+       //ALL getNextChar.... ARE OPTIMIZED COPIES 
+       if (this.currentPosition >= this.source.length) // handle the obvious case upfront
+               return false;
+
+       int temp = this.currentPosition;
+       try {
+               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                       && (this.source[this.currentPosition] == 'u')) {
+                       //-------------unicode traitement ------------
+                       int c1, c2, c3, c4;
+                       int unicodeSize = 6;
+                       this.currentPosition++;
+                       while (this.source[this.currentPosition] == 'u') {
+                               this.currentPosition++;
+                               unicodeSize++;
+                       }
+
+                       if (((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                               || c1 < 0)
+                               || ((c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c2 < 0)
+                               || ((c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c3 < 0)
+                               || ((c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c4 < 0)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       if (!isDigit(this.currentCharacter)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       //need the unicode buffer
+                       if (this.withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                               unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+                       }
+                       //fill the buffer with the char
+                       unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+               } //-------------end unicode traitement--------------
+               else {
+                       if (!isDigit(this.currentCharacter)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+                       if (this.withoutUnicodePtr != 0)
+                               unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+               }
+       } catch (IndexOutOfBoundsException e) {
+               this.currentPosition = temp;
+               return false;
+       }
+}
+public final boolean getNextCharAsDigit(int radix) {
+       //BOOLEAN
+       //handle the case of unicode.
+       //when a unicode appears then we must use a buffer that holds char internal values
+       //At the end of this method currentCharacter holds the new visited char
+       //and currentPosition points right next after it
+       //Both previous lines are true if the currentCharacter is a digit base on radix
+       //On false, no side effect has occured.
+
+       //ALL getNextChar.... ARE OPTIMIZED COPIES 
+       if (this.currentPosition >= this.source.length) // handle the obvious case upfront
+               return false;
+
+       int temp = this.currentPosition;
+       try {
+               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                       && (this.source[this.currentPosition] == 'u')) {
+                       //-------------unicode traitement ------------
+                       int c1, c2, c3, c4;
+                       int unicodeSize = 6;
+                       this.currentPosition++;
+                       while (this.source[this.currentPosition] == 'u') {
+                               this.currentPosition++;
+                               unicodeSize++;
+                       }
+
+                       if (((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                               || c1 < 0)
+                               || ((c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c2 < 0)
+                               || ((c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c3 < 0)
+                               || ((c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c4 < 0)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       if (Character.digit(this.currentCharacter, radix) == -1) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       //need the unicode buffer
+                       if (this.withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                               unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+                       }
+                       //fill the buffer with the char
+                       unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+               } //-------------end unicode traitement--------------
+               else {
+                       if (Character.digit(this.currentCharacter, radix) == -1) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+                       if (this.withoutUnicodePtr != 0)
+                               unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+               }
+       } catch (IndexOutOfBoundsException e) {
+               this.currentPosition = temp;
+               return false;
+       }
+}
+public boolean getNextCharAsJavaIdentifierPart() {
+       //BOOLEAN
+       //handle the case of unicode.
+       //when a unicode appears then we must use a buffer that holds char internal values
+       //At the end of this method currentCharacter holds the new visited char
+       //and currentPosition points right next after it
+       //Both previous lines are true if the currentCharacter is a JavaIdentifierPart
+       //On false, no side effect has occured.
+
+       //ALL getNextChar.... ARE OPTIMIZED COPIES 
+       if (this.currentPosition >= this.source.length) // handle the obvious case upfront
+               return false;
+
+       int temp = this.currentPosition;
+       try {
+               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                       && (this.source[this.currentPosition] == 'u')) {
+                       //-------------unicode traitement ------------
+                       int c1, c2, c3, c4;
+                       int unicodeSize = 6;
+                       this.currentPosition++;
+                       while (this.source[this.currentPosition] == 'u') {
+                               this.currentPosition++;
+                               unicodeSize++;
+                       }
+
+                       if (((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                               || c1 < 0)
+                               || ((c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c2 < 0)
+                               || ((c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c3 < 0)
+                               || ((c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c4 < 0)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       if (!Character.isJavaIdentifierPart(this.currentCharacter)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       //need the unicode buffer
+                       if (this.withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                               unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+                       }
+                       //fill the buffer with the char
+                   unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+               } //-------------end unicode traitement--------------
+               else {
+                       if (!Character.isJavaIdentifierPart(this.currentCharacter)) {
+                               this.currentPosition = temp;
+                               return false;
+                       }
+
+                       if (this.withoutUnicodePtr != 0)
+                           unicodeStoreAt(++this.withoutUnicodePtr);
+                       return true;
+               }
+       } catch (IndexOutOfBoundsException e) {
+               this.currentPosition = temp;
+               return false;
+       }
+}
+public int getNextToken() throws InvalidInputException {
+       this.wasAcr = false;
+       if (this.diet) {
+               jumpOverMethodBody();
+               this.diet = false;
+               return this.currentPosition > this.source.length ? TokenNameEOF : TokenNameRBRACE;
+       }
+       int whiteStart = 0;
+       try {
+               while (true) { //loop for jumping over comments
+                       this.withoutUnicodePtr = 0;
+                       //start with a new token (even comment written with unicode )
+
+                       // ---------Consume white space and handles startPosition---------
+                       whiteStart = this.currentPosition;
+                       boolean isWhiteSpace, hasWhiteSpaces = false;
+                       int offset = 0;
+                       do {
+                               this.startPosition = this.currentPosition;
+                               boolean checkIfUnicode = false;
+                               try {
+                                       checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                               && (this.source[this.currentPosition] == 'u');
+                               } catch(IndexOutOfBoundsException e) {
+                                       if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+                                               // reposition scanner in case we are interested by spaces as tokens
+                                               this.currentPosition--;
+                                               this.startPosition = whiteStart;
+                                               return TokenNameWHITESPACE;
+                                       }
+                                       if (this.currentPosition > this.eofPosition)
+                                               return TokenNameEOF;
+                               }
+                               if (checkIfUnicode) {
+                                       isWhiteSpace = jumpOverUnicodeWhiteSpace();
+                                       offset = 6;
+                               } else {
+                                       offset = 1;
+                                       if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+                                               checkNonExternalizedString();
+                                               if (this.recordLineSeparator) {
+                                                       pushLineSeparator();
+                                               } else {
+                                                       this.currentLine = null;
+                                               }
+                                       }
+                                       isWhiteSpace = 
+                                               (this.currentCharacter == ' ') || CharOperation.isWhitespace(this.currentCharacter); 
+                               }
+                               if (isWhiteSpace) {
+                                       hasWhiteSpaces = true;
+                               }
+                       } while (isWhiteSpace);
+                       if (this.tokenizeWhiteSpace && hasWhiteSpaces) {
+                               // reposition scanner in case we are interested by spaces as tokens
+                               this.currentPosition-=offset;
+                               this.startPosition = whiteStart;
+                               return TokenNameWHITESPACE;
+                       }
+                       //little trick to get out in the middle of a source compuation
+                       if (this.currentPosition > this.eofPosition)
+                               return TokenNameEOF;
+
+                       // ---------Identify the next token-------------
+
+                       switch (this.currentCharacter) {
+                               case '(' :
+                                       return TokenNameLPAREN;
+                               case ')' :
+                                       return TokenNameRPAREN;
+                               case '{' :
+                                       return TokenNameLBRACE;
+                               case '}' :
+                                       return TokenNameRBRACE;
+                               case '[' :
+                                       return TokenNameLBRACKET;
+                               case ']' :
+                                       return TokenNameRBRACKET;
+                               case ';' :
+                                       return TokenNameSEMICOLON;
+                               case ',' :
+                                       return TokenNameCOMMA;
+                               case '.' :
+                                       if (getNextCharAsDigit())
+                                               return scanNumber(true);
+                                       return TokenNameDOT;
+                               case '+' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('+', '=')) == 0)
+                                                       return TokenNamePLUS_PLUS;
+                                               if (test > 0)
+                                                       return TokenNamePLUS_EQUAL;
+                                               return TokenNamePLUS;
+                                       }
+                               case '-' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('-', '=')) == 0)
+                                                       return TokenNameMINUS_MINUS;
+                                               if (test > 0)
+                                                       return TokenNameMINUS_EQUAL;
+                                               return TokenNameMINUS;
+                                       }
+                               case '~' :
+                                       return TokenNameTWIDDLE;
+                               case '!' :
+                                       if (getNextChar('='))
+                                               return TokenNameNOT_EQUAL;
+                                       return TokenNameNOT;
+                               case '*' :
+                                       if (getNextChar('='))
+                                               return TokenNameMULTIPLY_EQUAL;
+                                       return TokenNameMULTIPLY;
+                               case '%' :
+                                       if (getNextChar('='))
+                                               return TokenNameREMAINDER_EQUAL;
+                                       return TokenNameREMAINDER;
+                               case '<' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('=', '<')) == 0)
+                                                       return TokenNameLESS_EQUAL;
+                                               if (test > 0) {
+                                                       if (getNextChar('='))
+                                                               return TokenNameLEFT_SHIFT_EQUAL;
+                                                       return TokenNameLEFT_SHIFT;
+                                               }
+                                               return TokenNameLESS;
+                                       }
+                               case '>' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('=', '>')) == 0)
+                                                       return TokenNameGREATER_EQUAL;
+                                               if (test > 0) {
+                                                       if ((test = getNextChar('=', '>')) == 0)
+                                                               return TokenNameRIGHT_SHIFT_EQUAL;
+                                                       if (test > 0) {
+                                                               if (getNextChar('='))
+                                                                       return TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
+                                                               return TokenNameUNSIGNED_RIGHT_SHIFT;
+                                                       }
+                                                       return TokenNameRIGHT_SHIFT;
+                                               }
+                                               return TokenNameGREATER;
+                                       }
+                               case '=' :
+                                       if (getNextChar('='))
+                                               return TokenNameEQUAL_EQUAL;
+                                       return TokenNameEQUAL;
+                               case '&' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('&', '=')) == 0)
+                                                       return TokenNameAND_AND;
+                                               if (test > 0)
+                                                       return TokenNameAND_EQUAL;
+                                               return TokenNameAND;
+                                       }
+                               case '|' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('|', '=')) == 0)
+                                                       return TokenNameOR_OR;
+                                               if (test > 0)
+                                                       return TokenNameOR_EQUAL;
+                                               return TokenNameOR;
+                                       }
+                               case '^' :
+                                       if (getNextChar('='))
+                                               return TokenNameXOR_EQUAL;
+                                       return TokenNameXOR;
+                               case '?' :
+                                       return TokenNameQUESTION;
+                               case ':' :
+                                       return TokenNameCOLON;
+                               case '\'' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('\n', '\r')) == 0) {
+                                                       throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                                               }
+                                               if (test > 0) {
+                                                       // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                                       for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+                                                               if (this.currentPosition + lookAhead == this.source.length)
+                                                                       break;
+                                                               if (this.source[this.currentPosition + lookAhead] == '\n')
+                                                                       break;
+                                                               if (this.source[this.currentPosition + lookAhead] == '\'') {
+                                                                       this.currentPosition += lookAhead + 1;
+                                                                       break;
+                                                               }
+                                                       }
+                                                       throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                                               }
+                                       }
+                                       if (getNextChar('\'')) {
+                                               // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                               for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
+                                                       if (this.currentPosition + lookAhead == this.source.length)
+                                                               break;
+                                                       if (this.source[this.currentPosition + lookAhead] == '\n')
+                                                               break;
+                                                       if (this.source[this.currentPosition + lookAhead] == '\'') {
+                                                               this.currentPosition += lookAhead + 1;
+                                                               break;
+                                                       }
+                                               }
+                                               throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                                       }
+                                       if (getNextChar('\\'))
+                                               scanEscapeCharacter();
+                                       else { // consume next character
+                                               this.unicodeAsBackSlash = false;
+                                               boolean checkIfUnicode = false;
+                                               try {
+                                                       checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                       && (this.source[this.currentPosition] == 'u');
+                                               } catch(IndexOutOfBoundsException e) {
+                                                       this.currentPosition--;
+                                                       throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                                               }
+                                               if (checkIfUnicode) {
+                                                       getNextUnicodeChar();
+                                               } else {
+                                                       if (this.withoutUnicodePtr != 0) {
+                                                               unicodeStoreAt(++this.withoutUnicodePtr);
+                                                       }
+                                               }
+                                       }
+                                       if (getNextChar('\''))
+                                               return TokenNameCharacterLiteral;
+                                       // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                       for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
+                                               if (this.currentPosition + lookAhead == this.source.length)
+                                                       break;
+                                               if (this.source[this.currentPosition + lookAhead] == '\n')
+                                                       break;
+                                               if (this.source[this.currentPosition + lookAhead] == '\'') {
+                                                       this.currentPosition += lookAhead + 1;
+                                                       break;
+                                               }
+                                       }
+                                       throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+                               case '"' :
+                                       try {
+                                               // consume next character
+                                               this.unicodeAsBackSlash = false;
+                                               boolean isUnicode = false;
+                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                       && (this.source[this.currentPosition] == 'u')) {
+                                                       getNextUnicodeChar();
+                                                       isUnicode = true;
+                                               } else {
+                                                       if (this.withoutUnicodePtr != 0) {
+                                                               unicodeStoreAt(++this.withoutUnicodePtr);
+                                                       }
+                                               }
+
+                                               while (this.currentCharacter != '"') {
+                                                       /**** \r and \n are not valid in string literals ****/
+                                                       if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
+                                                               // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                                               if (isUnicode) {
+                                                                       int start = this.currentPosition;
+                                                                       for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+                                                                               if (this.currentPosition >= this.eofPosition) {
+                                                                                       this.currentPosition = start;
+                                                                                       break;
+                                                                               }
+                                                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
+                                                                                       isUnicode = true;
+                                                                                       getNextUnicodeChar();
+                                                                               } else {
+                                                                                       isUnicode = false;
+                                                                               }
+                                                                               if (!isUnicode && this.currentCharacter == '\n') {
+                                                                                       this.currentPosition--; // set current position on new line character
+                                                                                       break;
+                                                                               }
+                                                                               if (this.currentCharacter == '\"') {
+                                                                                       throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+                                                                               }
+                                                                       }
+                                                               } else {
+                                                                       this.currentPosition--; // set current position on new line character
+                                                               }
+                                                               throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+                                                       }
+                                                       if (this.currentCharacter == '\\') {
+                                                               int escapeSize = this.currentPosition;
+                                                               boolean backSlashAsUnicodeInString = this.unicodeAsBackSlash;
+                                                               //scanEscapeCharacter make a side effect on this value and we need the previous value few lines down this one
+                                                               scanEscapeCharacter();
+                                                               escapeSize = this.currentPosition - escapeSize;
+                                                               if (this.withoutUnicodePtr == 0) {
+                                                                       //buffer all the entries that have been left aside....
+                                                                   unicodeInitializeBuffer(this.currentPosition - escapeSize - 1 - this.startPosition);
+                                                                   unicodeStoreAt(++this.withoutUnicodePtr);
+                                                               } else { //overwrite the / in the buffer
+                                                                   unicodeStoreAt(this.withoutUnicodePtr);
+                                                                       if (backSlashAsUnicodeInString) { //there are TWO \ in the stream where only one is correct
+                                                                               this.withoutUnicodePtr--;
+                                                                       }
+                                                               }
+                                                       }
+                                                       // 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);
+                                                               }
+                                                       }
+
+                                               }
+                                       } catch (IndexOutOfBoundsException e) {
+                                               this.currentPosition--;
+                                               throw new InvalidInputException(UNTERMINATED_STRING);
+                                       } catch (InvalidInputException e) {
+                                               if (e.getMessage().equals(INVALID_ESCAPE)) {
+                                                       // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+                                                       for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+                                                               if (this.currentPosition + lookAhead == this.source.length)
+                                                                       break;
+                                                               if (this.source[this.currentPosition + lookAhead] == '\n')
+                                                                       break;
+                                                               if (this.source[this.currentPosition + lookAhead] == '\"') {
+                                                                       this.currentPosition += lookAhead + 1;
+                                                                       break;
+                                                               }
+                                                       }
+
+                                               }
+                                               throw e; // rethrow
+                                       }
+                                       if (this.checkNonExternalizedStringLiterals){ // check for presence of  NLS tags //$NON-NLS-?$ where ? is an int.
+                                               if (this.currentLine == null) {
+                                                       this.currentLine = new NLSLine();
+                                               }
+                                               this.currentLine.add(
+                                                       new StringLiteral(
+                                                               getCurrentTokenSourceString(), 
+                                                               this.startPosition, 
+                                                               this.currentPosition - 1));
+                                       }
+                                       return TokenNameStringLiteral;
+                               case '/' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('/', '*')) == 0) { //line comment 
+                                                       this.lastCommentLinePosition = this.currentPosition;
+                                                       try { //get the next char 
+                                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                       && (this.source[this.currentPosition] == 'u')) {
+                                                                       //-------------unicode traitement ------------
+                                                                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                       this.currentPosition++;
+                                                                       while (this.source[this.currentPosition] == 'u') {
+                                                                               this.currentPosition++;
+                                                                       }
+                                                                       if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c1 < 0
+                                                                               || (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c2 < 0
+                                                                               || (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c3 < 0
+                                                                               || (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c4 < 0) {
+                                                                               throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+                                                                       } else {
+                                                                               this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                       }
+                                                               }
+
+                                                               //handle the \\u case manually into comment
+                                                               if (this.currentCharacter == '\\') {
+                                                                       if (this.source[this.currentPosition] == '\\')
+                                                                               this.currentPosition++;
+                                                               } //jump over the \\
+                                                               boolean isUnicode = false;
+                                                               while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
+                                                                       this.lastCommentLinePosition = this.currentPosition;
+                                                                       //get the next char
+                                                                       isUnicode = false;                                                                      
+                                                                       if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                               && (this.source[this.currentPosition] == 'u')) {
+                                                                               isUnicode = true;                                                                                       
+                                                                               //-------------unicode traitement ------------
+                                                                               int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                               this.currentPosition++;
+                                                                               while (this.source[this.currentPosition] == 'u') {
+                                                                                       this.currentPosition++;
+                                                                               }
+                                                                               if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c1 < 0
+                                                                                       || (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c2 < 0
+                                                                                       || (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c3 < 0
+                                                                                       || (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c4 < 0) {
+                                                                                       throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+                                                                               } else {
+                                                                                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                               }
+                                                                       }
+                                                                       //handle the \\u case manually into comment
+                                                                       if (this.currentCharacter == '\\') {
+                                                                               if (this.source[this.currentPosition] == '\\')
+                                                                                       this.currentPosition++;
+                                                                       } //jump over the \\
+                                                               }
+                                                               /*
+                                                                * We need to completely consume the line break
+                                                                */
+                                                               if (this.currentCharacter == '\r'
+                                                                  && this.source.length > this.currentPosition) {
+                                                                       if (this.source[this.currentPosition] == '\n') {
+                                                                               this.currentPosition++;
+                                                                               this.currentCharacter = '\n';
+                                                                       } else if ((this.source[this.currentPosition] == '\\')
+                                                                               && (this.source[this.currentPosition + 1] == 'u')) {
+                                                                               isUnicode = true;
+                                                                               char unicodeChar;
+                                                                               int index = this.currentPosition + 1;
+                                                                               index++;
+                                                                               while (this.source[index] == 'u') {
+                                                                                       index++;
+                                                                               }
+                                                                               //-------------unicode traitement ------------
+                                                                               int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                               if ((c1 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c1 < 0
+                                                                                       || (c2 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c2 < 0
+                                                                                       || (c3 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c3 < 0
+                                                                                       || (c4 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c4 < 0) {
+                                                                                       this.currentPosition = index;
+                                                                                       throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+                                                                               } else {
+                                                                                       unicodeChar = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                               }
+                                                                               if (unicodeChar == '\n') {
+                                                                                       this.currentPosition = index;
+                                                                                       this.currentCharacter = '\n';
+                                                                               }
+                                                                       }
+                                                               }
+                                                               recordComment(TokenNameCOMMENT_LINE);
+                                                               if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+                                                               if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+                                                                       checkNonExternalizedString();
+                                                                       if (this.recordLineSeparator) {
+                                                                               if (isUnicode) {
+                                                                                       pushUnicodeLineSeparator();
+                                                                               } else {
+                                                                                       pushLineSeparator();
+                                                                               }
+                                                                       } else {
+                                                                               this.currentLine = null;
+                                                                       }
+                                                               }
+                                                               if (this.tokenizeComments) {
+                                                                       return TokenNameCOMMENT_LINE;
+                                                               }
+                                                       } catch (IndexOutOfBoundsException e) {
+                                                               this.currentPosition--;
+                                                               recordComment(TokenNameCOMMENT_LINE);
+                                                               if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+                                                               if (this.tokenizeComments) {
+                                                                       return TokenNameCOMMENT_LINE;
+                                                               } else {
+                                                                       this.currentPosition++; 
+                                                               }
+                                                       }
+                                                       break;
+                                               }
+                                               if (test > 0) { //traditional and javadoc comment
+                                                       try { //get the next char
+                                                               boolean isJavadoc = false, star = false;
+                                                               boolean isUnicode = false;
+                                                               // consume next character
+                                                               this.unicodeAsBackSlash = false;
+                                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                       && (this.source[this.currentPosition] == 'u')) {
+                                                                       getNextUnicodeChar();
+                                                                       isUnicode = true;
+                                                               } else {
+                                                                       isUnicode = false;
+                                                                       if (this.withoutUnicodePtr != 0) {
+                                                                               unicodeStoreAt(++this.withoutUnicodePtr);
+                                                                       }
+                                                               }
+       
+                                                               if (this.currentCharacter == '*') {
+                                                                       isJavadoc = true;
+                                                                       star = true;
+                                                               }
+                                                               if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+                                                                       checkNonExternalizedString();
+                                                                       if (this.recordLineSeparator) {
+                                                                               if (!isUnicode) {
+                                                                                       pushLineSeparator();
+                                                                               }
+                                                                       } else {
+                                                                               this.currentLine = null;
+                                                                       }
+                                                               }
+                                                               isUnicode = false;
+                                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                       && (this.source[this.currentPosition] == 'u')) {
+                                                                       //-------------unicode traitement ------------
+                                                                       getNextUnicodeChar();
+                                                                       isUnicode = true;
+                                                               } else {
+                                                                       isUnicode = false;
+                                                               }
+                                                               //handle the \\u case manually into comment
+                                                               if (this.currentCharacter == '\\') {
+                                                                       if (this.source[this.currentPosition] == '\\')
+                                                                               this.currentPosition++; //jump over the \\
+                                                               }
+                                                               // empty comment is not a javadoc /**/
+                                                               if (this.currentCharacter == '/') { 
+                                                                       isJavadoc = false;
+                                                               }
+                                                               //loop until end of comment */
+                                                               while ((this.currentCharacter != '/') || (!star)) {
+                                                                       if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+                                                                               checkNonExternalizedString();
+                                                                               if (this.recordLineSeparator) {
+                                                                                       if (!isUnicode) {
+                                                                                               pushLineSeparator();
+                                                                                       }
+                                                                               } else {
+                                                                                       this.currentLine = null;
+                                                                               }
+                                                                       }
+                                                                       star = this.currentCharacter == '*';
+                                                                       //get next char
+                                                                       if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                               && (this.source[this.currentPosition] == 'u')) {
+                                                                               //-------------unicode traitement ------------
+                                                                               getNextUnicodeChar();
+                                                                               isUnicode = true;
+                                                                       } else {
+                                                                               isUnicode = false;
+                                                                       }
+                                                                       //handle the \\u case manually into comment
+                                                                       if (this.currentCharacter == '\\') {
+                                                                               if (this.source[this.currentPosition] == '\\')
+                                                                                       this.currentPosition++;
+                                                                       } //jump over the \\
+                                                               }
+                                                               int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK;
+                                                               recordComment(token);
+                                                               if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
+                                                               if (this.tokenizeComments) {
+                                                                       /*
+                                                                       if (isJavadoc)
+                                                                               return TokenNameCOMMENT_JAVADOC;
+                                                                       return TokenNameCOMMENT_BLOCK;
+                                                                       */
+                                                                       return token;
+                                                               }
+                                                       } catch (IndexOutOfBoundsException e) {
+                                                               this.currentPosition--;
+                                                               throw new InvalidInputException(UNTERMINATED_COMMENT);
+                                                       }
+                                                       break;
+                                               }
+                                               if (getNextChar('='))
+                                                       return TokenNameDIVIDE_EQUAL;
+                                               return TokenNameDIVIDE;
+                                       }
+                               case '\u001a' :
+                                       if (atEnd())
+                                               return TokenNameEOF;
+                                       //the atEnd may not be <currentPosition == source.length> if source is only some part of a real (external) stream
+                                       throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
+
+                               default :
+                                       if (Character.isJavaIdentifierStart(this.currentCharacter))
+                                               return scanIdentifierOrKeyword();
+                                       if (isDigit(this.currentCharacter))
+                                               return scanNumber(false);
+                                       return TokenNameERROR;
+                       }
+               }
+       } //-----------------end switch while try--------------------
+       catch (IndexOutOfBoundsException e) {
+               if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
+                       // reposition scanner in case we are interested by spaces as tokens
+                       this.currentPosition--;
+                       this.startPosition = whiteStart;
+                       return TokenNameWHITESPACE;
+               }
+       }
+       return TokenNameEOF;
+}
+public final void getNextUnicodeChar()
+       throws InvalidInputException {
+       //VOID
+       //handle the case of unicode.
+       //when a unicode appears then we must use a buffer that holds char internal values
+       //At the end of this method currentCharacter holds the new visited char
+       //and currentPosition points right next after it
+
+       //ALL getNextChar.... ARE OPTIMIZED COPIES 
+
+       try {
+               int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
+               this.currentPosition++;
+               while (this.source[this.currentPosition] == 'u') {
+                       this.currentPosition++;
+                       unicodeSize++;
+               }
+
+               if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                       || c1 < 0
+                       || (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                       || c2 < 0
+                       || (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                       || c3 < 0
+                       || (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                       || c4 < 0){
+                       throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+               } else {
+                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                       //need the unicode buffer
+                       if (this.withoutUnicodePtr == 0) {
+                               //buffer all the entries that have been left aside....
+                               unicodeInitializeBuffer(this.currentPosition - unicodeSize - this.startPosition);
+                       }
+                       //fill the buffer with the char
+                       unicodeStoreAt(++this.withoutUnicodePtr);
+               }
+               this.unicodeAsBackSlash = this.currentCharacter == '\\';
+       } catch (ArrayIndexOutOfBoundsException e) {
+               this.currentPosition--;
+               throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+       }
+}
+
+public char[] getSource(){
+       return this.source;
+}
+private boolean isDigit(char c) throws InvalidInputException {
+       if (Character.isDigit(c)) {
+               switch(c) {
+                       case '0' :
+                       case '1' :
+                       case '2' :
+                       case '3' :
+                       case '4' :
+                       case '5' :
+                       case '6' :
+                       case '7' :
+                       case '8' :
+                       case '9' :
+                               return true;
+               }
+               throw new InvalidInputException(Scanner.INVALID_INPUT);
+       } else {
+               return false;
+       }
+}
+/* Tokenize a method body, assuming that curly brackets are properly balanced.
+ */
+public final void jumpOverMethodBody() {
+
+       this.wasAcr = false;
+       int found = 1;
+       try {
+               while (true) { //loop for jumping over comments
+                       // ---------Consume white space and handles startPosition---------
+                       boolean isWhiteSpace;
+                       do {
+                               this.startPosition = this.currentPosition;
+                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                       && (this.source[this.currentPosition] == 'u')) {
+                                       isWhiteSpace = jumpOverUnicodeWhiteSpace();
+                               } else {
+                                       if (this.recordLineSeparator
+                                               && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')))
+                                               pushLineSeparator();
+                                       isWhiteSpace = CharOperation.isWhitespace(this.currentCharacter);
+                               }
+                       } while (isWhiteSpace);
+
+                       // -------consume token until } is found---------
+                       switch (this.currentCharacter) {
+                               case '{' :
+                                       found++;
+                                       break;
+                               case '}' :
+                                       found--;
+                                       if (found == 0)
+                                               return;
+                                       break;
+                               case '\'' :
+                                       {
+                                               boolean test;
+                                               test = getNextChar('\\');
+                                               if (test) {
+                                                       try {
+                                                               scanEscapeCharacter();
+                                                       } catch (InvalidInputException ex) {
+                                                               // ignore
+                                                       }
+                                               } else {
+                                                       try { // 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);
+                                                                       }
+                                                               }
+                                                       } catch (InvalidInputException ex) {
+                                                               // ignore
+                                                       }
+                                               }
+                                               getNextChar('\'');
+                                               break;
+                                       }
+                               case '"' :
+                                       try {
+                                               try { // 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);
+                                                               }
+                                                       }
+                                               } catch (InvalidInputException ex) {
+                                                               // ignore
+                                               }
+                                               while (this.currentCharacter != '"') {
+                                                       if (this.currentCharacter == '\r'){
+                                                               if (this.source[this.currentPosition] == '\n') this.currentPosition++;
+                                                               break; // the string cannot go further that the line
+                                                       }
+                                                       if (this.currentCharacter == '\n'){
+                                                               break; // the string cannot go further that the line
+                                                       }
+                                                       if (this.currentCharacter == '\\') {
+                                                               try {
+                                                                       scanEscapeCharacter();
+                                                               } catch (InvalidInputException ex) {
+                                                                       // ignore
+                                                               }
+                                                       }
+                                                       try { // 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);
+                                                                       }
+                                                               }
+                                                       } catch (InvalidInputException ex) {
+                                                               // ignore
+                                                       }
+                                               }
+                                       } catch (IndexOutOfBoundsException e) {
+                                               return;
+                                       }
+                                       break;
+                               case '/' :
+                                       {
+                                               int test;
+                                               if ((test = getNextChar('/', '*')) == 0) { //line comment 
+                                                       try {
+                                                               this.lastCommentLinePosition = this.currentPosition;
+                                                               //get the next char 
+                                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                       && (this.source[this.currentPosition] == 'u')) {
+                                                                       //-------------unicode traitement ------------
+                                                                       int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                       this.currentPosition++;
+                                                                       while (this.source[this.currentPosition] == 'u') {
+                                                                               this.currentPosition++;
+                                                                       }
+                                                                       if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c1 < 0
+                                                                               || (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c2 < 0
+                                                                               || (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c3 < 0
+                                                                               || (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                               || c4 < 0) { //error don't care of the value
+                                                                               this.currentCharacter = 'A';
+                                                                       } //something different from \n and \r
+                                                                       else {
+                                                                               this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                       }
+                                                               }
+                                                               //handle the \\u case manually into comment
+                                                               if (this.currentCharacter == '\\') {
+                                                                       if (this.source[this.currentPosition] == '\\')
+                                                                               this.currentPosition++;
+                                                               } //jump over the \\
+                                                               boolean isUnicode = false;
+                                                               while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
+                                                                       this.lastCommentLinePosition = this.currentPosition;
+                                                                       //get the next char 
+                                                                       isUnicode = false;
+                                                                       if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                               && (this.source[this.currentPosition] == 'u')) {
+                                                                               isUnicode = true;
+                                                                               //-------------unicode traitement ------------
+                                                                               int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                               this.currentPosition++;
+                                                                               while (this.source[this.currentPosition] == 'u') {
+                                                                                       this.currentPosition++;
+                                                                               }
+                                                                               if ((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c1 < 0
+                                                                                       || (c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c2 < 0
+                                                                                       || (c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c3 < 0
+                                                                                       || (c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                                                                                       || c4 < 0) { //error don't care of the value
+                                                                                       this.currentCharacter = 'A';
+                                                                               } //something different from \n and \r
+                                                                               else {
+                                                                                       this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                               }
+                                                                       }
+                                                                       //handle the \\u case manually into comment
+                                                                       if (this.currentCharacter == '\\') {
+                                                                               if (this.source[this.currentPosition] == '\\')
+                                                                                       this.currentPosition++;
+                                                                       } //jump over the \\
+                                                               }
+                                                               /*
+                                                                * We need to completely consume the line break
+                                                                */
+                                                               if (this.currentCharacter == '\r'
+                                                                  && this.source.length > this.currentPosition) {
+                                                                       if (this.source[this.currentPosition] == '\n') {
+                                                                               this.currentPosition++;
+                                                                               this.currentCharacter = '\n';
+                                                                       } else if ((this.source[this.currentPosition] == '\\')
+                                                                               && (this.source[this.currentPosition + 1] == 'u')) {
+                                                                               isUnicode = true;
+                                                                               char unicodeChar;
+                                                                               int index = this.currentPosition + 1;
+                                                                               index++;
+                                                                               while (this.source[index] == 'u') {
+                                                                                       index++;
+                                                                               }
+                                                                               //-------------unicode traitement ------------
+                                                                               int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+                                                                               if ((c1 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c1 < 0
+                                                                                       || (c2 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c2 < 0
+                                                                                       || (c3 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c3 < 0
+                                                                                       || (c4 = Character.getNumericValue(this.source[index++])) > 15
+                                                                                       || c4 < 0) { //error don't care of the value
+                                                                                       unicodeChar = 'A';
+                                                                               } else {
+                                                                                       unicodeChar = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+                                                                               }
+                                                                               if (unicodeChar == '\n') {
+                                                                                       this.currentPosition = index;
+                                                                                       this.currentCharacter = '\n';
+                                                                               }
+                                                                       }
+                                                               }
+                                                               recordComment(TokenNameCOMMENT_LINE);
+                                                               if (this.recordLineSeparator
+                                                                       && ((this.currentCharacter == '\r') || (this.currentCharacter == '\n'))) {
+                                                                               if (isUnicode) {
+                                                                                       pushUnicodeLineSeparator();
+                                                                               } else {
+                                                                                       pushLineSeparator();
+                                                                               }
+                                                                       }
+                                                       } catch (IndexOutOfBoundsException e) {
+                                                                //an eof will then be generated
+                                                               this.currentPosition--;
+                                                               recordComment(TokenNameCOMMENT_LINE);
+                                                               if (!this.tokenizeComments) {
+                                                                       this.currentPosition++; 
+                                                               }
+                                                       }
+                                                       break;
+                                               }
+                                               if (test > 0) { //traditional and javadoc comment
+                                                       boolean isJavadoc = false;
+                                                       try { //get the next char
+                                                               boolean star = false;
+                                                               boolean isUnicode = false;
+                                                               // consume next character
+                                                               this.unicodeAsBackSlash = false;
+                                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                       && (this.source[this.currentPosition] == 'u')) {
+                                                                       getNextUnicodeChar();
+                                                                       isUnicode = true;
+                                                               } else {
+                                                                       isUnicode = false;
+                                                                       if (this.withoutUnicodePtr != 0) {
+                                                                   unicodeStoreAt(++this.withoutUnicodePtr);
+                                                                       }
+                                                               }
+       
+                                                               if (this.currentCharacter == '*') {
+                                                                       isJavadoc = true;
+                                                                       star = true;
+                                                               }
+                                                               if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+                                                                       if (this.recordLineSeparator) {
+                                                                               if (isUnicode) {
+                                                                                       pushUnicodeLineSeparator();
+                                                                               } else {
+                                                                                       pushLineSeparator();
+                                                                               }
+                                                                       } else {
+                                                                               this.currentLine = null;
+                                                                       }
+                                                               }
+                                                               isUnicode = false;
+                                                               if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                       && (this.source[this.currentPosition] == 'u')) {
+                                                                       //-------------unicode traitement ------------
+                                                                       getNextUnicodeChar();
+                                                                       isUnicode = true;
+                                                               } else {
+                                                                       isUnicode = false;
+                                                               }
+                                                               //handle the \\u case manually into comment
+                                                               if (this.currentCharacter == '\\') {
+                                                                       if (this.source[this.currentPosition] == '\\')
+                                                                               this.currentPosition++; //jump over the \\
+                                                               }
+                                                               // empty comment is not a javadoc /**/
+                                                               if (this.currentCharacter == '/') { 
+                                                                       isJavadoc = false;
+                                                               }
+                                                               //loop until end of comment */
+                                                               while ((this.currentCharacter != '/') || (!star)) {
+                                                                       if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
+                                                                               if (this.recordLineSeparator) {
+                                                                                       if (isUnicode) {
+                                                                                               pushUnicodeLineSeparator();
+                                                                                       } else {
+                                                                                               pushLineSeparator();
+                                                                                       }
+                                                                               } else {
+                                                                                       this.currentLine = null;
+                                                                               }
+                                                                       }
+                                                                       star = this.currentCharacter == '*';
+                                                                       //get next char
+                                                                       if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+                                                                               && (this.source[this.currentPosition] == 'u')) {
+                                                                               //-------------unicode traitement ------------
+                                                                               getNextUnicodeChar();
+                                                                               isUnicode = true;
+                                                                       } else {
+                                                                               isUnicode = false;
+                                                                       }
+                                                                       //handle the \\u case manually into comment
+                                                                       if (this.currentCharacter == '\\') {
+                                                                               if (this.source[this.currentPosition] == '\\')
+                                                                                       this.currentPosition++;
+                                                                       } //jump over the \\
+                                                               }
+                                                               recordComment(isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK);
+                                                       } catch (IndexOutOfBoundsException e) {
+                                                               return;
+                                                       }
+                                                       break;
+                                               }
+                                               break;
+                                       }
+
+                               default :
+                                       if (Character.isJavaIdentifierStart(this.currentCharacter)) {
+                                               scanIdentifierOrKeyword();
+                                               break;
+                                       }
+                                       if (isDigit(this.currentCharacter)) {
+                                               try {
+                                                       scanNumber(false);
+                                               } catch (InvalidInputException ex) {
+                                                       // ignore
+                                               }
+                                               break;
+                                       }
+                       }
+               }
+               //-----------------end switch while try--------------------
+       } catch (IndexOutOfBoundsException e) {
+               // ignore
+       } catch (InvalidInputException e) {
+               // ignore
+       }
+       return;
+}
+public final boolean jumpOverUnicodeWhiteSpace() throws InvalidInputException {
+       //BOOLEAN
+       //handle the case of unicode. Jump over the next whiteSpace
+       //making startPosition pointing on the next available char
+       //On false, the currentCharacter is filled up with a potential
+       //correct char
+
+       try {
+               this.wasAcr = false;
+               int c1, c2, c3, c4;
+               int unicodeSize = 6;
+               this.currentPosition++;
+               while (this.source[this.currentPosition] == 'u') {
+                       this.currentPosition++;
+                       unicodeSize++;
+               }
+
+               if (((c1 = Character.getNumericValue(this.source[this.currentPosition++])) > 15
+                       || c1 < 0)
+                       || ((c2 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c2 < 0)
+                       || ((c3 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c3 < 0)
+                       || ((c4 = Character.getNumericValue(this.source[this.currentPosition++])) > 15 || c4 < 0)) {
+                       throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+               }
+
+               this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+               if (CharOperation.isWhitespace(this.currentCharacter))
+                       return true;
+
+               //buffer the new char which is not a white space
+               unicodeStoreAt(++this.withoutUnicodePtr);
+               //this.withoutUnicodePtr == 1 is true here
+               return false;
+       } catch (IndexOutOfBoundsException e){
+               this.currentPosition--;
+               throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+       }
+}
+
+final char[] optimizedCurrentTokenSource1() {
+       //return always the same char[] build only once
+
+       //optimization at no speed cost of 99.5 % of the singleCharIdentifier
+       char charOne = this.source[this.startPosition];
+       switch (charOne) {
+               case 'a' :
+                       return charArray_a;
+               case 'b' :
+                       return charArray_b;
+               case 'c' :
+                       return charArray_c;
+               case 'd' :
+                       return charArray_d;
+               case 'e' :
+                       return charArray_e;
+               case 'f' :
+                       return charArray_f;
+               case 'g' :
+                       return charArray_g;
+               case 'h' :
+                       return charArray_h;
+               case 'i' :
+                       return charArray_i;
+               case 'j' :
+                       return charArray_j;
+               case 'k' :
+                       return charArray_k;
+               case 'l' :
+                       return charArray_l;
+               case 'm' :
+                       return charArray_m;
+               case 'n' :
+                       return charArray_n;
+               case 'o' :
+                       return charArray_o;
+               case 'p' :
+                       return charArray_p;
+               case 'q' :
+                       return charArray_q;
+               case 'r' :
+                       return charArray_r;
+               case 's' :
+                       return charArray_s;
+               case 't' :
+                       return charArray_t;
+               case 'u' :
+                       return charArray_u;
+               case 'v' :
+                       return charArray_v;
+               case 'w' :
+                       return charArray_w;
+               case 'x' :
+                       return charArray_x;
+               case 'y' :
+                       return charArray_y;
+               case 'z' :
+                       return charArray_z;
+               default :
+                       return new char[] {charOne};
+       }
+}
+final char[] optimizedCurrentTokenSource2() {
+       //try to return the same char[] build only once
+
+       char c0, c1;
+       int hash = 
+               (((c0 = this.source[this.startPosition]) << 6) + (c1 = this.source[this.startPosition + 1]))
+                       % TableSize; 
+       char[][] table = this.charArray_length[0][hash];
+       int i = newEntry2;
+       while (++i < InternalTableSize) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0]) && (c1 == charArray[1]))
+                       return charArray;
+       }
+       //---------other side---------
+       i = -1;
+       int max = newEntry2;
+       while (++i <= max) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0]) && (c1 == charArray[1]))
+                       return charArray;
+       }
+       //--------add the entry-------
+       if (++max >= InternalTableSize) max = 0;
+       char[] r;
+       table[max] = (r = new char[] {c0, c1});
+       newEntry2 = max;
+       return r;
+}
+final char[] optimizedCurrentTokenSource3() {
+       //try to return the same char[] build only once
+
+       char c0, c1, c2;
+       int hash = 
+               (((c0 = this.source[this.startPosition]) << 12)
+                       + ((c1 = this.source[this.startPosition + 1]) << 6)
+                       + (c2 = this.source[this.startPosition + 2]))
+                       % TableSize; 
+       char[][] table = this.charArray_length[1][hash];
+       int i = newEntry3;
+       while (++i < InternalTableSize) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]))
+                       return charArray;
+       }
+       //---------other side---------
+       i = -1;
+       int max = newEntry3;
+       while (++i <= max) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0]) && (c1 == charArray[1]) && (c2 == charArray[2]))
+                       return charArray;
+       }
+       //--------add the entry-------
+       if (++max >= InternalTableSize) max = 0;
+       char[] r;
+       table[max] = (r = new char[] {c0, c1, c2});
+       newEntry3 = max;
+       return r;
+}
+final char[] optimizedCurrentTokenSource4() {
+       //try to return the same char[] build only once
+
+       char c0, c1, c2, c3;
+       long hash = 
+               ((((long) (c0 = this.source[this.startPosition])) << 18)
+                       + ((c1 = this.source[this.startPosition + 1]) << 12)
+                       + ((c2 = this.source[this.startPosition + 2]) << 6)
+                       + (c3 = this.source[this.startPosition + 3]))
+                       % TableSize; 
+       char[][] table = this.charArray_length[2][(int) hash];
+       int i = newEntry4;
+       while (++i < InternalTableSize) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0])
+                       && (c1 == charArray[1])
+                       && (c2 == charArray[2])
+                       && (c3 == charArray[3]))
+                       return charArray;
+       }
+       //---------other side---------
+       i = -1;
+       int max = newEntry4;
+       while (++i <= max) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0])
+                       && (c1 == charArray[1])
+                       && (c2 == charArray[2])
+                       && (c3 == charArray[3]))
+                       return charArray;
+       }
+       //--------add the entry-------
+       if (++max >= InternalTableSize) max = 0;
+       char[] r;
+       table[max] = (r = new char[] {c0, c1, c2, c3});
+       newEntry4 = max;
+       return r;
+       
+}
+final char[] optimizedCurrentTokenSource5() {
+       //try to return the same char[] build only once
+
+       char c0, c1, c2, c3, c4;
+       long hash = 
+               ((((long) (c0 = this.source[this.startPosition])) << 24)
+                       + (((long) (c1 = this.source[this.startPosition + 1])) << 18)
+                       + ((c2 = this.source[this.startPosition + 2]) << 12)
+                       + ((c3 = this.source[this.startPosition + 3]) << 6)
+                       + (c4 = this.source[this.startPosition + 4]))
+                       % TableSize; 
+       char[][] table = this.charArray_length[3][(int) hash];
+       int i = newEntry5;
+       while (++i < InternalTableSize) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0])
+                       && (c1 == charArray[1])
+                       && (c2 == charArray[2])
+                       && (c3 == charArray[3])
+                       && (c4 == charArray[4]))
+                       return charArray;
+       }
+       //---------other side---------
+       i = -1;
+       int max = newEntry5;
+       while (++i <= max) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0])
+                       && (c1 == charArray[1])
+                       && (c2 == charArray[2])
+                       && (c3 == charArray[3])
+                       && (c4 == charArray[4]))
+                       return charArray;
+       }
+       //--------add the entry-------
+       if (++max >= InternalTableSize) max = 0;
+       char[] r;
+       table[max] = (r = new char[] {c0, c1, c2, c3, c4});
+       newEntry5 = max;
+       return r;
+               
+}
+final char[] optimizedCurrentTokenSource6() {
+       //try to return the same char[] build only once
+
+       char c0, c1, c2, c3, c4, c5;
+       long hash = 
+               ((((long) (c0 = this.source[this.startPosition])) << 32)
+                       + (((long) (c1 = this.source[this.startPosition + 1])) << 24)
+                       + (((long) (c2 = this.source[this.startPosition + 2])) << 18)
+                       + ((c3 = this.source[this.startPosition + 3]) << 12)
+                       + ((c4 = this.source[this.startPosition + 4]) << 6)
+                       + (c5 = this.source[this.startPosition + 5]))
+                       % TableSize; 
+       char[][] table = this.charArray_length[4][(int) hash];
+       int i = newEntry6;
+       while (++i < InternalTableSize) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0])
+                       && (c1 == charArray[1])
+                       && (c2 == charArray[2])
+                       && (c3 == charArray[3])
+                       && (c4 == charArray[4])
+                       && (c5 == charArray[5]))
+                       return charArray;
+       }
+       //---------other side---------
+       i = -1;
+       int max = newEntry6;
+       while (++i <= max) {
+               char[] charArray = table[i];
+               if ((c0 == charArray[0])
+                       && (c1 == charArray[1])
+                       && (c2 == charArray[2])
+                       && (c3 == charArray[3])
+                       && (c4 == charArray[4])
+                       && (c5 == charArray[5]))
+                       return charArray;
+       }
+       //--------add the entry-------
+       if (++max >= InternalTableSize) max = 0;
+       char[] r;
+       table[max] = (r = new char[] {c0, c1, c2, c3, c4, c5});
+       newEntry6 = max;
+       return r;       
+}
+private void parseTags(NLSLine line) {
+       String s = new String(getCurrentTokenSource());
+       int pos = s.indexOf(TAG_PREFIX);
+       int lineLength = line.size();
+       while (pos != -1) {
+               int start = pos + TAG_PREFIX_LENGTH;
+               int end = s.indexOf(TAG_POSTFIX, start);
+               if (end != -1) {
+                       String index = s.substring(start, end);
+                       int i = 0;
+                       try {
+                               i = Integer.parseInt(index) - 1; // Tags are one based not zero based.
+                       } catch (NumberFormatException e) {
+                               i = -1; // we don't want to consider this as a valid NLS tag
+                       }
+                       if (line.exists(i)) {
+                               line.set(i, null);
+                       }
+               }
+               pos = s.indexOf(TAG_PREFIX, start);
+       }
+
+       this.nonNLSStrings = new StringLiteral[lineLength];
+       int nonNLSCounter = 0;
+       for (Iterator iterator = line.iterator(); iterator.hasNext(); ) {
+               StringLiteral literal = (StringLiteral) iterator.next();
+               if (literal != null) {
+                       this.nonNLSStrings[nonNLSCounter++] = literal;
+               }
+       }
+       if (nonNLSCounter == 0) {
+               this.nonNLSStrings = null;
+               this.currentLine = null;
+               return;
+       } 
+       this.wasNonExternalizedStringLiteral = true;
+       if (nonNLSCounter != lineLength) {
+               System.arraycopy(this.nonNLSStrings, 0, (this.nonNLSStrings = new StringLiteral[nonNLSCounter]), 0, nonNLSCounter);
+       }
+       this.currentLine = null;
+}
+
+public final void pushLineSeparator() {
+       //see comment on isLineDelimiter(char) for the use of '\n' and '\r'
+       final int INCREMENT = 250;
+       
+       if (this.checkNonExternalizedStringLiterals) {
+       // reinitialize the current line for non externalize strings purpose
+               this.currentLine = null;
+       }
+       //currentCharacter is at position currentPosition-1
+
+       // cr 000D
+       if (this.currentCharacter == '\r') {
+               int separatorPos = this.currentPosition - 1;
+               //TODO (olivier) david - why the following line was "if ((this.linePtr > 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;" ?
+               if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
+               //System.out.println("CR-" + separatorPos);
+               int length = this.lineEnds.length;
+               if (++this.linePtr >=  length)
+                       System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length);
+               this.lineEnds[this.linePtr] = separatorPos;
+               // look-ahead for merged cr+lf
+               try {
+                       if (this.source[this.currentPosition] == '\n') {
+                               //System.out.println("look-ahead LF-" + this.currentPosition);                  
+                               this.lineEnds[this.linePtr] = this.currentPosition;
+                               this.currentPosition++;
+                               this.wasAcr = false;
+                       } else {
+                               this.wasAcr = true;
+                       }
+               } catch(IndexOutOfBoundsException e) {
+                       this.wasAcr = true;
+               }
+       } else {
+               // lf 000A
+               if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf
+                       if (this.wasAcr && (this.lineEnds[this.linePtr] == (this.currentPosition - 2))) {
+                               //System.out.println("merge LF-" + (this.currentPosition - 1));                                                 
+                               this.lineEnds[this.linePtr] = this.currentPosition - 1;
+                       } else {
+                               int separatorPos = this.currentPosition - 1;
+                               //TODO (olivier) david - why the following line was "if ((this.linePtr > 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;" ?
+                               if ((this.linePtr >= 0) && (this.lineEnds[this.linePtr] >= separatorPos)) return;
+                               // System.out.println("LF-" + separatorPos);
+                               int length = this.lineEnds.length;
+                               if (++this.linePtr >=  length)
+                                       System.arraycopy(this.lineEnds, 0, this.lineEnds = new int[length + INCREMENT], 0, length);
+                               this.lineEnds[this.linePtr] = separatorPos;
+                       }
+                       this.wasAcr = false;
+               }
+       }
+}
+public final void pushUnicodeLineSeparator() {
+       if (this.checkNonExternalizedStringLiterals) {
+       // reinitialize the current line for non externalize strings purpose
+               this.currentLine = null;
+       }
+       
+       // cr 000D
+       if (this.currentCharacter == '\r') {
+               if (this.source[this.currentPosition] == '\n') {
+                       this.wasAcr = false;
+               } else {
+                       this.wasAcr = true;
+               }
+       } else {
+               // lf 000A
+               if (this.currentCharacter == '\n') { //must merge eventual cr followed by lf
+                       this.wasAcr = false;
+               }
+       }
+}
+public void recordComment(int token) {
+       // compute position
+       int stopPosition = this.currentPosition;
+       switch (token) {
+               case TokenNameCOMMENT_LINE:
+                       stopPosition = -this.lastCommentLinePosition;
+                       break;
+               case TokenNameCOMMENT_BLOCK:
+                       stopPosition = -this.currentPosition;
+                       break;
+       }
+
+       // a new comment is recorded
+       int length = this.commentStops.length;
+       if (++this.commentPtr >=  length) {
+               System.arraycopy(this.commentStops, 0, this.commentStops = new int[length + 30], 0, length);
+               //grows the positions buffers too
+               System.arraycopy(this.commentStarts, 0, this.commentStarts = new int[length + 30], 0, length);
+       }
+       this.commentStops[this.commentPtr] = stopPosition;
+       this.commentStarts[this.commentPtr] = this.startPosition;
+}
+
+/**
+ * Reposition the scanner on some portion of the original source. The given endPosition is the last valid position.
+ * Beyond this position, the scanner will answer EOF tokens (<code>ITerminalSymbols.TokenNameEOF</code>).
+ * 
+ * @param begin the given start position
+ * @param end the given end position
+ */
+public void resetTo(int begin, int end) {
+       //reset the scanner to a given position where it may rescan again
+
+       this.diet = false;
+       this.initialPosition = this.startPosition = this.currentPosition = begin;
+       this.eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
+       this.commentPtr = -1; // reset comment stack
+       this.foundTaskCount = 0;
+       
+//     // if resetTo is used with being > than end.
+//     if (begin > this.eofPosition) {
+//             begin = this.eofPosition;
+//     }
+}
+
+public final void scanEscapeCharacter() throws InvalidInputException {
+       // the string with "\\u" is a legal string of two chars \ and u
+       //thus we use a direct access to the source (for regular cases).
+
+       if (this.unicodeAsBackSlash) {
+               // 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);
+                       }
+               }
+       } else
+               this.currentCharacter = this.source[this.currentPosition++];
+       switch (this.currentCharacter) {
+               case 'b' :
+                       this.currentCharacter = '\b';
+                       break;
+               case 't' :
+                       this.currentCharacter = '\t';
+                       break;
+               case 'n' :
+                       this.currentCharacter = '\n';
+                       break;
+               case 'f' :
+                       this.currentCharacter = '\f';
+                       break;
+               case 'r' :
+                       this.currentCharacter = '\r';
+                       break;
+               case '\"' :
+                       this.currentCharacter = '\"';
+                       break;
+               case '\'' :
+                       this.currentCharacter = '\'';
+                       break;
+               case '\\' :
+                       this.currentCharacter = '\\';
+                       break;
+               default :
+                       // -----------octal escape--------------
+                       // OctalDigit
+                       // OctalDigit OctalDigit
+                       // ZeroToThree OctalDigit OctalDigit
+
+                       int number = Character.getNumericValue(this.currentCharacter);
+                       if (number >= 0 && number <= 7) {
+                               boolean zeroToThreeNot = number > 3;
+                               if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+                                       int digit = Character.getNumericValue(this.currentCharacter);
+                                       if (digit >= 0 && digit <= 7) {
+                                               number = (number * 8) + digit;
+                                               if (isDigit(this.currentCharacter = this.source[this.currentPosition++])) {
+                                                       if (zeroToThreeNot) {// has read \NotZeroToThree OctalDigit Digit --> ignore last character
+                                                               this.currentPosition--;
+                                                       } else {
+                                                               digit = Character.getNumericValue(this.currentCharacter);
+                                                               if (digit >= 0 && digit <= 7){ // has read \ZeroToThree OctalDigit OctalDigit
+                                                                       number = (number * 8) + digit;
+                                                               } else {// has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character
+                                                                       this.currentPosition--;
+                                                               }
+                                                       }
+                                               } else { // has read \OctalDigit NonDigit--> ignore last character
+                                                       this.currentPosition--;
+                                               }
+                                       } else { // has read \OctalDigit NonOctalDigit--> ignore last character                                         
+                                               this.currentPosition--;
+                                       }
+                               } else { // has read \OctalDigit --> ignore last character
+                                       this.currentPosition--;
+                               }
+                               if (number > 255)
+                                       throw new InvalidInputException(INVALID_ESCAPE);
+                               this.currentCharacter = (char) number;
+                       } else
+                               throw new InvalidInputException(INVALID_ESCAPE);
+       }
+}
+public int scanIdentifierOrKeyword() {
+       //test keywords
+
+       //first dispatch on the first char.
+       //then the length. If there are several
+       //keywors with the same length AND the same first char, then do another
+       //dispatch on the second char 
+       this.useAssertAsAnIndentifier = false;
+       while (getNextCharAsJavaIdentifierPart()){/*empty*/}
+
+       int index, length;
+       char[] data;
+       char firstLetter;
+       if (this.withoutUnicodePtr == 0)
+
+               //quick test on length == 1 but not on length > 12 while most identifier
+               //have a length which is <= 12...but there are lots of identifier with
+               //only one char....
+
+               {
+               if ((length = this.currentPosition - this.startPosition) == 1)
+                       return TokenNameIdentifier;
+               data = this.source;
+               index = this.startPosition;
+       } else {
+               if ((length = this.withoutUnicodePtr) == 1)
+                       return TokenNameIdentifier;
+               data = this.withoutUnicodeBuffer;
+               index = 1;
+       }
+
+       firstLetter = data[index];
+       switch (firstLetter) {
+
+               case 'a' : 
+                       switch(length) {
+                               case 8: //abstract
+                                       if ((data[++index] == 'b')
+                                               && (data[++index] == 's')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 'c')
+                                               && (data[++index] == 't')) {
+                                                       return TokenNameabstract;
+                                               } else {
+                                                       return TokenNameIdentifier;
+                                               }
+                               case 6: // assert
+                                       if ((data[++index] == 's')
+                                               && (data[++index] == 's')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 't')) {
+                                                       if (this.assertMode) {
+                                                               this.containsAssertKeyword = true;
+                                                               return TokenNameassert;
+                                                       } else {
+                                                               this.useAssertAsAnIndentifier = true;
+                                                               return TokenNameIdentifier;                                                             
+                                                       }
+                                               } else {
+                                                       return TokenNameIdentifier;
+                                               }
+                               default: 
+                                       return TokenNameIdentifier;
+                       }
+               case 'b' : //boolean break byte
+                       switch (length) {
+                               case 4 :
+                                       if ((data[++index] == 'y') && (data[++index] == 't') && (data[++index] == 'e'))
+                                               return TokenNamebyte;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 5 :
+                                       if ((data[++index] == 'r')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 'k'))
+                                               return TokenNamebreak;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 7 :
+                                       if ((data[++index] == 'o')
+                                               && (data[++index] == 'o')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 'n'))
+                                               return TokenNameboolean;
+                                       else
+                                               return TokenNameIdentifier;
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'c' : //case char catch const class continue
+                       switch (length) {
+                               case 4 :
+                                       if (data[++index] == 'a')
+                                               if ((data[++index] == 's') && (data[++index] == 'e'))
+                                                       return TokenNamecase;
+                                               else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if ((data[index] == 'h') && (data[++index] == 'a') && (data[++index] == 'r'))
+                                                       return TokenNamechar;
+                                               else
+                                                       return TokenNameIdentifier;
+                               case 5 :
+                                       if (data[++index] == 'a')
+                                               if ((data[++index] == 't') && (data[++index] == 'c') && (data[++index] == 'h'))
+                                                       return TokenNamecatch;
+                                               else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if (data[index] == 'l')
+                                                       if ((data[++index] == 'a')
+                                                               && (data[++index] == 's')
+                                                               && (data[++index] == 's'))
+                                                               return TokenNameclass;
+                                                       else
+                                                               return TokenNameIdentifier;
+                                               else if ((data[index] == 'o')
+                                                       && (data[++index] == 'n')
+                                                       && (data[++index] == 's')
+                                                       && (data[++index] == 't'))
+                                                       return TokenNameERROR; //const is not used in java ???????
+                                               else
+                                                       return TokenNameIdentifier;
+                               case 8 :
+                                       if ((data[++index] == 'o')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 'u')
+                                               && (data[++index] == 'e'))
+                                               return TokenNamecontinue;
+                                       else
+                                               return TokenNameIdentifier;
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'd' : //default do double
+                       switch (length) {
+                               case 2 :
+                                       if ((data[++index] == 'o'))
+                                               return TokenNamedo;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 6 :
+                                       if ((data[++index] == 'o')
+                                               && (data[++index] == 'u')
+                                               && (data[++index] == 'b')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'e'))
+                                               return TokenNamedouble;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 7 :
+                                       if ((data[++index] == 'e')
+                                               && (data[++index] == 'f')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 'u')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 't'))
+                                               return TokenNamedefault;
+                                       else
+                                               return TokenNameIdentifier;
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+               case 'e' : //else extends
+                       switch (length) {
+                               case 4 :
+                                       if ((data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
+                                               return TokenNameelse;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 7 :
+                                       if ((data[++index] == 'x')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 'd')
+                                               && (data[++index] == 's'))
+                                               return TokenNameextends;
+                                       else
+                                               return TokenNameIdentifier;
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'f' : //final finally float for false
+                       switch (length) {
+                               case 3 :
+                                       if ((data[++index] == 'o') && (data[++index] == 'r'))
+                                               return TokenNamefor;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 5 :
+                                       if (data[++index] == 'i')
+                                               if ((data[++index] == 'n')
+                                                       && (data[++index] == 'a')
+                                                       && (data[++index] == 'l')) {
+                                                       return TokenNamefinal;
+                                               } else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if (data[index] == 'l')
+                                                       if ((data[++index] == 'o')
+                                                               && (data[++index] == 'a')
+                                                               && (data[++index] == 't'))
+                                                               return TokenNamefloat;
+                                                       else
+                                                               return TokenNameIdentifier;
+                                               else
+                                                       if ((data[index] == 'a')
+                                                               && (data[++index] == 'l')
+                                                               && (data[++index] == 's')
+                                                               && (data[++index] == 'e'))
+                                                               return TokenNamefalse;
+                                                       else
+                                                               return TokenNameIdentifier;
+                               case 7 :
+                                       if ((data[++index] == 'i')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'y'))
+                                               return TokenNamefinally;
+                                       else
+                                               return TokenNameIdentifier;
+
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+               case 'g' : //goto
+                       if (length == 4) {
+                               if ((data[++index] == 'o')
+                                       && (data[++index] == 't')
+                                       && (data[++index] == 'o')) {
+                                       return TokenNameERROR;
+                               }
+                       } //no goto in java are allowed, so why java removes this keyword ???
+                       return TokenNameIdentifier;
+
+               case 'i' : //if implements import instanceof int interface
+                       switch (length) {
+                               case 2 :
+                                       if (data[++index] == 'f')
+                                               return TokenNameif;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 3 :
+                                       if ((data[++index] == 'n') && (data[++index] == 't'))
+                                               return TokenNameint;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 6 :
+                                       if ((data[++index] == 'm')
+                                               && (data[++index] == 'p')
+                                               && (data[++index] == 'o')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 't'))
+                                               return TokenNameimport;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 9 :
+                                       if ((data[++index] == 'n')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 'f')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 'c')
+                                               && (data[++index] == 'e'))
+                                               return TokenNameinterface;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 10 :
+                                       if (data[++index] == 'm')
+                                               if ((data[++index] == 'p')
+                                                       && (data[++index] == 'l')
+                                                       && (data[++index] == 'e')
+                                                       && (data[++index] == 'm')
+                                                       && (data[++index] == 'e')
+                                                       && (data[++index] == 'n')
+                                                       && (data[++index] == 't')
+                                                       && (data[++index] == 's'))
+                                                       return TokenNameimplements;
+                                               else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if ((data[index] == 'n')
+                                                       && (data[++index] == 's')
+                                                       && (data[++index] == 't')
+                                                       && (data[++index] == 'a')
+                                                       && (data[++index] == 'n')
+                                                       && (data[++index] == 'c')
+                                                       && (data[++index] == 'e')
+                                                       && (data[++index] == 'o')
+                                                       && (data[++index] == 'f'))
+                                                       return TokenNameinstanceof;
+                                               else
+                                                       return TokenNameIdentifier;
+
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'l' : //long
+                       if (length == 4) {
+                               if ((data[++index] == 'o')
+                                       && (data[++index] == 'n')
+                                       && (data[++index] == 'g')) {
+                                       return TokenNamelong;
+                               }
+                       }
+                       return TokenNameIdentifier;
+
+               case 'n' : //native new null
+                       switch (length) {
+                               case 3 :
+                                       if ((data[++index] == 'e') && (data[++index] == 'w'))
+                                               return TokenNamenew;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 4 :
+                                       if ((data[++index] == 'u') && (data[++index] == 'l') && (data[++index] == 'l'))
+                                               return TokenNamenull;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 6 :
+                                       if ((data[++index] == 'a')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'v')
+                                               && (data[++index] == 'e')) {
+                                               return TokenNamenative;
+                                       } else
+                                               return TokenNameIdentifier;
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'p' : //package private protected public
+                       switch (length) {
+                               case 6 :
+                                       if ((data[++index] == 'u')
+                                               && (data[++index] == 'b')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'c')) {
+                                               return TokenNamepublic;
+                                       } else
+                                               return TokenNameIdentifier;
+                               case 7 :
+                                       if (data[++index] == 'a')
+                                               if ((data[++index] == 'c')
+                                                       && (data[++index] == 'k')
+                                                       && (data[++index] == 'a')
+                                                       && (data[++index] == 'g')
+                                                       && (data[++index] == 'e'))
+                                                       return TokenNamepackage;
+                                               else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if ((data[index] == 'r')
+                                                       && (data[++index] == 'i')
+                                                       && (data[++index] == 'v')
+                                                       && (data[++index] == 'a')
+                                                       && (data[++index] == 't')
+                                                       && (data[++index] == 'e')) {
+                                                       return TokenNameprivate;
+                                               } else
+                                                       return TokenNameIdentifier;
+                               case 9 :
+                                       if ((data[++index] == 'r')
+                                               && (data[++index] == 'o')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'c')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'd')) {
+                                               return TokenNameprotected;
+                                       } else
+                                               return TokenNameIdentifier;
+
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'r' : //return
+                       if (length == 6) {
+                               if ((data[++index] == 'e')
+                                       && (data[++index] == 't')
+                                       && (data[++index] == 'u')
+                                       && (data[++index] == 'r')
+                                       && (data[++index] == 'n')) {
+                                       return TokenNamereturn;
+                               }
+                       }
+                       return TokenNameIdentifier;
+
+               case 's' : //short static super switch synchronized strictfp
+                       switch (length) {
+                               case 5 :
+                                       if (data[++index] == 'h')
+                                               if ((data[++index] == 'o') && (data[++index] == 'r') && (data[++index] == 't'))
+                                                       return TokenNameshort;
+                                               else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if ((data[index] == 'u')
+                                                       && (data[++index] == 'p')
+                                                       && (data[++index] == 'e')
+                                                       && (data[++index] == 'r'))
+                                                       return TokenNamesuper;
+                                               else
+                                                       return TokenNameIdentifier;
+
+                               case 6 :
+                                       if (data[++index] == 't')
+                                               if ((data[++index] == 'a')
+                                                       && (data[++index] == 't')
+                                                       && (data[++index] == 'i')
+                                                       && (data[++index] == 'c')) {
+                                                       return TokenNamestatic;
+                                               } else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if ((data[index] == 'w')
+                                                       && (data[++index] == 'i')
+                                                       && (data[++index] == 't')
+                                                       && (data[++index] == 'c')
+                                                       && (data[++index] == 'h'))
+                                                       return TokenNameswitch;
+                                               else
+                                                       return TokenNameIdentifier;
+                               case 8 :
+                                       if ((data[++index] == 't')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'c')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'f')
+                                               && (data[++index] == 'p'))
+                                               return TokenNamestrictfp;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 12 :
+                                       if ((data[++index] == 'y')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 'c')
+                                               && (data[++index] == 'h')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 'o')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'z')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'd')) {
+                                               return TokenNamesynchronized;
+                                       } else
+                                               return TokenNameIdentifier;
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 't' : //try throw throws transient this true
+                       switch (length) {
+                               case 3 :
+                                       if ((data[++index] == 'r') && (data[++index] == 'y'))
+                                               return TokenNametry;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 4 :
+                                       if (data[++index] == 'h') 
+                                               if ((data[++index] == 'i') && (data[++index] == 's'))
+                                                       return TokenNamethis;
+                                               else
+                                                       return TokenNameIdentifier;
+                                       else
+                                               if ((data[index] == 'r') && (data[++index] == 'u') && (data[++index] == 'e'))
+                                                       return TokenNametrue;
+                                               else
+                                                       return TokenNameIdentifier;
+                               case 5 :
+                                       if ((data[++index] == 'h')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 'o')
+                                               && (data[++index] == 'w'))
+                                               return TokenNamethrow;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 6 :
+                                       if ((data[++index] == 'h')
+                                               && (data[++index] == 'r')
+                                               && (data[++index] == 'o')
+                                               && (data[++index] == 'w')
+                                               && (data[++index] == 's'))
+                                               return TokenNamethrows;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 9 :
+                                       if ((data[++index] == 'r')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 's')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'e')
+                                               && (data[++index] == 'n')
+                                               && (data[++index] == 't')) {
+                                               return TokenNametransient;
+                                       } else
+                                               return TokenNameIdentifier;
+
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'v' : //void volatile
+                       switch (length) {
+                               case 4 :
+                                       if ((data[++index] == 'o') && (data[++index] == 'i') && (data[++index] == 'd'))
+                                               return TokenNamevoid;
+                                       else
+                                               return TokenNameIdentifier;
+                               case 8 :
+                                       if ((data[++index] == 'o')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'a')
+                                               && (data[++index] == 't')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'e')) {
+                                               return TokenNamevolatile;
+                                       } else
+                                               return TokenNameIdentifier;
+
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               case 'w' : //while widefp
+                       switch (length) {
+                               case 5 :
+                                       if ((data[++index] == 'h')
+                                               && (data[++index] == 'i')
+                                               && (data[++index] == 'l')
+                                               && (data[++index] == 'e'))
+                                               return TokenNamewhile;
+                                       else
+                                               return TokenNameIdentifier;
+                                       //case 6:if ( (data[++index] =='i') && (data[++index]=='d') && (data[++index]=='e') && (data[++index]=='f')&& (data[++index]=='p'))
+                                       //return TokenNamewidefp ;
+                                       //else
+                                       //return TokenNameIdentifier;
+                               default :
+                                       return TokenNameIdentifier;
+                       }
+
+               default :
+                       return TokenNameIdentifier;
+       }
+}
+public int scanNumber(boolean dotPrefix) throws InvalidInputException {
+
+       //when entering this method the currentCharacter is the first
+       //digit of the number. It may be preceeded by a '.' when
+       //dotPrefix is true
+
+       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--
+                       while (getNextCharAsDigit(16)){/*empty*/}
+                       if (getNextChar('l', 'L') >= 0)
+                               return TokenNameLongLiteral;
+                       else
+                               return TokenNameIntegerLiteral;
+               }
+
+               //there is x or X in the number
+               //potential octal ! ... some one may write 000099.0 ! thus 00100 < 00078.0 is true !!!!! crazy language
+               if (getNextCharAsDigit()) { //-------------potential octal-----------------
+                       while (getNextCharAsDigit()){/*empty*/}
+
+                       if (getNextChar('l', 'L') >= 0) {
+                               return TokenNameLongLiteral;
+                       }
+
+                       if (getNextChar('f', 'F') >= 0) {
+                               return TokenNameFloatingPointLiteral;
+                       }
+
+                       if (getNextChar('d', 'D') >= 0) {
+                               return TokenNameDoubleLiteral;
+                       } else { //make the distinction between octal and float ....
+                               boolean isInteger = true;
+                               if (getNextChar('.')) { 
+                                       isInteger = false;
+                                       while (getNextCharAsDigit()){/*empty*/}
+                               }
+                               if (getNextChar('e', 'E') >= 0) { // consume next character
+                                       isInteger = false;
+                                       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 || !isInteger)
+                                       return TokenNameDoubleLiteral;
+                               return TokenNameIntegerLiteral;
+                       }
+               } else {
+                       /* carry on */
+               }
+       }
+
+       while (getNextCharAsDigit()){/*empty*/}
+
+       if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
+               return TokenNameLongLiteral;
+
+       if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
+               while (getNextCharAsDigit()){/*empty*/}
+               floating = true;
+       }
+
+       //if floating is true both exponant and suffix may be optional
+
+       if (getNextChar('e', 'E') >= 0) {
+               floating = true;
+               // 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_FLOAT);
+               while (getNextCharAsDigit()){/*empty*/}
+       }
+
+       if (getNextChar('d', 'D') >= 0)
+               return TokenNameDoubleLiteral;
+       if (getNextChar('f', 'F') >= 0)
+               return TokenNameFloatingPointLiteral;
+
+       //the long flag has been tested before
+
+       return floating ? TokenNameDoubleLiteral : TokenNameIntegerLiteral;
+}
+/**
+ * Search the line number corresponding to a specific position
+ * @param position int
+ * @return int
+ */
+public final int getLineNumber(int position) {
+
+       if (this.lineEnds == null)
+               return 1;
+       int length = this.linePtr+1;
+       if (length == 0)
+               return 1;
+       int g = 0, d = length - 1;
+       int m = 0;
+       while (g <= d) {
+               m = (g + d) /2;
+               if (position < this.lineEnds[m]) {
+                       d = m-1;
+               } else if (position > this.lineEnds[m]) {
+                       g = m+1;
+               } else {
+                       return m + 1;
+               }
+       }
+       if (position < this.lineEnds[m]) {
+               return m+1;
+       }
+       return m+2;
+}
+public final void setSource(char[] sourceString){
+       //the source-buffer is set to sourceString
+
+       int sourceLength;
+       if (sourceString == null) {
+               this.source = CharOperation.NO_CHAR;
+               sourceLength = 0;
+       } else {
+               this.source = sourceString;
+               sourceLength = sourceString.length;
+       }
+       this.startPosition = -1;
+       this.eofPosition = sourceLength;
+       this.initialPosition = this.currentPosition = 0;
+       this.containsAssertKeyword = false;
+}
+
+public String toString() {
+       if (this.startPosition == this.source.length)
+               return "EOF\n\n" + new String(this.source); //$NON-NLS-1$
+       if (this.currentPosition > this.source.length)
+               return "behind the EOF\n\n" + new String(this.source); //$NON-NLS-1$
+
+       char front[] = new char[this.startPosition];
+       System.arraycopy(this.source, 0, front, 0, this.startPosition);
+
+       int middleLength = (this.currentPosition - 1) - this.startPosition + 1;
+       char middle[];
+       if (middleLength > -1) {
+               middle = new char[middleLength];
+               System.arraycopy(
+                       this.source, 
+                       this.startPosition, 
+                       middle, 
+                       0, 
+                       middleLength);
+       } else {
+               middle = CharOperation.NO_CHAR;
+       }
+       
+       char end[] = new char[this.source.length - (this.currentPosition - 1)];
+       System.arraycopy(
+               this.source, 
+               (this.currentPosition - 1) + 1, 
+               end, 
+               0, 
+               this.source.length - (this.currentPosition - 1) - 1);
+       
+       return new String(front)
+               + "\n===============================\nStarts here -->" //$NON-NLS-1$
+               + new String(middle)
+               + "<-- Ends here\n===============================\n" //$NON-NLS-1$
+               + new String(end); 
+}
+public final String toStringAction(int act) {
+       switch (act) {
+               case TokenNameIdentifier :
+                       return "Identifier(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+               case TokenNameabstract :
+                       return "abstract"; //$NON-NLS-1$
+               case TokenNameboolean :
+                       return "boolean"; //$NON-NLS-1$
+               case TokenNamebreak :
+                       return "break"; //$NON-NLS-1$
+               case TokenNamebyte :
+                       return "byte"; //$NON-NLS-1$
+               case TokenNamecase :
+                       return "case"; //$NON-NLS-1$
+               case TokenNamecatch :
+                       return "catch"; //$NON-NLS-1$
+               case TokenNamechar :
+                       return "char"; //$NON-NLS-1$
+               case TokenNameclass :
+                       return "class"; //$NON-NLS-1$
+               case TokenNamecontinue :
+                       return "continue"; //$NON-NLS-1$
+               case TokenNamedefault :
+                       return "default"; //$NON-NLS-1$
+               case TokenNamedo :
+                       return "do"; //$NON-NLS-1$
+               case TokenNamedouble :
+                       return "double"; //$NON-NLS-1$
+               case TokenNameelse :
+                       return "else"; //$NON-NLS-1$
+               case TokenNameextends :
+                       return "extends"; //$NON-NLS-1$
+               case TokenNamefalse :
+                       return "false"; //$NON-NLS-1$
+               case TokenNamefinal :
+                       return "final"; //$NON-NLS-1$
+               case TokenNamefinally :
+                       return "finally"; //$NON-NLS-1$
+               case TokenNamefloat :
+                       return "float"; //$NON-NLS-1$
+               case TokenNamefor :
+                       return "for"; //$NON-NLS-1$
+               case TokenNameif :
+                       return "if"; //$NON-NLS-1$
+               case TokenNameimplements :
+                       return "implements"; //$NON-NLS-1$
+               case TokenNameimport :
+                       return "import"; //$NON-NLS-1$
+               case TokenNameinstanceof :
+                       return "instanceof"; //$NON-NLS-1$
+               case TokenNameint :
+                       return "int"; //$NON-NLS-1$
+               case TokenNameinterface :
+                       return "interface"; //$NON-NLS-1$
+               case TokenNamelong :
+                       return "long"; //$NON-NLS-1$
+               case TokenNamenative :
+                       return "native"; //$NON-NLS-1$
+               case TokenNamenew :
+                       return "new"; //$NON-NLS-1$
+               case TokenNamenull :
+                       return "null"; //$NON-NLS-1$
+               case TokenNamepackage :
+                       return "package"; //$NON-NLS-1$
+               case TokenNameprivate :
+                       return "private"; //$NON-NLS-1$
+               case TokenNameprotected :
+                       return "protected"; //$NON-NLS-1$
+               case TokenNamepublic :
+                       return "public"; //$NON-NLS-1$
+               case TokenNamereturn :
+                       return "return"; //$NON-NLS-1$
+               case TokenNameshort :
+                       return "short"; //$NON-NLS-1$
+               case TokenNamestatic :
+                       return "static"; //$NON-NLS-1$
+               case TokenNamesuper :
+                       return "super"; //$NON-NLS-1$
+               case TokenNameswitch :
+                       return "switch"; //$NON-NLS-1$
+               case TokenNamesynchronized :
+                       return "synchronized"; //$NON-NLS-1$
+               case TokenNamethis :
+                       return "this"; //$NON-NLS-1$
+               case TokenNamethrow :
+                       return "throw"; //$NON-NLS-1$
+               case TokenNamethrows :
+                       return "throws"; //$NON-NLS-1$
+               case TokenNametransient :
+                       return "transient"; //$NON-NLS-1$
+               case TokenNametrue :
+                       return "true"; //$NON-NLS-1$
+               case TokenNametry :
+                       return "try"; //$NON-NLS-1$
+               case TokenNamevoid :
+                       return "void"; //$NON-NLS-1$
+               case TokenNamevolatile :
+                       return "volatile"; //$NON-NLS-1$
+               case TokenNamewhile :
+                       return "while"; //$NON-NLS-1$
+
+               case TokenNameIntegerLiteral :
+                       return "Integer(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+               case TokenNameLongLiteral :
+                       return "Long(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+               case TokenNameFloatingPointLiteral :
+                       return "Float(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+               case TokenNameDoubleLiteral :
+                       return "Double(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+               case TokenNameCharacterLiteral :
+                       return "Char(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+               case TokenNameStringLiteral :
+                       return "String(" + new String(getCurrentTokenSource()) + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+
+               case TokenNamePLUS_PLUS :
+                       return "++"; //$NON-NLS-1$
+               case TokenNameMINUS_MINUS :
+                       return "--"; //$NON-NLS-1$
+               case TokenNameEQUAL_EQUAL :
+                       return "=="; //$NON-NLS-1$
+               case TokenNameLESS_EQUAL :
+                       return "<="; //$NON-NLS-1$
+               case TokenNameGREATER_EQUAL :
+                       return ">="; //$NON-NLS-1$
+               case TokenNameNOT_EQUAL :
+                       return "!="; //$NON-NLS-1$
+               case TokenNameLEFT_SHIFT :
+                       return "<<"; //$NON-NLS-1$
+               case TokenNameRIGHT_SHIFT :
+                       return ">>"; //$NON-NLS-1$
+               case TokenNameUNSIGNED_RIGHT_SHIFT :
+                       return ">>>"; //$NON-NLS-1$
+               case TokenNamePLUS_EQUAL :
+                       return "+="; //$NON-NLS-1$
+               case TokenNameMINUS_EQUAL :
+                       return "-="; //$NON-NLS-1$
+               case TokenNameMULTIPLY_EQUAL :
+                       return "*="; //$NON-NLS-1$
+               case TokenNameDIVIDE_EQUAL :
+                       return "/="; //$NON-NLS-1$
+               case TokenNameAND_EQUAL :
+                       return "&="; //$NON-NLS-1$
+               case TokenNameOR_EQUAL :
+                       return "|="; //$NON-NLS-1$
+               case TokenNameXOR_EQUAL :
+                       return "^="; //$NON-NLS-1$
+               case TokenNameREMAINDER_EQUAL :
+                       return "%="; //$NON-NLS-1$
+               case TokenNameLEFT_SHIFT_EQUAL :
+                       return "<<="; //$NON-NLS-1$
+               case TokenNameRIGHT_SHIFT_EQUAL :
+                       return ">>="; //$NON-NLS-1$
+               case TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL :
+                       return ">>>="; //$NON-NLS-1$
+               case TokenNameOR_OR :
+                       return "||"; //$NON-NLS-1$
+               case TokenNameAND_AND :
+                       return "&&"; //$NON-NLS-1$
+               case TokenNamePLUS :
+                       return "+"; //$NON-NLS-1$
+               case TokenNameMINUS :
+                       return "-"; //$NON-NLS-1$
+               case TokenNameNOT :
+                       return "!"; //$NON-NLS-1$
+               case TokenNameREMAINDER :
+                       return "%"; //$NON-NLS-1$
+               case TokenNameXOR :
+                       return "^"; //$NON-NLS-1$
+               case TokenNameAND :
+                       return "&"; //$NON-NLS-1$
+               case TokenNameMULTIPLY :
+                       return "*"; //$NON-NLS-1$
+               case TokenNameOR :
+                       return "|"; //$NON-NLS-1$
+               case TokenNameTWIDDLE :
+                       return "~"; //$NON-NLS-1$
+               case TokenNameDIVIDE :
+                       return "/"; //$NON-NLS-1$
+               case TokenNameGREATER :
+                       return ">"; //$NON-NLS-1$
+               case TokenNameLESS :
+                       return "<"; //$NON-NLS-1$
+               case TokenNameLPAREN :
+                       return "("; //$NON-NLS-1$
+               case TokenNameRPAREN :
+                       return ")"; //$NON-NLS-1$
+               case TokenNameLBRACE :
+                       return "{"; //$NON-NLS-1$
+               case TokenNameRBRACE :
+                       return "}"; //$NON-NLS-1$
+               case TokenNameLBRACKET :
+                       return "["; //$NON-NLS-1$
+               case TokenNameRBRACKET :
+                       return "]"; //$NON-NLS-1$
+               case TokenNameSEMICOLON :
+                       return ";"; //$NON-NLS-1$
+               case TokenNameQUESTION :
+                       return "?"; //$NON-NLS-1$
+               case TokenNameCOLON :
+                       return ":"; //$NON-NLS-1$
+               case TokenNameCOMMA :
+                       return ","; //$NON-NLS-1$
+               case TokenNameDOT :
+                       return "."; //$NON-NLS-1$
+               case TokenNameEQUAL :
+                       return "="; //$NON-NLS-1$
+               case TokenNameEOF :
+                       return "EOF"; //$NON-NLS-1$
+               default :
+                       return "not-a-token"; //$NON-NLS-1$
+       }
+}
+public void unicodeInitializeBuffer(int length) {
+       this.withoutUnicodePtr = length;        
+    if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[length+(1+10)];
+    int bLength = this.withoutUnicodeBuffer.length;
+    if (1+length >= bLength) {
+        System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length + (1+10)], 0, bLength);
+    }
+       System.arraycopy(this.source, this.startPosition, this.withoutUnicodeBuffer, 1, length);    
+}
+public void unicodeStoreAt(int pos) {
+    if (this.withoutUnicodeBuffer == null) this.withoutUnicodeBuffer = new char[10];
+    int length = this.withoutUnicodeBuffer.length;
+    if (pos == length) {
+        System.arraycopy(this.withoutUnicodeBuffer, 0, this.withoutUnicodeBuffer = new char[length * 2], 0, length);
+    }
+       this.withoutUnicodeBuffer[pos] = this.currentCharacter;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java b/src/java/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
new file mode 100644 (file)
index 0000000..c05ff33
--- /dev/null
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.compiler.parser;
+/**
+ * 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. 
+ * The mirror implementation is using the backward compatible ITerminalSymbols constant 
+ * 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. 
+ * 
+ * Disclaimer : These constant values are generated automatically using a Java 
+ * grammar, therefore their actual values are subject to change if new keywords 
+ * were added to the language (for instance, 'assert' is a keyword in 1.4).
+ */
+public interface TerminalTokens {
+
+       // special tokens not part of grammar - not autogenerated
+       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;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java b/src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/DiagnoseParser.java
new file mode 100644 (file)
index 0000000..58e0506
--- /dev/null
@@ -0,0 +1,2216 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.parser.ParserBasicInformation;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+
+public class DiagnoseParser implements ParserBasicInformation, TerminalTokens {
+       private static final boolean DEBUG = false;
+       
+       private static final String EMPTY_STRING = ""; //$NON-NLS-1$
+       private static final int STACK_INCREMENT = 256;
+       
+//     private static final int ERROR_CODE = 1;
+       private static final int BEFORE_CODE = 2;
+       private static final int INSERTION_CODE = 3;
+       private static final int INVALID_CODE = 4;
+       private static final int SUBSTITUTION_CODE = 5;
+       private static final int DELETION_CODE = 6;
+       private static final int MERGE_CODE = 7;
+       private static final int MISPLACED_CODE = 8;
+       private static final int SCOPE_CODE = 9;
+       private static final int SECONDARY_CODE = 10;
+       private static final int EOF_CODE = 11;
+
+       private static final int BUFF_UBOUND  = 31;
+       private static final int BUFF_SIZE    = 32;
+       private static final int MAX_DISTANCE = 30;
+       private static final int MIN_DISTANCE = 3;
+       
+       private LexStream lexStream;
+       private int errorToken;
+       private int errorTokenStart;
+       
+       private int currentToken = 0;
+       
+       private int stackLength;
+       private int stateStackTop;
+       private int[] stack;
+       
+       private int[] locationStack;
+       private int[] locationStartStack;
+       
+       private int tempStackTop;
+       private int[] tempStack;
+       
+       private int prevStackTop;
+       private int[] prevStack;
+       private int nextStackTop;
+       private int[] nextStack;
+       
+       private int scopeStackTop;
+    private int[] scopeIndex;
+    private int[] scopePosition;
+       
+       int[] list = new int[NUM_SYMBOLS + 1];
+       int[] buffer = new int[BUFF_SIZE];
+       
+       private static final int NIL = -1;
+       int[] stateSeen;
+       
+       int statePoolTop;
+       StateInfo[] statePool;
+       
+       private Parser parser;
+       
+       private class RepairCandidate {
+               public int symbol;
+               public int location;
+               
+               public RepairCandidate(){
+                       this.symbol = 0;
+                       this.location = 0;
+               }
+       }
+       
+       private class PrimaryRepairInfo {
+               public int distance;
+               public int misspellIndex;
+               public int code;
+               public int bufferPosition;
+               public int symbol;
+               
+               public PrimaryRepairInfo(){
+                       this.distance = 0;
+                       this.misspellIndex = 0;
+                       this.code = 0;
+                       this.bufferPosition = 0;
+                       this.symbol = 0;
+               }
+               
+               public PrimaryRepairInfo copy(){
+                       PrimaryRepairInfo c = new PrimaryRepairInfo();
+                       c.distance = this.distance;
+                       c.misspellIndex = this.misspellIndex;
+                       c.code = this.code;
+                       c.bufferPosition = this .bufferPosition;
+                       c.symbol = this.symbol;
+                       return c;
+                       
+               }
+       }
+       
+       private class SecondaryRepairInfo {
+               public int code;
+               public int distance;
+               public int bufferPosition;
+               public int stackPosition;
+               public int numDeletions;
+               public int symbol;
+
+               boolean recoveryOnNextStack;
+       } 
+       
+       private class StateInfo {
+           int state;
+           int next;
+           
+           public StateInfo(int state, int next){
+               this.state = state;
+               this.next = next;
+           }
+       }
+
+       public DiagnoseParser(Parser parser, int firstToken, int start, int end) {
+               this(parser, firstToken, start, end, new int[0], new int[0], new int[0]);
+       }
+
+       public DiagnoseParser(Parser parser, int firstToken, int start, int end, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip) {
+               this.parser = parser;
+               this.lexStream = new LexStream(BUFF_SIZE, parser.scanner, intervalStartToSkip, intervalEndToSkip, intervalFlagsToSkip, firstToken, start, end);
+       }
+       
+       private ProblemReporter problemReporter(){
+               return parser.problemReporter();
+       }
+
+       private void reallocateStacks() {
+               int old_stack_length = stackLength;
+
+               stackLength += STACK_INCREMENT;
+
+               if(old_stack_length == 0){
+                       stack = new int[stackLength];
+                       locationStack = new int[stackLength];
+                       locationStartStack = new int[stackLength];
+                       tempStack = new int[stackLength];
+                       prevStack = new int[stackLength];
+                       nextStack = new int[stackLength];
+                       scopeIndex = new int[stackLength];
+                       scopePosition = new int[stackLength];
+               } else {
+                       System.arraycopy(stack, 0, stack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(locationStack, 0, locationStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(locationStartStack, 0, locationStartStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(tempStack, 0, tempStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(prevStack, 0, prevStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(nextStack, 0, nextStack = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(scopeIndex, 0, scopeIndex = new int[stackLength], 0, old_stack_length);
+                       System.arraycopy(scopePosition, 0, scopePosition = new int[stackLength], 0, old_stack_length);
+               }
+               return;
+       }
+
+
+       public void diagnoseParse() {
+               lexStream.reset();
+
+               currentToken = lexStream.getToken();
+
+               int prev_pos;
+               int pos;
+               int next_pos;
+               int act = START_STATE;
+
+               reallocateStacks();
+
+               //
+               // Start parsing
+               //
+               stateStackTop = 0;
+               stack[stateStackTop] = act;
+
+               int tok = lexStream.kind(currentToken);
+               locationStack[stateStackTop] = currentToken;
+               locationStartStack[stateStackTop] = lexStream.start(currentToken);
+               
+               boolean forceRecoveryAfterLBracketMissing = false;
+//             int forceRecoveryToken = -1;
+
+               //
+               // Process a terminal
+               //
+               do {
+                       //
+                       // Synchronize state stacks and update the location stack
+                       //
+                       prev_pos = -1;
+                       prevStackTop = -1;
+
+                       next_pos = -1;
+                       nextStackTop = -1;
+
+                       pos = stateStackTop;
+                       tempStackTop = stateStackTop - 1;
+                       for (int i = 0; i <= stateStackTop; i++)
+                               tempStack[i] = stack[i];
+
+                       act = Parser.tAction(act, tok);
+                       //
+                       // When a reduce action is encountered, we compute all REDUCE
+                       // and associated goto actions induced by the current token.
+                       // Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is
+                       // computed...
+                       //
+                       while (act <= NUM_RULES) {
+                               do {
+                                       tempStackTop -= (Parser.rhs[act]-1);
+                                       act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]);
+                               } while(act <= NUM_RULES);
+                               //
+                               // ... Update the maximum useful position of the
+                               // (STATE_)STACK, push goto state into stack, and
+                               // compute next action on current symbol ...
+                               //
+                               if (tempStackTop + 1 >= stackLength)
+                                       reallocateStacks();
+                               pos = pos < tempStackTop ? pos : tempStackTop;
+                               tempStack[tempStackTop + 1] = act;
+                               act = Parser.tAction(act, tok);
+                       }
+
+                       //
+                       // At this point, we have a shift, shift-reduce, accept or error
+                       // action.  STACK contains the configuration of the state stack
+                       // prior to executing any action on curtok. next_stack contains
+                       // the configuration of the state stack after executing all
+                       // reduce actions induced by curtok.  The variable pos indicates
+                       // the highest position in STACK that is still useful after the
+                       // reductions are executed.
+                       //
+                       while(act > ERROR_ACTION || act < ACCEPT_ACTION) { // SHIFT-REDUCE action or SHIFT action ?
+                               nextStackTop = tempStackTop + 1;
+                               for (int i = next_pos + 1; i <= nextStackTop; i++)
+                                       nextStack[i] = tempStack[i];
+
+                               for (int i = pos + 1; i <= nextStackTop; i++) {
+                                       locationStack[i] = locationStack[stateStackTop];
+                                       locationStartStack[i] = locationStartStack[stateStackTop];
+                               }
+
+                               //
+                               // If we have a shift-reduce, process it as well as
+                               // the goto-reduce actions that follow it.
+                               //
+                               if (act > ERROR_ACTION) {
+                                       act -= ERROR_ACTION;
+                                       do {
+                                               nextStackTop -= (Parser.rhs[act]-1);
+                                               act = Parser.ntAction(nextStack[nextStackTop], Parser.lhs[act]);
+                                       } while(act <= NUM_RULES);
+                                       pos = pos < nextStackTop ? pos : nextStackTop;
+                               }
+
+                               if (nextStackTop + 1 >= stackLength)
+                                       reallocateStacks();
+
+                               tempStackTop = nextStackTop;
+                               nextStack[++nextStackTop] = act;
+                               next_pos = nextStackTop;
+
+                               //
+                               // Simulate the parser through the next token without
+                               // destroying STACK or next_stack.
+                               //
+                               currentToken = lexStream.getToken();
+                               tok = lexStream.kind(currentToken);
+                               act = Parser.tAction(act, tok);
+                               while(act <= NUM_RULES) {
+                                       //
+                                       // ... Process all goto-reduce actions following
+                                       // reduction, until a goto action is computed ...
+                                       //
+                                       do {
+                                               int lhs_symbol = Parser.lhs[act];
+                                               if(DEBUG) {
+                                                       System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]);
+                                               }
+                                               tempStackTop -= (Parser.rhs[act]-1);
+                                               act = (tempStackTop > next_pos
+                                                                  ? tempStack[tempStackTop]
+                                                                  : nextStack[tempStackTop]);
+                                               act = Parser.ntAction(act, lhs_symbol);
+                                       }   while(act <= NUM_RULES);
+
+                                       //
+                                       // ... Update the maximum useful position of the
+                                       // (STATE_)STACK, push GOTO state into stack, and
+                                       // compute next action on current symbol ...
+                                       //
+                                       if (tempStackTop + 1 >= stackLength)
+                                               reallocateStacks();
+
+                                       next_pos = next_pos < tempStackTop ? next_pos : tempStackTop;
+                                       tempStack[tempStackTop + 1] = act;
+                                       act = Parser.tAction(act, tok);
+                               }
+
+//                             if((tok != TokenNameRBRACE || (forceRecoveryToken != currentToken && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0))
+//                                     && (lexStream.flags(currentToken) & LexStream.IS_AFTER_JUMP) !=0) {
+//                                     act = ERROR_ACTION;
+//                                     if(forceRecoveryToken != currentToken
+//                                             && (lexStream.flags(currentToken) & LexStream.LBRACE_MISSING) != 0) {
+//                                             forceRecoveryAfterLBracketMissing = true;
+//                                             forceRecoveryToken = currentToken;
+//                                     }
+//                             }
+                               
+                               //
+                               // No error was detected, Read next token into
+                               // PREVTOK element, advance CURTOK pointer and
+                               // update stacks.
+                               //
+                               if (act != ERROR_ACTION) {
+                                       prevStackTop = stateStackTop;
+                                       for (int i = prev_pos + 1; i <= prevStackTop; i++)
+                                               prevStack[i] = stack[i];
+                                       prev_pos = pos;
+
+                                       stateStackTop = nextStackTop;
+                                       for (int i = pos + 1; i <= stateStackTop; i++)
+                                               stack[i] = nextStack[i];
+                                       locationStack[stateStackTop] = currentToken;
+                                       locationStartStack[stateStackTop] = lexStream.start(currentToken);
+                                       pos = next_pos;
+                               }
+                       }
+
+                       //
+                       // At this stage, either we have an ACCEPT or an ERROR
+                       // action.
+                       //
+                       if (act == ERROR_ACTION) {
+                               //
+                               // An error was detected.
+                               //
+                               RepairCandidate candidate = errorRecovery(currentToken, forceRecoveryAfterLBracketMissing);
+                               
+                               forceRecoveryAfterLBracketMissing = false;
+                               
+                               if(parser.reportOnlyOneSyntaxError) {
+                                       return;
+                               }
+                               
+                               if(this.parser.problemReporter().options.maxProblemsPerUnit < this.parser.compilationUnit.compilationResult.problemCount) {
+                                       return;
+                               }
+
+                               act = stack[stateStackTop];
+
+                               //
+                               // If the recovery was successful on a nonterminal candidate,
+                               // parse through that candidate and "read" the next token.
+                               //
+                               if (candidate.symbol == 0) {
+                                       break;
+                               } else if (candidate.symbol > NT_OFFSET) {
+                                       int lhs_symbol = candidate.symbol - NT_OFFSET;
+                                       if(DEBUG) {
+                                               System.out.println(Parser.name[Parser.non_terminal_index[lhs_symbol]]);
+                                       }
+                                       act = Parser.ntAction(act, lhs_symbol);
+                                       while(act <= NUM_RULES) {
+                                               stateStackTop -= (Parser.rhs[act]-1);
+                                               act = Parser.ntAction(stack[stateStackTop], Parser.lhs[act]);
+                                       }
+                                       stack[++stateStackTop] = act;
+                                       currentToken = lexStream.getToken();
+                                       tok = lexStream.kind(currentToken);
+                                       locationStack[stateStackTop] = currentToken;
+                                       locationStartStack[stateStackTop] = lexStream.start(currentToken);
+                               } else {
+                                       tok = candidate.symbol;
+                                       locationStack[stateStackTop] = candidate.location;
+                                       locationStartStack[stateStackTop] = lexStream.start(candidate.location);
+                               }
+                       }
+               } while (act != ACCEPT_ACTION);
+
+               return;
+       }
+
+       //
+//             This routine is invoked when an error is encountered.  It
+//        tries to diagnose the error and recover from it.  If it is
+//        successful, the state stack, the current token and the buffer
+//        are readjusted; i.e., after a successful recovery,
+//        state_stack_top points to the location in the state stack
+//        that contains the state on which to recover; curtok
+//        identifies the symbol on which to recover.
+//
+//        Up to three configurations may be available when this routine
+//        is invoked. PREV_STACK may contain the sequence of states
+//        preceding any action on prevtok, STACK always contains the
+//        sequence of states preceding any action on curtok, and
+//        NEXT_STACK may contain the sequence of states preceding any
+//        action on the successor of curtok.
+//
+       private RepairCandidate errorRecovery(int error_token, boolean forcedError) {
+               this.errorToken = error_token;
+               this.errorTokenStart = lexStream.start(error_token);
+               
+               int prevtok = lexStream.previous(error_token);
+               int prevtokKind = lexStream.kind(prevtok);
+               
+               if(forcedError) {
+                       int name_index = Parser.terminal_index[TokenNameLBRACE];
+
+                       reportError(INSERTION_CODE, name_index, prevtok, prevtok);
+                       
+                       RepairCandidate candidate = new RepairCandidate();
+                       candidate.symbol = TokenNameLBRACE;
+                       candidate.location = error_token;
+                       lexStream.reset(error_token);
+                       
+                       stateStackTop = nextStackTop;
+                       for (int j = 0; j <= stateStackTop; j++) {
+                               stack[j] = nextStack[j];
+                       }
+                       locationStack[stateStackTop] = error_token;
+                       locationStartStack[stateStackTop] = lexStream.start(error_token);
+                       
+                       return candidate;
+               }
+
+               //
+               // Try primary phase recoveries. If not successful, try secondary
+               // phase recoveries.  If not successful and we are at end of the
+               // file, we issue the end-of-file error and quit. Otherwise, ...
+               //
+               RepairCandidate candidate = primaryPhase(error_token);
+               if (candidate.symbol != 0) {
+                       return candidate;
+               }
+
+               candidate = secondaryPhase(error_token);
+               if (candidate.symbol != 0) {
+                       return candidate;
+               }
+
+               if (lexStream.kind(error_token) == EOFT_SYMBOL) {
+                       reportError(EOF_CODE,
+                                               Parser.terminal_index[EOFT_SYMBOL],
+                                               prevtok,
+                                               prevtok);
+                       candidate.symbol = 0;
+                       candidate.location = error_token;
+                       return candidate;
+               }
+
+               //
+               // At this point, primary and (initial attempt at) secondary
+               // recovery did not work.  We will now get into "panic mode" and
+               // keep trying secondary phase recoveries until we either find
+               // a successful recovery or have consumed the remaining input
+               // tokens.
+               //
+               while(lexStream.kind(buffer[BUFF_UBOUND]) != EOFT_SYMBOL) {
+                       candidate = secondaryPhase(buffer[MAX_DISTANCE - MIN_DISTANCE + 2]);
+                       if (candidate.symbol != 0) {
+                               return candidate;
+                       }
+               }
+
+               //
+               // We reached the end of the file while panicking. Delete all
+               // remaining tokens in the input.
+               //
+               int i;
+               for (i = BUFF_UBOUND; lexStream.kind(buffer[i]) == EOFT_SYMBOL; i--){/*empty*/}
+
+               reportError(DELETION_CODE,
+                                       Parser.terminal_index[prevtokKind],//Parser.terminal_index[lexStream.kind(prevtok)],
+                                       error_token,
+                                       buffer[i]);
+
+               candidate.symbol = 0;
+               candidate.location = buffer[i];
+
+               return candidate;
+       }
+
+//
+//        This function tries primary and scope recovery on each
+//        available configuration.  If a successful recovery is found
+//        and no secondary phase recovery can do better, a diagnosis is
+//        issued, the configuration is updated and the function returns
+//        "true".  Otherwise, it returns "false".
+//
+       private RepairCandidate primaryPhase(int error_token) {
+               PrimaryRepairInfo repair = new PrimaryRepairInfo();
+               RepairCandidate candidate = new RepairCandidate();
+
+               //
+               // Initialize the buffer.
+               //
+               int i = (nextStackTop >= 0 ? 3 : 2);
+               buffer[i] = error_token;
+
+               for (int j = i; j > 0; j--)
+                       buffer[j - 1] = lexStream.previous(buffer[j]);
+
+               for (int k = i + 1; k < BUFF_SIZE; k++)
+                       buffer[k] = lexStream.next(buffer[k - 1]);
+
+               //
+               // If NEXT_STACK_TOP > 0 then the parse was successful on CURTOK
+               // and the error was detected on the successor of CURTOK. In
+               // that case, first check whether or not primary recovery is
+               // possible on next_stack ...
+               //
+               if (nextStackTop >= 0) {
+                       repair.bufferPosition = 3;
+                       repair = checkPrimaryDistance(nextStack, nextStackTop, repair);
+               }
+
+               //
+               // ... Next, try primary recovery on the current token...
+               //
+               PrimaryRepairInfo new_repair = repair.copy();
+
+               new_repair.bufferPosition = 2;
+               new_repair = checkPrimaryDistance(stack, stateStackTop, new_repair);
+               if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) {
+                       repair = new_repair;
+               }
+
+               //
+               // Finally, if prev_stack_top >= 0 then try primary recovery on
+               // the prev_stack configuration.
+               //
+               
+               if (prevStackTop >= 0) {
+                       new_repair = repair.copy();
+                       new_repair.bufferPosition = 1;
+                       new_repair = checkPrimaryDistance(prevStack,prevStackTop, new_repair);
+                       if (new_repair.distance > repair.distance || new_repair.misspellIndex > repair.misspellIndex) {
+                               repair = new_repair;
+                       }
+               }
+
+               //
+               // Before accepting the best primary phase recovery obtained,
+               // ensure that we cannot do better with a similar secondary
+               // phase recovery.
+               //
+               if (nextStackTop >= 0) {// next_stack available
+                       if (secondaryCheck(nextStack,nextStackTop,3,repair.distance)) {
+                               return candidate;
+                       }
+               }
+               else if (secondaryCheck(stack, stateStackTop, 2, repair.distance)) {
+                       return candidate;
+               }
+
+               //
+               // First, adjust distance if the recovery is on the error token;
+               // it is important that the adjustment be made here and not at
+               // each primary trial to prevent the distance tests from being
+               // biased in favor of deferred recoveries which have access to
+               // more input tokens...
+               //
+               repair.distance = repair.distance - repair.bufferPosition + 1;
+
+               //
+               // ...Next, adjust the distance if the recovery is a deletion or
+               // (some form of) substitution...
+               //
+               if (repair.code == INVALID_CODE      ||
+                       repair.code == DELETION_CODE     ||
+                       repair.code == SUBSTITUTION_CODE ||
+                       repair.code == MERGE_CODE) {
+                        repair.distance--;
+               }
+
+               //
+               // ... After adjustment, check if the most successful primary
+               // recovery can be applied.  If not, continue with more radical
+               // recoveries...
+               //
+               if (repair.distance < MIN_DISTANCE) {
+                       return candidate;
+               }
+
+               //
+               // When processing an insertion error, if the token preceeding
+               // the error token is not available, we change the repair code
+               // into a BEFORE_CODE to instruct the reporting routine that it
+               // indicates that the repair symbol should be inserted before
+               // the error token.
+               //
+               if (repair.code == INSERTION_CODE) {
+                       if (buffer[repair.bufferPosition - 1] == 0) {
+                               repair.code = BEFORE_CODE;
+                       }
+               }
+
+               //
+               // Select the proper sequence of states on which to recover,
+               // update stack accordingly and call diagnostic routine.
+               //
+               if (repair.bufferPosition == 1) {
+                       stateStackTop = prevStackTop;
+                       for (int j = 0; j <= stateStackTop; j++) {
+                               stack[j] = prevStack[j];
+                       }
+               } else if (nextStackTop >= 0 && repair.bufferPosition >= 3) {
+                       stateStackTop = nextStackTop;
+                       for (int j = 0; j <= stateStackTop; j++) {
+                               stack[j] = nextStack[j];
+                       }
+                       locationStack[stateStackTop] = buffer[3];
+                       locationStartStack[stateStackTop] = lexStream.start(buffer[3]);
+               }
+
+               return primaryDiagnosis(repair);
+       }
+
+
+//
+//                This function checks whether or not a given state has a
+//        candidate, whose string representaion is a merging of the two
+//        tokens at positions buffer_position and buffer_position+1 in
+//        the buffer.  If so, it returns the candidate in question;
+//        otherwise it returns 0.
+//
+       private int mergeCandidate(int state, int buffer_position) {
+               char[] name1 = lexStream.name(buffer[buffer_position]);
+               char[] name2 = lexStream.name(buffer[buffer_position + 1]);
+               
+               int len  = name1.length + name2.length;
+
+               char[] str = CharOperation.concat(name1, name2);
+
+               for (int k = Parser.asi(state); Parser.asr[k] != 0; k++) {
+                       int l = Parser.terminal_index[Parser.asr[k]];
+
+                       if (len == Parser.name[l].length()) {
+                               char[] name = Parser.name[l].toCharArray();
+
+                               if (CharOperation.equals(str, name, false)) {
+                                       return Parser.asr[k];
+                               }
+                       }
+               }
+
+               return 0;
+       }
+
+
+//
+//        This procedure takes as arguments a parsing configuration
+//        consisting of a state stack (stack and stack_top) and a fixed
+//        number of input tokens (starting at buffer_position) in the
+//        input BUFFER; and some reference arguments: repair_code,
+//        distance, misspell_index, candidate, and stack_position
+//        which it sets based on the best possible recovery that it
+//        finds in the given configuration.  The effectiveness of a
+//        a repair is judged based on two criteria:
+//
+//              1) the number of tokens that can be parsed after the repair
+//                     is applied: distance.
+//              2) how close to perfection is the candidate that is chosen:
+//                     misspell_index.
+//        When this procedure is entered, distance, misspell_index and
+//        repair_code are assumed to be initialized.
+//
+       private PrimaryRepairInfo checkPrimaryDistance(int stck[], int stack_top, PrimaryRepairInfo repair) {
+               int i, j, k, next_state, max_pos, act, root, symbol, tok;
+
+               //
+           //  First, try scope and manual recovery.
+           //
+           PrimaryRepairInfo scope_repair = scopeTrial(stck, stack_top, repair.copy());
+           if (scope_repair.distance > repair.distance)
+               repair = scope_repair;
+               
+               //
+               //  Next, try merging the error token with its successor.
+               //
+           if(buffer[repair.bufferPosition] != 0 && buffer[repair.bufferPosition + 1] != 0) {// do not merge the first token
+                       symbol = mergeCandidate(stck[stack_top], repair.bufferPosition);
+                       if (symbol != 0) {
+                               j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+2);
+                               if ((j > repair.distance) || (j == repair.distance && repair.misspellIndex < 10)) {
+                                       repair.misspellIndex = 10;
+                                       repair.symbol = symbol;
+                                       repair.distance = j;
+                                       repair.code = MERGE_CODE;
+                               }
+                       }
+           }
+
+               //
+               // Next, try deletion of the error token.
+               //
+               j = parseCheck(
+                               stck,
+                               stack_top,
+                               lexStream.kind(buffer[repair.bufferPosition + 1]),
+                               repair.bufferPosition + 2);
+               if (lexStream.kind(buffer[repair.bufferPosition]) == EOLT_SYMBOL &&
+                       lexStream.afterEol(buffer[repair.bufferPosition+1])) {
+                        k = 10;
+               } else {
+                       k = 0;
+               }
+               if (j > repair.distance || (j == repair.distance && k > repair.misspellIndex)) {
+                       repair.misspellIndex = k;
+                       repair.code = DELETION_CODE;
+                       repair.distance = j;
+               }
+
+               //
+               // Update the error configuration by simulating all reduce and
+               // goto actions induced by the error token. Then assign the top
+               // most state of the new configuration to next_state.
+               //
+               next_state = stck[stack_top];
+               max_pos = stack_top;
+               tempStackTop = stack_top - 1;
+
+               tok = lexStream.kind(buffer[repair.bufferPosition]);
+               lexStream.reset(buffer[repair.bufferPosition + 1]);
+               act = Parser.tAction(next_state, tok);
+               while(act <= NUM_RULES) {
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               symbol = Parser.lhs[act];
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, symbol);
+                       } while(act <= NUM_RULES);
+                       max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                       tempStack[tempStackTop + 1] = act;
+                       next_state = act;
+                       act = Parser.tAction(next_state, tok);
+               }
+
+               //
+               //  Next, place the list of candidates in proper order.
+               //
+               root = 0;
+               for (i = Parser.asi(next_state); Parser.asr[i] != 0; i++) {
+                       symbol = Parser.asr[i];
+                       if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL) {
+                               if (root == 0) {
+                                       list[symbol] = symbol;
+                               } else {
+                                       list[symbol] = list[root];
+                                       list[root] = symbol;
+                               }
+                               root = symbol;
+                       }
+               }
+
+               if (stck[stack_top] != next_state) {
+                       for (i = Parser.asi(stck[stack_top]); Parser.asr[i] != 0; i++) {
+                               symbol = Parser.asr[i];
+                               if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL && list[symbol] == 0) {
+                                       if (root == 0) {
+                                               list[symbol] = symbol;
+                                       } else {
+                                               list[symbol] = list[root];
+                                               list[root] = symbol;
+                                       }
+                                       root = symbol;
+                               }
+                       }
+               }
+
+               i = list[root];
+               list[root] = 0;
+               root = i;
+
+               //
+               //  Next, try insertion for each possible candidate available in
+               // the current state, except EOFT and ERROR_SYMBOL.
+               //
+               symbol = root;
+               while(symbol != 0) {
+                       if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition])) {
+                               k = 10;
+                       } else {
+                               k = 0;
+                       }
+                       j = parseCheck(stck, stack_top, symbol, repair.bufferPosition);
+                       if (j > repair.distance) {
+                               repair.misspellIndex = k;
+                               repair.distance = j;
+                               repair.symbol = symbol;
+                               repair.code = INSERTION_CODE;
+                       } else if (j == repair.distance && k > repair.misspellIndex) {
+                               repair.misspellIndex = k;
+                               repair.distance = j;
+                               repair.symbol = symbol;
+                               repair.code = INSERTION_CODE;
+                       } else if (j == repair.distance && k == repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) {
+                               repair.misspellIndex = k;
+                               repair.distance = j;
+                               repair.symbol = symbol;
+                               repair.code = INSERTION_CODE;
+                       }
+
+                       symbol = list[symbol];
+               }
+
+               //
+               //  Next, Try substitution for each possible candidate available
+               // in the current state, except EOFT and ERROR_SYMBOL.
+               //
+               symbol = root;
+               
+               if(buffer[repair.bufferPosition] != 0) {// do not replace the first token
+                       while(symbol != 0) {
+                               if (symbol == EOLT_SYMBOL && lexStream.afterEol(buffer[repair.bufferPosition+1])) {
+                                       k = 10;
+                               } else {
+                                       k = misspell(symbol, buffer[repair.bufferPosition]);
+                               }
+                               j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1);
+                               if (j > repair.distance) {
+                                       repair.misspellIndex = k;
+                                       repair.distance = j;
+                                       repair.symbol = symbol;
+                                       repair.code = SUBSTITUTION_CODE;
+                               } else if (j == repair.distance && k > repair.misspellIndex) {
+                                       repair.misspellIndex = k;
+                                       repair.symbol = symbol;
+                                       repair.code = SUBSTITUTION_CODE;
+                               } else if (j == repair.distance && k > repair.misspellIndex && isBetterSymbol(symbol, repair.symbol)) {
+                                       repair.misspellIndex = k;
+                                       repair.symbol = symbol;
+                                       repair.code = SUBSTITUTION_CODE;
+                               }
+                               i = symbol;
+                               symbol = list[symbol];
+                               list[i] = 0;                             // reset element
+                       }
+               }
+
+
+               //
+               // Next, we try to insert a nonterminal candidate in front of the
+               // error token, or substituting a nonterminal candidate for the
+               // error token. Precedence is given to insertion.
+               //
+                for (i = Parser.nasi(stck[stack_top]); Parser.nasr[i] != 0; i++) {
+                        symbol = Parser.nasr[i] + NT_OFFSET;
+                        j = parseCheck(stck, stack_top, symbol, repair.bufferPosition+1);
+                        if (j > repair.distance) {
+                                repair.misspellIndex = 0;
+                                repair.distance = j;
+                                repair.symbol = symbol;
+                                repair.code = INVALID_CODE;
+                        }
+
+                        j = parseCheck(stck, stack_top, symbol, repair.bufferPosition);
+                        if ((j > repair.distance) || (j == repair.distance && repair.code == INVALID_CODE)) {
+                                repair.misspellIndex = 0;
+                                repair.distance = j;
+                                repair.symbol = symbol;
+                                repair.code = INSERTION_CODE;
+                        }
+                }
+
+               return repair;
+       }
+
+
+//
+//        This procedure is invoked to issue a diagnostic message and
+//        adjust the input buffer.  The recovery in question is either
+//        the insertion of one or more scopes, the merging of the error
+//        token with its successor, the deletion of the error token,
+//        the insertion of a single token in front of the error token
+//        or the substitution of another token for the error token.
+//
+       private RepairCandidate primaryDiagnosis(PrimaryRepairInfo repair) {
+               int name_index;
+
+               //
+               //  Issue diagnostic.
+               //
+               int prevtok = buffer[repair.bufferPosition - 1];
+               int     curtok  = buffer[repair.bufferPosition];
+
+               switch(repair.code) {
+                       case INSERTION_CODE:
+                       case BEFORE_CODE: {
+                               if (repair.symbol > NT_OFFSET)
+                                        name_index = getNtermIndex(stack[stateStackTop],
+                                                                                               repair.symbol,
+                                                                                               repair.bufferPosition);
+                               else name_index = getTermIndex(stack,
+                                                                                          stateStackTop,
+                                                                                          repair.symbol,
+                                                                                          repair.bufferPosition);
+
+                               int t = (repair.code == INSERTION_CODE ? prevtok : curtok);
+                               reportError(repair.code, name_index, t, t);
+                               break;
+                       }
+                       case INVALID_CODE: {
+                               name_index = getNtermIndex(stack[stateStackTop],
+                                                                                  repair.symbol,
+                                                                                  repair.bufferPosition + 1);
+                               reportError(repair.code, name_index, curtok, curtok);
+                               break;
+                       }
+                       case SUBSTITUTION_CODE: {
+                               if (repair.misspellIndex >= 6)
+                                       name_index = Parser.terminal_index[repair.symbol];
+                               else
+                               {
+                                       name_index = getTermIndex(stack, stateStackTop,
+                                                                                         repair.symbol,
+                                                                                         repair.bufferPosition + 1);
+                                       if (name_index != Parser.terminal_index[repair.symbol])
+                                               repair.code = INVALID_CODE;
+                               }
+                               reportError(repair.code, name_index, curtok, curtok);
+                               break;
+                       }
+                       case MERGE_CODE: {
+                               reportError(repair.code,
+                                                        Parser.terminal_index[repair.symbol],
+                                                        curtok,
+                                                        lexStream.next(curtok));
+                               break;
+                       }
+                       case SCOPE_CODE: {
+                   for (int i = 0; i < scopeStackTop; i++) {
+                       reportError(repair.code,
+                                   -scopeIndex[i],
+                                   locationStack[scopePosition[i]],
+                                   prevtok,
+                                   Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]);
+                   }
+       
+                   repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET;
+                   stateStackTop = scopePosition[scopeStackTop];
+                   reportError(repair.code,
+                               -scopeIndex[scopeStackTop],
+                               locationStack[scopePosition[scopeStackTop]],
+                               prevtok,
+                               getNtermIndex(stack[stateStackTop],
+                                             repair.symbol,
+                                             repair.bufferPosition)
+                              );
+                   break;
+               }
+                       default: {// deletion
+                               reportError(repair.code, Parser.terminal_index[ERROR_SYMBOL], curtok, curtok);
+                       }
+               }
+
+               //
+               //  Update buffer.
+               //
+               RepairCandidate candidate = new RepairCandidate();
+               switch (repair.code) {
+                       case INSERTION_CODE:
+                       case BEFORE_CODE:
+                       case SCOPE_CODE: {
+                               candidate.symbol = repair.symbol;
+                               candidate.location = buffer[repair.bufferPosition];
+                               lexStream.reset(buffer[repair.bufferPosition]);
+                               break;
+                       }
+                       case INVALID_CODE:
+                       case SUBSTITUTION_CODE: {
+                               candidate.symbol = repair.symbol;
+                               candidate.location = buffer[repair.bufferPosition];
+                               lexStream.reset(buffer[repair.bufferPosition + 1]);
+                               break;
+                       }
+                       case MERGE_CODE: {
+                               candidate.symbol = repair.symbol;
+                               candidate.location = buffer[repair.bufferPosition];
+                               lexStream.reset(buffer[repair.bufferPosition + 2]);
+                               break;
+                       }
+                       default: {// deletion
+                               candidate.location = buffer[repair.bufferPosition + 1];
+                               candidate.symbol =
+                                                 lexStream.kind(buffer[repair.bufferPosition + 1]);
+                               lexStream.reset(buffer[repair.bufferPosition + 2]);
+                               break;
+                       }
+               }
+
+               return candidate;
+       }
+
+
+//
+//        This function takes as parameter an integer STACK_TOP that
+//        points to a STACK element containing the state on which a
+//        primary recovery will be made; the terminal candidate on which
+//        to recover; and an integer: buffer_position, which points to
+//        the position of the next input token in the BUFFER.  The
+//        parser is simulated until a shift (or shift-reduce) action
+//        is computed on the candidate.  Then we proceed to compute the
+//        the name index of the highest level nonterminal that can
+//        directly or indirectly produce the candidate.
+//
+       private int getTermIndex(int stck[], int stack_top, int tok, int buffer_position) {
+               //
+               // Initialize stack index of temp_stack and initialize maximum
+               // position of state stack that is still useful.
+               //
+               int act = stck[stack_top],
+                       max_pos = stack_top,
+                       highest_symbol = tok;
+
+               tempStackTop = stack_top - 1;
+
+               //
+               // Compute all reduce and associated actions induced by the
+               // candidate until a SHIFT or SHIFT-REDUCE is computed. ERROR
+               // and ACCEPT actions cannot be computed on the candidate in
+               // this context, since we know that it is suitable for recovery.
+               //
+               lexStream.reset(buffer[buffer_position]);
+               act = Parser.tAction(act, tok);
+               while(act <= NUM_RULES) {
+                       //
+                       // Process all goto-reduce actions following reduction,
+                       // until a goto action is computed ...
+                       //
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               int lhs_symbol = Parser.lhs[act];
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, lhs_symbol);
+                       } while(act <= NUM_RULES);
+
+                       //
+                       // Compute new maximum useful position of (STATE_)stack,
+                       // push goto state into the stack, and compute next
+                       // action on candidate ...
+                       //
+                       max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               //
+               // At this stage, we have simulated all actions induced by the
+               // candidate and we are ready to shift or shift-reduce it. First,
+               // set tok and next_ptr appropriately and identify the candidate
+               // as the initial highest_symbol. If a shift action was computed
+               // on the candidate, update the stack and compute the next
+               // action. Next, simulate all actions possible on the next input
+               // token until we either have to shift it or are about to reduce
+               // below the initial starting point in the stack (indicated by
+               // max_pos as computed in the previous loop).  At that point,
+               // return the highest_symbol computed.
+               //
+               tempStackTop++; // adjust top of stack to reflect last goto
+                                                 // next move is shift or shift-reduce.
+               int threshold = tempStackTop;
+
+               tok = lexStream.kind(buffer[buffer_position]);
+               lexStream.reset(buffer[buffer_position + 1]);
+
+               if (act > ERROR_ACTION) {  // shift-reduce on candidate?
+                       act -= ERROR_ACTION;
+               } else {
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               while(act <= NUM_RULES) {
+                       //
+                       // Process all goto-reduce actions following reduction,
+                       // until a goto action is computed ...
+                       //
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+
+                               if (tempStackTop < threshold) {
+                                       return (highest_symbol > NT_OFFSET
+                                                ? Parser.non_terminal_index[highest_symbol - NT_OFFSET]
+                                                : Parser.terminal_index[highest_symbol]);
+                               }
+
+                               int lhs_symbol = Parser.lhs[act];
+                               if (tempStackTop == threshold)
+                                       highest_symbol = lhs_symbol + NT_OFFSET;
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, lhs_symbol);
+                       } while(act <= NUM_RULES);
+
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               return (highest_symbol > NT_OFFSET
+                                                        ? Parser.non_terminal_index[highest_symbol - NT_OFFSET]
+                                                        : Parser.terminal_index[highest_symbol]);
+       }
+
+//
+//        This function takes as parameter a starting state number:
+//        start, a nonterminal symbol, A (candidate), and an integer,
+//        buffer_position,  which points to the position of the next
+//        input token in the BUFFER.
+//        It returns the highest level non-terminal B such that
+//        B =>*rm A.  I.e., there does not exists a nonterminal C such
+//        that C =>+rm B. (Recall that for an LALR(k) grammar if
+//        C =>+rm B, it cannot be the case that B =>+rm C)
+//
+       private int getNtermIndex(int start, int sym, int buffer_position) {
+               int highest_symbol = sym - NT_OFFSET,
+                       tok = lexStream.kind(buffer[buffer_position]);
+               lexStream.reset(buffer[buffer_position + 1]);
+
+               //
+               // Initialize stack index of temp_stack and initialize maximum
+               // position of state stack that is still useful.
+               //
+               tempStackTop = 0;
+               tempStack[tempStackTop] = start;
+
+               int act = Parser.ntAction(start, highest_symbol);
+               if (act > NUM_RULES) { // goto action?
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               while(act <= NUM_RULES) {
+                       //
+                       // Process all goto-reduce actions following reduction,
+                       // until a goto action is computed ...
+                       //
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               if (tempStackTop < 0)
+                                       return Parser.non_terminal_index[highest_symbol];
+                               if (tempStackTop == 0)
+                                       highest_symbol = Parser.lhs[act];
+                               act = Parser.ntAction(tempStack[tempStackTop], Parser.lhs[act]);
+                       } while(act <= NUM_RULES);
+                       tempStack[tempStackTop + 1] = act;
+                       act = Parser.tAction(act, tok);
+               }
+
+               return Parser.non_terminal_index[highest_symbol];
+       }
+
+       private boolean isBetterSymbol(int symbol, int actualSymbol) {
+//             switch (actualSymbol) {
+//                     case TokenNameinterface :
+//                             if(symbol == TokenNameclass) {
+//                                     return true;
+//                             }
+//                             break;
+//             }
+               return false;
+       }
+
+//
+//                Check whether or not there is a high probability that a
+//        given string is a misspelling of another.
+//        Certain singleton symbols (such as ":" and ";") are also
+//        considered to be misspelling of each other.
+//
+       private int misspell(int sym, int tok) {
+               
+
+               //
+               //
+               //
+               char[] name = Parser.name[Parser.terminal_index[sym]].toCharArray();
+               int n = name.length;
+               char[] s1 = new char[n + 1];
+               for (int k = 0; k < n; k++) {
+                       char c = name[k];
+                       s1[k] = Character.toLowerCase(c);
+               }
+               s1[n] = '\0';
+
+               //
+               //
+               //
+               char[] tokenName = lexStream.name(tok);
+               int len = tokenName.length;
+               int m = len < MAX_NAME_LENGTH ? len : MAX_NAME_LENGTH;
+               char[] s2 = new char[m + 1];
+               for (int k = 0; k < m; k++) {
+                       char c = tokenName[k];
+                       s2[k] = Character.toLowerCase(c);
+               }
+               s2[m] = '\0';
+
+               //
+               //  Singleton mispellings:
+               //
+               //  ;      <---->     ,
+               //
+               //  ;      <---->     :
+               //
+               //  .      <---->     ,
+               //
+               //  '      <---->     "
+               //
+               //
+               if (n == 1  &&  m == 1) {
+                       if ((s1[0] == ';'  &&  s2[0] == ',')  ||
+                               (s1[0] == ','  &&  s2[0] == ';')  ||
+                               (s1[0] == ';'  &&  s2[0] == ':')  ||
+                               (s1[0] == ':'  &&  s2[0] == ';')  ||
+                               (s1[0] == '.'  &&  s2[0] == ',')  ||
+                               (s1[0] == ','  &&  s2[0] == '.')  ||
+                               (s1[0] == '\'' &&  s2[0] == '\"')  ||
+                               (s1[0] == '\"'  &&  s2[0] == '\'')) {
+                                       return 3;
+                       }
+               }
+
+               //
+               // Scan the two strings. Increment "match" count for each match.
+               // When a transposition is encountered, increase "match" count
+               // by two but count it as an error. When a typo is found, skip
+               // it and count it as an error. Otherwise we have a mismatch; if
+               // one of the strings is longer, increment its index, otherwise,
+               // increment both indices and continue.
+               //
+               // This algorithm is an adaptation of a boolean misspelling
+               // algorithm proposed by Juergen Uhl.
+               //
+               int count = 0;
+               int prefix_length = 0;
+               int num_errors = 0;
+
+               int i = 0;
+               int j = 0;
+               while ((i < n)  &&  (j < m)) {
+                       if (s1[i] == s2[j]) {
+                               count++;
+                               i++;
+                               j++;
+                               if (num_errors == 0) {
+                                       prefix_length++;
+                               }
+                       } else if (s1[i+1] == s2[j]  &&  s1[i] == s2[j+1]) {
+                               count += 2;
+                               i += 2;
+                               j += 2;
+                               num_errors++;
+                       } else if (s1[i+1] == s2[j+1]) {
+                               i++;
+                               j++;
+                               num_errors++;
+                       } else {
+                               if ((n - i) > (m - j)) {
+                                        i++;
+                               } else if ((m - j) > (n - i)) {
+                                        j++;
+                               } else {
+                                       i++;
+                                       j++;
+                               }
+                               num_errors++;
+                       }
+               }
+
+               if (i < n  ||  j < m)
+                       num_errors++;
+
+               if (num_errors > ((n < m ? n : m) / 6 + 1))
+                        count = prefix_length;
+
+               return(count * 10 / ((n < len ? len : n) + num_errors));
+       }
+       
+       private PrimaryRepairInfo scopeTrial(int stck[], int stack_top, PrimaryRepairInfo repair) {
+           stateSeen = new int[stackLength];
+           for (int i = 0; i < stackLength; i++)
+               stateSeen[i] = NIL;
+           
+           statePoolTop = 0;
+           statePool = new StateInfo[stackLength];
+       
+           scopeTrialCheck(stck, stack_top, repair, 0);
+       
+           stateSeen = null;
+           statePoolTop = 0;
+       
+           repair.code = SCOPE_CODE;
+           repair.misspellIndex = 10;
+       
+           return repair;
+       }
+       
+       private void scopeTrialCheck(int stck[], int stack_top, PrimaryRepairInfo repair, int indx) {
+               if(indx > 20) return; // avoid too much recursive call to improve performance
+               
+               int act = stck[stack_top];
+       
+           for (int i = stateSeen[stack_top]; i != NIL; i = statePool[i].next) {
+               if (statePool[i].state == act) return;
+           }
+
+           int old_state_pool_top = statePoolTop++;
+           if(statePoolTop >= statePool.length) {
+               System.arraycopy(statePool, 0, statePool = new StateInfo[statePoolTop * 2], 0, statePoolTop);
+           }
+           
+           statePool[old_state_pool_top] = new StateInfo(act, stateSeen[stack_top]);
+           stateSeen[stack_top] = old_state_pool_top;
+       
+           for (int i = 0; i < SCOPE_SIZE; i++) {
+               //
+               // Use the scope lookahead symbol to force all reductions
+               // inducible by that symbol.
+               //
+               act = stck[stack_top];
+               tempStackTop = stack_top - 1;
+               int max_pos = stack_top;
+               int tok = Parser.scope_la[i];
+               lexStream.reset(buffer[repair.bufferPosition]);
+               act = Parser.tAction(act, tok);
+               while(act <= NUM_RULES) {
+                   //
+                   // ... Process all goto-reduce actions following
+                   // reduction, until a goto action is computed ...
+                   //
+                   do  {
+                       tempStackTop -= (Parser.rhs[act]-1);
+                       int lhs_symbol = Parser.lhs[act];
+                       act =  (tempStackTop > max_pos
+                                   ?  tempStack[tempStackTop]
+                                   :  stck[tempStackTop]);
+                       act = Parser.ntAction(act, lhs_symbol);
+                   }  while(act <= NUM_RULES);
+                   if (tempStackTop + 1 >= stackLength)
+                       return;
+                   max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                   tempStack[tempStackTop + 1] = act;
+                   act = Parser.tAction(act, tok);
+               }
+       
+               //
+               // If the lookahead symbol is parsable, then we check
+               // whether or not we have a match between the scope
+               // prefix and the transition symbols corresponding to
+               // the states on top of the stack.
+               //
+               if (act != ERROR_ACTION) {
+                       int j, k;
+                   k = Parser.scope_prefix[i];
+                   for (j = tempStackTop + 1;
+                        j >= (max_pos + 1) &&
+                        Parser.in_symbol(tempStack[j]) == Parser.scope_rhs[k]; j--) {
+                        k++;
+                   }
+                   if (j == max_pos) {
+                       for (j = max_pos;
+                            j >= 1 && Parser.in_symbol(stck[j]) == Parser.scope_rhs[k];
+                            j--) {
+                           k++;
+                       }
+                   }
+                   //
+                   // If the prefix matches, check whether the state
+                   // newly exposed on top of the stack, (after the
+                   // corresponding prefix states are popped from the
+                   // stack), is in the set of "source states" for the
+                   // scope in question and that it is at a position
+                   // below the threshold indicated by MARKED_POS.
+                   //
+                   int marked_pos = (max_pos < stack_top ? max_pos + 1 : stack_top);
+                   if (Parser.scope_rhs[k] == 0 && j < marked_pos) { // match?
+                       int stack_position = j;
+                       for (j = Parser.scope_state_set[i];
+                            stck[stack_position] != Parser.scope_state[j] &&
+                            Parser.scope_state[j] != 0;
+                            j++){/*empty*/}
+                       //
+                       // If the top state is valid for scope recovery,
+                       // the left-hand side of the scope is used as
+                       // starting symbol and we calculate how far the
+                       // parser can advance within the forward context
+                       // after parsing the left-hand symbol.
+                       //
+                       if (Parser.scope_state[j] != 0) {     // state was found
+                           int previous_distance = repair.distance;
+                           int distance = parseCheck(stck,
+                                                 stack_position,
+                                                 Parser.scope_lhs[i]+NT_OFFSET,
+                                                 repair.bufferPosition);
+                           //
+                           // if the recovery is not successful, we
+                           // update the stack with all actions induced
+                           // by the left-hand symbol, and recursively
+                           // call SCOPE_TRIAL_CHECK to try again.
+                           // Otherwise, the recovery is successful. If
+                           // the new distance is greater than the
+                           // initial SCOPE_DISTANCE, we update
+                           // SCOPE_DISTANCE and set scope_stack_top to INDX
+                           // to indicate the number of scopes that are
+                           // to be applied for a succesful  recovery.
+                           // NOTE that this procedure cannot get into
+                           // an infinite loop, since each prefix match
+                           // is guaranteed to take us to a lower point
+                           // within the stack.
+                           //
+                           if ((distance - repair.bufferPosition + 1) < MIN_DISTANCE) {
+                               int top = stack_position;
+                               act = Parser.ntAction(stck[top], Parser.scope_lhs[i]);
+                               while(act <= NUM_RULES) {
+                                   top -= (Parser.rhs[act]-1);
+                                   act = Parser.ntAction(stck[top], Parser.lhs[act]);
+                               }
+                               top++;
+       
+                               j = act;
+                               act = stck[top];  // save
+                               stck[top] = j;    // swap
+                               scopeTrialCheck(stck, top, repair, indx+1);
+                               stck[top] = act; // restore
+                           } else if (distance > repair.distance) {
+                               scopeStackTop = indx;
+                               repair.distance = distance;
+                           }
+       
+                           if (lexStream.kind(buffer[repair.bufferPosition]) == EOFT_SYMBOL &&
+                               repair.distance == previous_distance) {
+                               scopeStackTop = indx;
+                               repair.distance = MAX_DISTANCE;
+                           }
+       
+                           //
+                           // If this scope recovery has beaten the
+                           // previous distance, then we have found a
+                           // better recovery (or this recovery is one
+                           // of a list of scope recoveries). Record
+                           // its information at the proper location
+                           // (INDX) in SCOPE_INDEX and SCOPE_STACK.
+                           //
+                           if (repair.distance > previous_distance) {
+                               scopeIndex[indx] = i;
+                               scopePosition[indx] = stack_position;
+                               return;
+                           }
+                       }
+                   }
+               }
+           }
+       }
+//
+//        This function computes the ParseCheck distance for the best
+//        possible secondary recovery for a given configuration that
+//        either deletes none or only one symbol in the forward context.
+//        If the recovery found is more effective than the best primary
+//        recovery previously computed, then the function returns true.
+//        Only misplacement, scope and manual recoveries are attempted;
+//        simple insertion or substitution of a nonterminal are tried
+//        in CHECK_PRIMARY_DISTANCE as part of primary recovery.
+//
+       private boolean secondaryCheck(int stck[], int stack_top, int buffer_position, int distance) {
+               int top, j;
+
+               for (top = stack_top - 1; top >= 0; top--) {
+                       j = parseCheck(stck, top,
+                                                  lexStream.kind(buffer[buffer_position]),
+                                                  buffer_position + 1);
+                       if (((j - buffer_position + 1) > MIN_DISTANCE) && (j > distance))
+                               return true;
+               }
+               
+               PrimaryRepairInfo repair = new PrimaryRepairInfo();
+           repair.bufferPosition = buffer_position + 1;
+           repair.distance = distance;
+           repair = scopeTrial(stck, stack_top, repair);
+           if ((repair.distance - buffer_position) > MIN_DISTANCE && repair.distance > distance)
+                return true;
+               return false;
+       }
+
+
+//
+//        Secondary_phase is a boolean function that checks whether or
+//        not some form of secondary recovery is applicable to one of
+//        the error configurations. First, if "next_stack" is available,
+//        misplacement and secondary recoveries are attempted on it.
+//        Then, in any case, these recoveries are attempted on "stack".
+//        If a successful recovery is found, a diagnosis is issued, the
+//        configuration is updated and the function returns "true".
+//        Otherwise, the function returns false.
+//
+       private RepairCandidate secondaryPhase(int error_token) {
+               SecondaryRepairInfo repair = new SecondaryRepairInfo();
+               SecondaryRepairInfo misplaced = new SecondaryRepairInfo();
+
+               RepairCandidate candidate = new RepairCandidate();
+
+               int i, j, k, top;
+               int     next_last_index = 0;
+               int     last_index;
+
+               candidate.symbol = 0;
+
+               repair.code = 0;
+               repair.distance = 0;
+               repair.recoveryOnNextStack = false;
+
+               misplaced.distance = 0;
+               misplaced.recoveryOnNextStack = false;
+
+               //
+               // If the next_stack is available, try misplaced and secondary
+               // recovery on it first.
+               //
+               if (nextStackTop >= 0) {
+                       int  save_location;
+
+                       buffer[2] = error_token;
+                       buffer[1] = lexStream.previous(buffer[2]);
+                       buffer[0] = lexStream.previous(buffer[1]);
+
+                       for (k = 3; k < BUFF_UBOUND; k++)
+                               buffer[k] = lexStream.next(buffer[k - 1]);
+
+                       buffer[BUFF_UBOUND] = lexStream.badtoken();// elmt not available
+
+                       //
+                       // If we are at the end of the input stream, compute the
+                       // index position of the first EOFT symbol (last useful
+                       // index).
+                       //
+                       for (next_last_index = MAX_DISTANCE - 1;
+                                next_last_index >= 1 &&
+                                lexStream.kind(buffer[next_last_index]) == EOFT_SYMBOL;
+                                next_last_index--){/*empty*/}
+                       next_last_index = next_last_index + 1;
+
+                       save_location = locationStack[nextStackTop];
+                       int save_location_start = locationStartStack[nextStackTop];
+                       locationStack[nextStackTop] = buffer[2];
+                       locationStartStack[nextStackTop] = lexStream.start(buffer[2]);
+                       misplaced.numDeletions = nextStackTop;
+                       misplaced = misplacementRecovery(nextStack, nextStackTop,
+                                                                                        next_last_index,
+                                                                                        misplaced, true);
+                       if (misplaced.recoveryOnNextStack)
+                               misplaced.distance++;
+
+                       repair.numDeletions = nextStackTop + BUFF_UBOUND;
+                       repair = secondaryRecovery(nextStack, nextStackTop,
+                                                                          next_last_index,
+                                                                          repair, true);
+                       if (repair.recoveryOnNextStack)
+                               repair.distance++;
+
+                       locationStack[nextStackTop] = save_location;
+                       locationStartStack[nextStackTop] = save_location_start;
+               } else {            // next_stack not available, initialize ...
+                       misplaced.numDeletions = stateStackTop;
+                       repair.numDeletions = stateStackTop + BUFF_UBOUND;
+               }
+
+               //
+               // Try secondary recovery on the "stack" configuration.
+               //
+               buffer[3] = error_token;
+
+               buffer[2] = lexStream.previous(buffer[3]);
+               buffer[1] = lexStream.previous(buffer[2]);
+               buffer[0] = lexStream.previous(buffer[1]);
+
+               for (k = 4; k < BUFF_SIZE; k++)
+                       buffer[k] = lexStream.next(buffer[k - 1]);
+
+               for (last_index = MAX_DISTANCE - 1;
+                        last_index >= 1 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL;
+                        last_index--){/*empty*/}
+               last_index++;
+
+               misplaced = misplacementRecovery(stack, stateStackTop,
+                                                                                last_index,
+                                                                                misplaced, false);
+
+               repair = secondaryRecovery(stack, stateStackTop,
+                                                                  last_index, repair, false);
+
+               //
+               // If a successful misplaced recovery was found, compare it with
+               // the most successful secondary recovery.  If the misplaced
+               // recovery either deletes fewer symbols or parse-checks further
+               // then it is chosen.
+               //
+               if (misplaced.distance > MIN_DISTANCE) {
+                       if (misplaced.numDeletions <= repair.numDeletions ||
+                          (misplaced.distance - misplaced.numDeletions) >=
+                          (repair.distance - repair.numDeletions)) {
+                               repair.code = MISPLACED_CODE;
+                               repair.stackPosition = misplaced.stackPosition;
+                               repair.bufferPosition = 2;
+                               repair.numDeletions = misplaced.numDeletions;
+                               repair.distance = misplaced.distance;
+                               repair.recoveryOnNextStack = misplaced.recoveryOnNextStack;
+                       }
+               }
+
+               //
+               // If the successful recovery was on next_stack, update: stack,
+               // buffer, location_stack and last_index.
+               //
+               if (repair.recoveryOnNextStack) {
+                       stateStackTop = nextStackTop;
+                       for (i = 0; i <= stateStackTop; i++)
+                               stack[i] = nextStack[i];
+
+                       buffer[2] = error_token;
+                       buffer[1] = lexStream.previous(buffer[2]);
+                       buffer[0] = lexStream.previous(buffer[1]);
+
+                       for (k = 3; k < BUFF_UBOUND; k++)
+                               buffer[k] = lexStream.next(buffer[k - 1]);
+
+                       buffer[BUFF_UBOUND] = lexStream.badtoken();// elmt not available
+
+                       locationStack[nextStackTop] = buffer[2];
+                       locationStartStack[nextStackTop] = lexStream.start(buffer[2]);
+                       last_index = next_last_index;
+               }
+
+           //
+           // Next, try scope recoveries after deletion of one, two, three,
+           // four ... buffer_position tokens from the input stream.
+           //
+           if (repair.code == SECONDARY_CODE || repair.code == DELETION_CODE) {
+               PrimaryRepairInfo scope_repair = new PrimaryRepairInfo();
+       
+               scope_repair.distance = 0;
+               for (scope_repair.bufferPosition = 2;
+                    scope_repair.bufferPosition <= repair.bufferPosition &&
+                    repair.code != SCOPE_CODE; scope_repair.bufferPosition++) {
+                   scope_repair = scopeTrial(stack, stateStackTop, scope_repair);
+                   j = (scope_repair.distance == MAX_DISTANCE
+                                               ? last_index
+                                               : scope_repair.distance);
+                   k = scope_repair.bufferPosition - 1;
+                   if ((j - k) > MIN_DISTANCE && (j - k) > (repair.distance - repair.numDeletions)) {
+                       repair.code = SCOPE_CODE;
+                       i = scopeIndex[scopeStackTop];       // upper bound
+                       repair.symbol = Parser.scope_lhs[i] + NT_OFFSET;
+                       repair.stackPosition = stateStackTop;
+                       repair.bufferPosition = scope_repair.bufferPosition;
+                   }
+               }
+           }
+       
+           //
+           // If no successful recovery is found and we have reached the
+           // end of the file, check whether or not scope recovery is
+           // applicable at the end of the file after discarding some
+           // states.
+           //
+           if (repair.code == 0 && lexStream.kind(buffer[last_index]) == EOFT_SYMBOL) {
+               PrimaryRepairInfo scope_repair = new PrimaryRepairInfo();
+       
+               scope_repair.bufferPosition = last_index;
+               scope_repair.distance = 0;
+               for (top = stateStackTop;
+                    top >= 0 && repair.code == 0; top--)
+               {
+                   scope_repair = scopeTrial(stack, top, scope_repair);
+                   if (scope_repair.distance > 0)
+                   {
+                       repair.code = SCOPE_CODE;
+                       i = scopeIndex[scopeStackTop];    // upper bound
+                       repair.symbol = Parser.scope_lhs[i] + NT_OFFSET;
+                       repair.stackPosition = top;
+                       repair.bufferPosition = scope_repair.bufferPosition;
+                   }
+               }
+           }
+
+               //
+               // If a successful repair was not found, quit!  Otherwise, issue
+               // diagnosis and adjust configuration...
+               //
+               if (repair.code == 0)
+                       return candidate;
+
+               secondaryDiagnosis(repair);
+
+               //
+               // Update buffer based on number of elements that are deleted.
+               //
+               switch(repair.code) {
+                       case MISPLACED_CODE:
+                                candidate.location = buffer[2];
+                                candidate.symbol = lexStream.kind(buffer[2]);
+                                lexStream.reset(lexStream.next(buffer[2]));
+
+                                break;
+
+                       case DELETION_CODE:
+                                candidate.location = buffer[repair.bufferPosition];
+                                candidate.symbol =
+                                                  lexStream.kind(buffer[repair.bufferPosition]);
+                                lexStream.reset(lexStream.next(buffer[repair.bufferPosition]));
+
+                                break;
+
+               default: // SCOPE_CODE || SECONDARY_CODE
+                                candidate.symbol = repair.symbol;
+                                candidate.location = buffer[repair.bufferPosition];
+                                lexStream.reset(buffer[repair.bufferPosition]);
+
+                                break;
+               }
+
+               return candidate;
+       }
+
+
+//
+//        This boolean function checks whether or not a given
+//        configuration yields a better misplacement recovery than
+//        the best misplacement recovery computed previously.
+//
+       private SecondaryRepairInfo misplacementRecovery(int stck[], int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) {
+               int  previous_loc = buffer[2];
+               int stack_deletions = 0;
+
+               for (int top = stack_top - 1; top >= 0; top--) {
+                       if (locationStack[top] < previous_loc) {
+                               stack_deletions++;
+                       }
+                       previous_loc = locationStack[top];
+
+                       int j = parseCheck(stck, top, lexStream.kind(buffer[2]), 3);
+                       if (j == MAX_DISTANCE) {
+                                j = last_index;
+                       }
+                       if ((j > MIN_DISTANCE) && (j - stack_deletions) > (repair.distance - repair.numDeletions)) {
+                               repair.stackPosition = top;
+                               repair.distance = j;
+                               repair.numDeletions = stack_deletions;
+                               repair.recoveryOnNextStack = stack_flag;
+                       }
+               }
+
+               return repair;
+       }
+
+
+//
+//        This boolean function checks whether or not a given
+//        configuration yields a better secondary recovery than the
+//        best misplacement recovery computed previously.
+//
+       private SecondaryRepairInfo secondaryRecovery(int stck[],int stack_top, int last_index, SecondaryRepairInfo repair, boolean stack_flag) {
+               int previous_loc;
+               int stack_deletions = 0;
+               
+               previous_loc = buffer[2];
+               for (int top = stack_top; top >= 0 && repair.numDeletions >= stack_deletions; top--) {
+                       if (locationStack[top] < previous_loc) {
+                               stack_deletions++;
+                       }
+                       previous_loc = locationStack[top];
+
+                       for (int i = 2;
+                                i <= (last_index - MIN_DISTANCE + 1) &&
+                                (repair.numDeletions >= (stack_deletions + i - 1)); i++) {
+                               int j = parseCheck(stck, top, lexStream.kind(buffer[i]), i + 1);
+
+                               if (j == MAX_DISTANCE) {
+                                        j = last_index;
+                               }
+                               if ((j - i + 1) > MIN_DISTANCE) {
+                                       int k = stack_deletions + i - 1;
+                                       if ((k < repair.numDeletions) ||
+                                               (j - k) > (repair.distance - repair.numDeletions) ||
+                                               ((repair.code == SECONDARY_CODE) && (j - k) == (repair.distance - repair.numDeletions))) {
+                                               repair.code = DELETION_CODE;
+                                               repair.distance = j;
+                                               repair.stackPosition = top;
+                                               repair.bufferPosition = i;
+                                               repair.numDeletions = k;
+                                               repair.recoveryOnNextStack = stack_flag;
+                                       }
+                               }
+
+                               for (int l = Parser.nasi(stck[top]); l >= 0 && Parser.nasr[l] != 0; l++) {
+                                       int symbol = Parser.nasr[l] + NT_OFFSET;
+                                       j = parseCheck(stck, top, symbol, i);
+                                       if (j == MAX_DISTANCE) {
+                                                j = last_index;
+                                       }
+                                       if ((j - i + 1) > MIN_DISTANCE) {
+                                               int k = stack_deletions + i - 1;
+                                               if (k < repair.numDeletions || (j - k) > (repair.distance - repair.numDeletions)) {
+                                                       repair.code = SECONDARY_CODE;
+                                                       repair.symbol = symbol;
+                                                       repair.distance = j;
+                                                       repair.stackPosition = top;
+                                                       repair.bufferPosition = i;
+                                                       repair.numDeletions = k;
+                                                       repair.recoveryOnNextStack = stack_flag;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return repair;
+       }
+
+
+//
+//        This procedure is invoked to issue a secondary diagnosis and
+//        adjust the input buffer.  The recovery in question is either
+//        an automatic scope recovery, a manual scope recovery, a
+//        secondary substitution or a secondary deletion.
+//
+       private void secondaryDiagnosis(SecondaryRepairInfo repair) {
+               switch(repair.code) {
+                       case SCOPE_CODE: {
+                   if (repair.stackPosition < stateStackTop) {
+                       reportError(DELETION_CODE,
+                                   Parser.terminal_index[ERROR_SYMBOL],
+                                   locationStack[repair.stackPosition],
+                                   buffer[1]);
+                   }
+                   for (int i = 0; i < scopeStackTop; i++) {
+                       reportError(SCOPE_CODE,
+                                   -scopeIndex[i],
+                                   locationStack[scopePosition[i]],
+                                   buffer[1],
+                                   Parser.non_terminal_index[Parser.scope_lhs[scopeIndex[i]]]);
+                   }
+       
+                   repair.symbol = Parser.scope_lhs[scopeIndex[scopeStackTop]] + NT_OFFSET;
+                   stateStackTop = scopePosition[scopeStackTop];
+                   reportError(SCOPE_CODE,
+                               -scopeIndex[scopeStackTop],
+                               locationStack[scopePosition[scopeStackTop]],
+                               buffer[1],
+                               getNtermIndex(stack[stateStackTop],
+                                             repair.symbol,
+                                             repair.bufferPosition)
+                              );
+                   break;
+               }
+                       default: {
+                               reportError(repair.code,
+                                                       (repair.code == SECONDARY_CODE
+                                                                                 ? getNtermIndex(stack[repair.stackPosition],
+                                                                                                                 repair.symbol,
+                                                                                                                 repair.bufferPosition)
+                                                                                 : Parser.terminal_index[ERROR_SYMBOL]),
+                                                       locationStack[repair.stackPosition],
+                                                       buffer[repair.bufferPosition - 1]);
+                               stateStackTop = repair.stackPosition;
+                       }
+               }
+       }
+
+
+
+
+//
+//        Try to parse until first_token and all tokens in BUFFER have
+//        been consumed, or an error is encountered. Return the number
+//        of tokens that were expended before the parse blocked.
+//
+       private int parseCheck(int stck[], int stack_top, int first_token, int buffer_position) {
+               int max_pos;
+               int indx;
+               int ct;
+               int act;
+
+               //
+               // Initialize pointer for temp_stack and initialize maximum
+               // position of state stack that is still useful.
+               //
+               act = stck[stack_top];
+               if (first_token > NT_OFFSET) {
+                       tempStackTop = stack_top;
+                       max_pos = stack_top;
+                       indx = buffer_position;
+                       ct = lexStream.kind(buffer[indx]);
+                       lexStream.reset(lexStream.next(buffer[indx]));
+                       int lhs_symbol = first_token - NT_OFFSET;
+                       act = Parser.ntAction(act, lhs_symbol);
+                       if (act <= NUM_RULES) {
+                               do {
+                                       tempStackTop -= (Parser.rhs[act]-1);
+                                       lhs_symbol = Parser.lhs[act];
+                                       act = (tempStackTop > max_pos
+                                                                                 ? tempStack[tempStackTop]
+                                                                                 : stck[tempStackTop]);
+                                       act = Parser.ntAction(act, lhs_symbol);
+                               } while(act <= NUM_RULES);
+       
+                               max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+                       }
+               } else {
+                       tempStackTop = stack_top - 1;
+                       max_pos = tempStackTop;
+                       indx = buffer_position - 1;
+                       ct = first_token;
+                       lexStream.reset(buffer[buffer_position]);
+               }
+
+               process_terminal: for (;;) {
+                       if (++tempStackTop >= stackLength)  // Stack overflow!!!
+                               return indx;
+                       tempStack[tempStackTop] = act;
+
+                       act = Parser.tAction(act, ct);
+
+                       if (act <= NUM_RULES) {               // reduce action
+                               tempStackTop--;
+                       } else if (act < ACCEPT_ACTION ||     // shift action
+                                        act > ERROR_ACTION) {        // shift-reduce action
+                               if (indx == MAX_DISTANCE)
+                                       return indx;
+                               indx++;
+                               ct = lexStream.kind(buffer[indx]);
+                               lexStream.reset(lexStream.next(buffer[indx]));
+                               if (act > ERROR_ACTION) {
+                                        act -= ERROR_ACTION;
+                               } else {
+                                       continue process_terminal;
+                               }
+                       } else if (act == ACCEPT_ACTION) {           // accept action
+                                return MAX_DISTANCE;
+                       } else {
+                               return indx;                         // error action
+                       }
+
+                       process_non_terminal:
+                       do {
+                               tempStackTop -= (Parser.rhs[act]-1);
+                               int lhs_symbol = Parser.lhs[act];
+                               act = (tempStackTop > max_pos
+                                                                         ? tempStack[tempStackTop]
+                                                                         : stck[tempStackTop]);
+                               act = Parser.ntAction(act, lhs_symbol);
+                       } while(act <= NUM_RULES);
+
+                       max_pos = max_pos < tempStackTop ? max_pos : tempStackTop;
+               } // process_terminal;
+       }
+       private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken) {
+               reportError(msgCode, nameIndex, leftToken, rightToken, 0);
+       }
+
+       private void reportError(int msgCode, int nameIndex, int leftToken, int rightToken, int scopeNameIndex) {
+               int lToken = (leftToken > rightToken ? rightToken : leftToken);
+
+               if (lToken < rightToken) {
+                       reportSecondaryError(msgCode, nameIndex, lToken, rightToken, scopeNameIndex);
+               } else {
+                       reportPrimaryError(msgCode, nameIndex, rightToken, scopeNameIndex);
+               }
+       }
+       private void reportPrimaryError(int msgCode, int nameIndex, int token, int scopeNameIndex) {
+               String name;
+               if (nameIndex >= 0) {
+                       name = Parser.readableName[nameIndex];
+               } else {
+                       name = EMPTY_STRING;
+               }
+
+               int errorStart = lexStream.start(token);
+               int errorEnd = lexStream.end(token);
+               int currentKind = lexStream.kind(token);
+               String errorTokenName = Parser.name[Parser.terminal_index[lexStream.kind(token)]];
+               char[] errorTokenSource = lexStream.name(token);
+
+               switch(msgCode) {
+                       case BEFORE_CODE:
+                               problemReporter().parseErrorInsertBeforeToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName, 
+                                       name);
+                                break;
+                       case INSERTION_CODE:
+                               problemReporter().parseErrorInsertAfterToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName, 
+                                       name);  
+                                break;
+                       case DELETION_CODE:
+                               problemReporter().parseErrorDeleteToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName);
+                               break;
+                       case INVALID_CODE:
+                               if (name.length() == 0) {
+                                       problemReporter().parseErrorReplaceToken(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName, 
+                                               name);
+                               } else {
+                                       problemReporter().parseErrorInvalidToken(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName, 
+                                               name);
+                               }
+                               break;
+                       case SUBSTITUTION_CODE:
+                               problemReporter().parseErrorReplaceToken(
+                                       errorStart, 
+                                       errorEnd, 
+                                       currentKind,
+                                       errorTokenSource, 
+                                       errorTokenName, 
+                                       name); 
+                                break;
+                       case SCOPE_CODE:
+                               StringBuffer buf = new StringBuffer();
+                               for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) {
+                                       buf.append(Parser.readableName[Parser.scope_rhs[i]]);
+                                       if (Parser.scope_rhs[i + 1] != 0) // any more symbols to print?
+                                               buf.append(' ');
+                                               
+                               }
+
+                               if (scopeNameIndex != 0) {
+                                       problemReporter().parseErrorInsertToComplete(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString(),
+                                               Parser.readableName[scopeNameIndex]);
+                               } else {
+                                       problemReporter().parseErrorInsertToCompleteScope(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString()); 
+                               }
+                               
+                               break;
+                       case EOF_CODE:
+                               problemReporter().parseErrorUnexpectedEnd(
+                                       errorStart, 
+                                       errorEnd); 
+                               break;
+                       case MERGE_CODE:
+                               problemReporter().parseErrorMergeTokens(
+                                       errorStart, 
+                                       errorEnd,
+                                       name);
+                               break;
+                       case MISPLACED_CODE:
+                               problemReporter().parseErrorMisplacedConstruct(
+                                       errorStart, 
+                                       errorEnd);
+                               break;
+                       default:
+                               if (name.length() == 0) {
+                                       problemReporter().parseErrorNoSuggestion(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName);
+                               } else {
+                                       problemReporter().parseErrorReplaceToken(
+                                               errorStart, 
+                                               errorEnd, 
+                                               currentKind,
+                                               errorTokenSource, 
+                                               errorTokenName, 
+                                               name); 
+                               }
+                               break;
+               }
+       }
+
+       private void reportSecondaryError(int msgCode,  int nameIndex,  int leftToken,  int rightToken, int scopeNameIndex) {
+               String name;
+               if (nameIndex >= 0) {
+                       name = Parser.readableName[nameIndex];
+               } else {
+                       name = EMPTY_STRING;    
+               }
+
+               int errorStart = -1;
+               if(lexStream.isInsideStream(leftToken)) {
+                       if(leftToken == 0) {
+                               errorStart = lexStream.start(leftToken + 1);
+                       } else {
+                               errorStart = lexStream.start(leftToken);
+                       }
+               } else {
+                       if(leftToken == errorToken) {
+                               errorStart = errorTokenStart;
+                       } else {
+                               for (int i = 0; i <= stateStackTop; i++) {
+                                       if(locationStack[i] == leftToken) {
+                                               errorStart = locationStartStack[i];
+                                       }
+                               }
+                       }
+                       if(errorStart == -1) {
+                               errorStart = lexStream.start(rightToken);
+                       }
+               }
+               int errorEnd = lexStream.end(rightToken);
+               
+               switch(msgCode) {
+                       case MISPLACED_CODE:
+                               problemReporter().parseErrorMisplacedConstruct(
+                                       errorStart, 
+                                       errorEnd); 
+                               break;
+                       case SCOPE_CODE:
+                               // error start is on the last token start
+                               errorStart = lexStream.start(rightToken);
+                       
+                   StringBuffer buf = new StringBuffer();
+                   for (int i = Parser.scope_suffix[- nameIndex]; Parser.scope_rhs[i] != 0; i++) {
+                       buf.append(Parser.readableName[Parser.scope_rhs[i]]);
+                       if (Parser.scope_rhs[i+1] != 0)
+                            buf.append(' ');
+                   }
+                   if (scopeNameIndex != 0) {
+                       problemReporter().parseErrorInsertToComplete(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString(),
+                                               Parser.readableName[scopeNameIndex]);
+                   } else {
+                       problemReporter().parseErrorInsertToCompletePhrase(
+                                               errorStart, 
+                                               errorEnd,
+                                               buf.toString()); 
+                   }
+                   break;
+                       case MERGE_CODE:
+                               problemReporter().parseErrorMergeTokens(
+                                       errorStart, 
+                                       errorEnd,
+                                       name);
+                               break;
+                       case DELETION_CODE:
+                               problemReporter().parseErrorDeleteTokens(
+                                       errorStart, 
+                                       errorEnd);
+                               break;
+                       default:
+                               if (name.length() == 0) {
+                                       problemReporter().parseErrorNoSuggestionForTokens(
+                                               errorStart, 
+                                               errorEnd);
+                               } else {
+                                       problemReporter().parseErrorReplaceTokens(
+                                               errorStart, 
+                                               errorEnd,
+                                               name);
+                               }
+               }
+               return;
+       }
+
+       public String toString() {
+               StringBuffer res = new StringBuffer();
+               
+               res.append(lexStream.toString());
+               
+               return res.toString();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/LexStream.java b/src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/LexStream.java
new file mode 100644 (file)
index 0000000..3231806
--- /dev/null
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.InvalidInputException;
+import org.eclipse.jdt.internal.compiler.parser.Scanner;
+import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
+
+public class LexStream implements TerminalTokens {
+       public static final int IS_AFTER_JUMP = 1;
+       public static final int LBRACE_MISSING = 2;
+               
+       public class Token{
+               int kind;
+               char[] name;
+               int start;
+               int end;
+               int line;
+               int flags;
+               
+               public String toString() {
+                       StringBuffer buffer = new StringBuffer();
+                       buffer.append(name).append('[').append(kind).append(']');
+                       buffer.append('{').append(start).append(',').append(end).append('}').append(line);
+                       return buffer.toString();
+               }
+
+       }
+
+       private int tokenCacheIndex;
+       private int tokenCacheEOFIndex;
+       private Token[] tokenCache;
+
+       private int currentIndex = -1;
+
+       private Scanner scanner;
+       private int[] intervalStartToSkip;
+       private int[] intervalEndToSkip;
+       private int[] intervalFlagsToSkip;
+       
+       private int previousInterval = -1;
+       
+       public LexStream(int size, Scanner scanner, int[] intervalStartToSkip, int[] intervalEndToSkip, int[] intervalFlagsToSkip, int firstToken, int init, int eof) {
+               this.tokenCache = new Token[size];
+               this.tokenCacheIndex = 0;
+               this.tokenCacheEOFIndex = Integer.MAX_VALUE;
+               this.tokenCache[0] = new Token();
+               this.tokenCache[0].kind = firstToken;
+               this.tokenCache[0].name = CharOperation.NO_CHAR;
+               this.tokenCache[0].start = init;
+               this.tokenCache[0].end = init;
+               this.tokenCache[0].line = 0;
+               
+               this.intervalStartToSkip = intervalStartToSkip;
+               this.intervalEndToSkip = intervalEndToSkip;
+               this.intervalFlagsToSkip = intervalFlagsToSkip;
+               
+               scanner.resetTo(init, eof);
+               this.scanner = scanner;
+       }
+       
+       private void readTokenFromScanner(){
+               int length = tokenCache.length;
+               boolean tokenNotFound = true;
+               
+               while(tokenNotFound) {
+                       try {
+                               int tokenKind =  scanner.getNextToken();
+                               if(tokenKind != TokenNameEOF) {
+                                       int start = scanner.getCurrentTokenStartPosition();
+                                       int end = scanner.getCurrentTokenEndPosition();
+                                       if(!RangeUtil.isInInterval(start, end, intervalStartToSkip, intervalEndToSkip)) {
+                                               Token token = new Token();
+                                               token.kind = tokenKind;
+                                               token.name = scanner.getCurrentTokenSource();
+                                               token.start = start;
+                                               token.end = end;
+                                               token.line = scanner.getLineNumber(end);
+                                               
+                                               int pInterval = RangeUtil.getPreviousInterval(start, end, intervalStartToSkip, intervalEndToSkip);
+                                               if(pInterval != previousInterval && (intervalFlagsToSkip[previousInterval + 1] & RangeUtil.IGNORE) == 0){
+                                                       token.flags = IS_AFTER_JUMP;
+                                                       if((intervalFlagsToSkip[pInterval] & RangeUtil.LBRACE_MISSING) != 0){
+                                                               token.flags |= LBRACE_MISSING;
+                                                       }
+                                               }
+                                               previousInterval = pInterval;
+
+                                               tokenCache[++tokenCacheIndex % length] = token;
+                                               
+                                               tokenNotFound = false;
+                                       }
+                               } else {
+                                       int start = scanner.getCurrentTokenStartPosition();
+                                       int end = scanner.getCurrentTokenEndPosition();
+                                       Token token = new Token();
+                                       token.kind = tokenKind;
+                                       token.name = CharOperation.NO_CHAR;
+                                       token.start = start;
+                                       token.end = end;
+                                       token.line = scanner.getLineNumber(end);
+                                       
+                                       tokenCache[++tokenCacheIndex % length] = token;
+                                       
+                                       tokenCacheEOFIndex = tokenCacheIndex;
+                                       tokenNotFound = false;
+                               }
+                       } catch (InvalidInputException e) {
+                               // return next token
+                       }
+               }
+       }
+       
+       public Token token(int index) {
+               if(index < 0) {
+                       Token eofToken = new Token();
+                       eofToken.kind = TokenNameEOF;
+                       eofToken.name = CharOperation.NO_CHAR;
+                       return eofToken;
+               }
+               if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) {
+                       return token(this.tokenCacheEOFIndex);
+               }
+               int length = tokenCache.length;
+               if(index > this.tokenCacheIndex) {
+                       int tokensToRead = index - this.tokenCacheIndex;
+                       while(tokensToRead-- != 0) {
+                               readTokenFromScanner();
+                       }
+               } else if(this.tokenCacheIndex - length >= index) {
+                       return null;
+               }
+               
+               return tokenCache[index % length];
+       }
+       
+       
+       
+       public int getToken() {
+               return currentIndex = next(currentIndex);
+       }
+       
+       public int previous(int tokenIndex) {
+               return tokenIndex > 0 ? tokenIndex - 1 : 0;
+       }
+
+       public int next(int tokenIndex) {
+               return tokenIndex < this.tokenCacheEOFIndex ? tokenIndex + 1 : this.tokenCacheEOFIndex;
+       }
+
+       public boolean afterEol(int i) {
+               return i < 1 ? true : line(i - 1) < line(i);
+       }
+       
+       public void reset() {
+               currentIndex = -1;
+       }
+       
+       public void reset(int i) {
+               currentIndex = previous(i);
+       }
+
+       public int badtoken() {
+               return 0;
+       }
+
+       public int kind(int tokenIndex) {
+               return token(tokenIndex).kind;
+       }
+       
+       public char[] name(int tokenIndex) {
+               return token(tokenIndex).name;
+       }
+
+       public int line(int tokenIndex) {
+               return token(tokenIndex).line;
+       }
+       
+       public int start(int tokenIndex) {
+               return token(tokenIndex).start;
+       }
+       
+       public int end(int tokenIndex) {
+               return token(tokenIndex).end;
+       }
+       
+       public int flags(int tokenIndex) {
+               return token(tokenIndex).flags;
+       }
+       
+       public boolean isInsideStream(int index) {
+               if(this.tokenCacheEOFIndex >= 0 && index > this.tokenCacheEOFIndex) {
+                       return false;
+               } else if(index > this.tokenCacheIndex) {
+                       return true;
+               } else if(this.tokenCacheIndex - tokenCache.length >= index) {
+                       return false;
+               } else {
+                       return true;
+               }
+       }
+       
+       /* (non-Javadoc)
+        * @see java.lang.Object#toString()
+        */
+       public String toString() {
+               StringBuffer res = new StringBuffer();
+               
+               String source = new String(scanner.source);
+               if(currentIndex < 0) {
+                       res.append(source);
+               } else {
+                       Token token = token(currentIndex);
+                       int curtokKind = token.kind;
+                       int curtokStart = token.start;
+                       int curtokEnd = token.end;
+                       
+                       int previousEnd = -1;
+                       for (int i = 0; i < intervalStartToSkip.length; i++) {
+                               int intervalStart = intervalStartToSkip[i];
+                               int intervalEnd = intervalEndToSkip[i];
+                               
+                               if(curtokStart >= previousEnd && curtokEnd <= intervalStart) {
+                                       res.append(source.substring(previousEnd + 1, curtokStart));
+                                       res.append('<');
+                                       res.append('#');
+                                       res.append(source.substring(curtokStart, curtokEnd + 1));
+                                       res.append('#');
+                                       res.append('>');
+                                       res.append(source.substring(curtokEnd+1, intervalStart));
+                               } else {
+                                       res.append(source.substring(previousEnd + 1, intervalStart));
+                               }
+                               res.append('<');
+                               res.append('@');
+                               res.append(source.substring(intervalStart, intervalEnd + 1));
+                               res.append('@');
+                               res.append('>');
+                               
+                               previousEnd = intervalEnd;
+                       }
+                       if(curtokStart >= previousEnd) {
+                               res.append(source.substring(previousEnd + 1, curtokStart));
+                               res.append('<');
+                               res.append('#');
+                               if(curtokKind == TokenNameEOF) {
+                                       res.append("EOF#>"); //$NON-NLS-1$
+                               } else {
+                                       res.append(source.substring(curtokStart, curtokEnd + 1));
+                                       res.append('#');
+                                       res.append('>');
+                                       res.append(source.substring(curtokEnd+1));
+                               }
+                       } else {
+                               res.append(source.substring(previousEnd + 1));
+                       }
+               }
+               
+               return res.toString();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java b/src/java/org/eclipse/jdt/internal/compiler/parser/diagnose/RangeUtil.java
new file mode 100644 (file)
index 0000000..4c53fa2
--- /dev/null
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.parser.diagnose;
+
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Initializer;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.CompilerModifiers;
+
+public class RangeUtil {
+       
+       // flags
+       public static final int NO_FLAG = 0;
+       public static final int LBRACE_MISSING = 1;
+       public static final int IGNORE = 2;
+       
+       static class RangeResult {
+               private static final int INITIAL_SIZE = 10;
+               int pos;
+               int[] intervalStarts;
+               int[] intervalEnds;
+               int[] intervalFlags;
+               
+               RangeResult() {
+                       this.pos = 0;
+                       this.intervalStarts = new int[INITIAL_SIZE];
+                       this.intervalEnds = new int[INITIAL_SIZE];
+                       this.intervalFlags = new int[INITIAL_SIZE];
+               }
+               
+               void addInterval(int start, int end){
+                       addInterval(start, end, NO_FLAG);
+               }
+               
+               void addInterval(int start, int end, int flags){
+                       if(pos >= intervalStarts.length) {
+                               System.arraycopy(intervalStarts, 0, intervalStarts = new int[pos * 2], 0, pos);
+                               System.arraycopy(intervalEnds, 0, intervalEnds = new int[pos * 2], 0, pos);
+                               System.arraycopy(intervalFlags, 0, intervalFlags = new int[pos * 2], 0, pos);
+                       }
+                       intervalStarts[pos] = start;
+                       intervalEnds[pos] = end;
+                       intervalFlags[pos] = flags;
+                       pos++;
+               }
+               
+               int[][] getRanges() {
+                       int[] resultStarts = new int[pos];
+                       int[] resultEnds = new int[pos];
+                       int[] resultFlags = new int[pos];
+                       
+                       System.arraycopy(intervalStarts, 0, resultStarts, 0, pos);
+                       System.arraycopy(intervalEnds, 0, resultEnds, 0, pos);
+                       System.arraycopy(intervalFlags, 0, resultFlags, 0, pos);
+
+                       if (resultStarts.length > 1) {
+                               quickSort(resultStarts, resultEnds, resultFlags, 0, resultStarts.length - 1);
+                       }
+                       return new int[][]{resultStarts, resultEnds, resultFlags};
+               }
+               
+               private void quickSort(int[] list, int[] list2, int[] list3, int left, int right) {
+                       int original_left= left;
+                       int original_right= right;
+                       int mid= list[(left + right) / 2];
+                       do {
+                               while (compare(list[left], mid) < 0) {
+                                       left++;
+                               }
+                               while (compare(mid, list[right]) < 0) {
+                                       right--;
+                               }
+                               if (left <= right) {
+                                       int tmp= list[left];
+                                       list[left]= list[right];
+                                       list[right]= tmp;
+                                       
+                                       tmp = list2[left];
+                                       list2[left]= list2[right];
+                                       list2[right]= tmp;
+                                       
+                                       tmp = list3[left];
+                                       list3[left]= list3[right];
+                                       list3[right]= tmp;
+                                       
+                                       left++;
+                                       right--;
+                               }
+                       } while (left <= right);
+                       
+                       if (original_left < right) {
+                               quickSort(list, list2, list3, original_left, right);
+                       }
+                       if (left < original_right) {
+                               quickSort(list, list2, list3, left, original_right);
+                       }
+               }
+               
+               private int compare(int i1, int i2) {
+                       return i1 - i2;
+               }
+       }
+       
+       
+       
+       public static boolean containsErrorInSignature(AbstractMethodDeclaration method){
+               return method.sourceEnd + 1 == method.bodyStart || method.bodyEnd == method.declarationSourceEnd;
+       }
+
+       public static int[][] computeDietRange(TypeDeclaration[] types) {
+               if(types == null || types.length == 0) {
+                       return new int[3][0];
+               } else {
+                       RangeResult result = new RangeResult();
+                       computeDietRange0(types, result);
+                       return result.getRanges();
+               }
+       }
+       
+       private static void computeDietRange0(TypeDeclaration[] types, RangeResult result) {
+               for (int j = 0; j < types.length; j++) {
+                       //members
+                       TypeDeclaration[] memberTypeDeclarations = types[j].memberTypes;
+                       if(memberTypeDeclarations != null && memberTypeDeclarations.length > 0) {
+                               computeDietRange0(types[j].memberTypes, result);
+                       }
+                       //methods
+                       AbstractMethodDeclaration[] methods = types[j].methods;
+                       if (methods != null) {
+                               int length = methods.length;
+                               for (int i = 0; i < length; i++) {
+                                       AbstractMethodDeclaration method = methods[i];
+                                       if(containsIgnoredBody(method)) {
+                                               if(containsErrorInSignature(method)) {
+                                                       method.errorInSignature = true;
+                                                       result.addInterval(method.declarationSourceStart, method.declarationSourceEnd, IGNORE);
+                                               } else {
+                                                       int flags = method.sourceEnd + 1 == method.bodyStart ? LBRACE_MISSING : NO_FLAG;
+                                                       result.addInterval(method.bodyStart, method.bodyEnd, flags);
+                                               }
+                                       }
+                               }
+                       }
+       
+                       //initializers
+                       FieldDeclaration[] fields = types[j].fields;
+                       if (fields != null) {
+                               int length = fields.length;
+                               for (int i = 0; i < length; i++) {
+                                       if (fields[i] instanceof Initializer) {
+                                               Initializer initializer = (Initializer)fields[i];
+                                               if(initializer.declarationSourceEnd == initializer.bodyEnd){
+                                                       initializer.errorInSignature = true;
+                                                       result.addInterval(initializer.declarationSourceStart, initializer.declarationSourceEnd, IGNORE);
+                                               } else {
+                                                       result.addInterval(initializer.bodyStart, initializer.bodyEnd);
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+       
+       public static boolean isInInterval(int start, int end, int[] intervalStart, int[] intervalEnd) {
+               int length = intervalStart.length;
+               for (int i = 0; i < length; i++) {
+                       if(intervalStart[i] <= start && intervalEnd[i] >= end) {
+                               return true;
+                       } else if(intervalStart[i] > end) {
+                               return false;
+                       }
+               }
+               return false;
+       }
+       
+       public static int getPreviousInterval(int start, int end, int[] intervalStart, int[] intervalEnd) {
+               int length = intervalStart.length;
+               for (int i = 0; i < length; i++) {
+                       if(intervalStart[i] > end) {
+                               return i - 1;
+                       }
+               }
+               return length - 1;
+       }
+       
+       public static boolean containsIgnoredBody(AbstractMethodDeclaration method){
+               return !method.isDefaultConstructor()
+                       && !method.isClinit()
+                       && (method.modifiers & CompilerModifiers.AccSemicolonBody) == 0;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser1.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser1.rsc
new file mode 100644 (file)
index 0000000..a35d6d8
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser1.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser10.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser10.rsc
new file mode 100644 (file)
index 0000000..57084e8
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser10.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser11.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser11.rsc
new file mode 100644 (file)
index 0000000..4ed7d3b
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser11.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser12.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser12.rsc
new file mode 100644 (file)
index 0000000..a114c91
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser12.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser13.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser13.rsc
new file mode 100644 (file)
index 0000000..6b56156
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser13.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser14.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser14.rsc
new file mode 100644 (file)
index 0000000..e701a9e
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser14.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser15.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser15.rsc
new file mode 100644 (file)
index 0000000..4497913
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser15.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser16.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser16.rsc
new file mode 100644 (file)
index 0000000..0046bb9
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser16.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser17.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser17.rsc
new file mode 100644 (file)
index 0000000..ca3af17
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser17.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser18.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser18.rsc
new file mode 100644 (file)
index 0000000..66f0156
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser18.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser19.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser19.rsc
new file mode 100644 (file)
index 0000000..0f1c471
--- /dev/null
@@ -0,0 +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
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser2.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser2.rsc
new file mode 100644 (file)
index 0000000..3d7327b
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser2.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser20.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser20.rsc
new file mode 100644 (file)
index 0000000..8dc5ace
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser20.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser3.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser3.rsc
new file mode 100644 (file)
index 0000000..81f96e1
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser3.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser4.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser4.rsc
new file mode 100644 (file)
index 0000000..2842e17
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser4.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser5.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser5.rsc
new file mode 100644 (file)
index 0000000..26aa971
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser5.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser6.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser6.rsc
new file mode 100644 (file)
index 0000000..69c1580
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser6.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser7.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser7.rsc
new file mode 100644 (file)
index 0000000..a4e445a
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser7.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser8.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser8.rsc
new file mode 100644 (file)
index 0000000..8ce79a7
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser8.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/parser9.rsc b/src/java/org/eclipse/jdt/internal/compiler/parser/parser9.rsc
new file mode 100644 (file)
index 0000000..6f68468
Binary files /dev/null and b/src/java/org/eclipse/jdt/internal/compiler/parser/parser9.rsc differ
diff --git a/src/java/org/eclipse/jdt/internal/compiler/parser/readableNames.properties b/src/java/org/eclipse/jdt/internal/compiler/parser/readableNames.properties
new file mode 100644 (file)
index 0000000..ecc98bf
--- /dev/null
@@ -0,0 +1,202 @@
+,opt=,
+AbstractMethodDeclaration=AbstractMethodDeclaration
+AdditiveExpression=Expression
+AllocationHeader=AllocationHeader
+AndExpression=Expression
+ArgumentList=ArgumentList
+ArgumentListopt=ArgumentList
+ArrayAccess=ArrayAccess
+ArrayCreationHeader=ArrayCreationHeader
+ArrayCreationWithArrayInitializer=ArrayCreationWithArrayInitializer
+ArrayCreationWithoutArrayInitializer=ArrayCreationWithoutArrayInitializer
+ArrayInitializer=ArrayInitializer
+ArrayType=ArrayType
+AssertStatement=AssertStatement
+Assignment=Assignment
+AssignmentExpression=Expression
+AssignmentOperator=AssignmentOperator
+Block=Block
+BlockStatement=BlockStatement
+BlockStatements=BlockStatements
+BlockStatementsopt=BlockStatements
+BooleanLiteral=BooleanLiteral
+BreakStatement=BreakStatement
+CastExpression=CastExpression
+CatchClause=CatchClause
+CatchHeader=CatchHeader
+Catches=Catches
+Catchesopt=Catches
+ClassBody=ClassBody
+ClassBodyDeclaration=ClassBodyDeclaration
+ClassBodyDeclarations=ClassBodyDeclarations
+ClassBodyDeclarationsopt=ClassBodyDeclarations
+ClassBodyopt=ClassBody
+ClassDeclaration=ClassDeclaration
+ClassHeader=ClassHeader
+ClassHeaderExtends=ClassHeaderExtends
+ClassHeaderExtendsopt=ClassHeaderExtends
+ClassHeaderImplements=ClassHeaderImplements
+ClassHeaderImplementsopt=ClassHeaderImplements
+ClassHeaderName=ClassHeaderName
+ClassInstanceCreationExpression=ClassInstanceCreationExpression
+ClassInstanceCreationExpressionName=ClassInstanceCreationExpressionName
+ClassMemberDeclaration=ClassMemberDeclaration
+ClassOrInterfaceType=Type
+ClassType=ClassType
+ClassTypeElt=ClassType
+ClassTypeList=ClassTypeList
+CompilationUnit=CompilationUnit
+ConditionalAndExpression=Expression
+ConditionalExpression=Expression
+ConditionalOrExpression=Expression
+ConstantDeclaration=ConstantDeclaration
+ConstantExpression=ConstantExpression
+ConstructorDeclaration=ConstructorDeclaration
+ConstructorHeader=ConstructorHeader
+ConstructorHeaderName=ConstructorHeaderName
+ContinueStatement=ContinueStatement
+Diet=Diet
+DimWithOrWithOutExpr=Dimension
+DimWithOrWithOutExprs=Dimensions
+Dims=Dimensions
+DimsLoop=Dimensions
+Dimsopt=Dimensions
+DoStatement=DoStatement
+EmptyStatement=EmptyStatement
+EnterAnonymousClassBody=EnterAnonymousClassBody
+EnterCompilationUnit=EnterCompilationUnit
+EnterVariable=EnterVariable
+EqualityExpression=Expression
+ExclusiveOrExpression=Expression
+ExitTryBlock=ExitTryBlock
+ExitVariableWithInitialization=ExitVariableWithInitialization
+ExitVariableWithoutInitialization=ExitVariableWithoutInitialization
+ExplicitConstructorInvocation=ExplicitConstructorInvocation
+Expression=Expression
+ExpressionStatement=Statement
+Expressionopt=Expression
+FieldAccess=FieldAccess
+FieldDeclaration=FieldDeclaration
+Finally=Finally
+FloatingPointType=FloatingPointType
+ForInit=ForInit
+ForInitopt=ForInit
+ForStatement=ForStatement
+ForStatementNoShortIf=ForStatement
+ForUpdate=ForUpdate
+ForUpdateopt=ForUpdate
+ForceNoDiet=ForceNoDiet
+FormalParameter=FormalParameter
+FormalParameterList=FormalParameterList
+FormalParameterListopt=FormalParameterList
+GenericMethodDeclaration=GenericMethodDeclaration
+Goal=Goal
+Header=Header
+Headers=Headers
+IfThenElseStatement=IfStatement
+IfThenElseStatementNoShortIf=IfStatement
+IfThenStatement=IfStatement
+ImportDeclaration=ImportDeclaration
+ImportDeclarations=ImportDeclarations
+ImportDeclarationsopt=ImportDeclarations
+InclusiveOrExpression=Expression
+Initializer=Initializer
+InsideCastExpression=InsideCastExpression
+InsideCastExpressionLL1=InsideCastExpression
+IntegralType=IntegralType
+InterfaceBody=InterfaceBody
+InterfaceDeclaration=InterfaceDeclaration
+InterfaceHeader=InterfaceHeader
+InterfaceHeaderExtends=InterfaceHeaderExtends
+InterfaceHeaderExtendsopt=InterfaceHeaderExtends
+InterfaceHeaderName=InterfaceHeaderName
+InterfaceMemberDeclaration=InterfaceMemberDeclaration
+InterfaceMemberDeclarations=InterfaceMemberDeclarations
+InterfaceMemberDeclarationsopt=InterfaceMemberDeclarations
+InterfaceType=InterfaceType
+InterfaceTypeList=InterfaceTypeList
+InvalidArrayInitializerAssignement=ArrayInitializerAssignement
+InvalidConstructorDeclaration=InvalidConstructorDeclaration
+InvalidInterfaceDeclaration=InvalidInterfaceDeclaration
+InvalidMethodDeclaration=InvalidMethodDeclaration
+LabeledStatement=LabeledStatement
+LabeledStatementNoShortIf=LabeledStatement
+Literal=Literal
+LocalVariableDeclaration=LocalVariableDeclaration
+LocalVariableDeclarationStatement=LocalVariableDeclarationStatement
+MethodBody=MethodBody
+MethodDeclaration=MethodDeclaration
+MethodHeader=MethodHeader
+MethodHeaderExtendedDims=MethodHeaderExtendedDims
+MethodHeaderName=MethodHeaderName
+MethodHeaderParameters=MethodHeaderParameters
+MethodHeaderThrowsClause=MethodHeaderThrowsClause
+MethodHeaderThrowsClauseopt=MethodHeaderThrowsClause
+MethodInvocation=MethodInvocation
+Modifier=Modifier
+Modifiers=Modifiers
+Modifiersopt=Modifiers
+MultiplicativeExpression=Expression
+Name=Name
+NestedMethod=NestedMethod
+NestedType=NestedType
+NumericType=NumericType
+OneDimLoop=Dimension
+OnlySynchronized=OnlySynchronized
+OpenBlock=OpenBlock
+PackageDeclaration=PackageDeclaration
+PackageDeclarationName=PackageDeclarationName
+PackageDeclarationopt=PackageDeclaration
+PostDecrementExpression=PostDecrementExpression
+PostIncrementExpression=PostIncrementExpression
+PostfixExpression=Expression
+PreDecrementExpression=PreDecrementExpression
+PreIncrementExpression=PreIncrementExpression
+Primary=Expression
+PrimaryNoNewArray=Expression
+PrimitiveType=PrimitiveType
+PushLPAREN=(
+PushModifiers=PushModifiers
+PushPosition=PushPosition
+PushRPAREN=)
+QualifiedName=QualifiedName
+ReferenceType=ReferenceType
+RelationalExpression=Expression
+RestoreDiet=RestoreDiet
+ReturnStatement=ReturnStatement
+ShiftExpression=Expression
+SimpleName=SimpleName
+SingleTypeImportDeclaration=SingleTypeImportDeclaration
+SingleTypeImportDeclarationName=SingleTypeImportDeclarationName
+Statement=Statement
+StatementExpression=Expression
+StatementExpressionList=StatementExpressionList
+StatementNoShortIf=Statement
+StatementWithoutTrailingSubstatement=Statement
+StaticInitializer=StaticInitializer
+StaticOnly=StaticOnly
+SwitchBlock=SwitchBlock
+SwitchBlockStatement=SwitchBlockStatement
+SwitchBlockStatements=SwitchBlockStatements
+SwitchLabel=SwitchLabel
+SwitchLabels=SwitchLabels
+SwitchStatement=SwitchStatement
+SynchronizedStatement=SynchronizedStatement
+ThrowStatement=ThrowStatement
+TryBlock=Block
+TryStatement=TryStatement
+Type=Type
+TypeDeclaration=TypeDeclaration
+TypeDeclarations=TypeDeclarations
+TypeDeclarationsopt=TypeDeclarations
+TypeImportOnDemandDeclaration=TypeImportOnDemandDeclaration
+TypeImportOnDemandDeclarationName=TypeImportOnDemandDeclarationName
+UnaryExpression=Expression
+UnaryExpressionNotPlusMinus=Expression
+VariableDeclarator=VariableDeclarator
+VariableDeclaratorId=VariableDeclaratorId
+VariableDeclarators=VariableDeclarators
+VariableInitializer=VariableInitializer
+VariableInitializers=VariableInitializers
+WhileStatement=WhileStatement
+WhileStatementNoShortIf=WhileStatement
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java b/src/java/org/eclipse/jdt/internal/compiler/problem/AbortCompilation.java
new file mode 100644 (file)
index 0000000..88e143d
--- /dev/null
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.problem;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
+
+/*
+ * Special unchecked exception type used 
+ * to abort from the compilation process
+ *
+ * should only be thrown from within problem handlers.
+ */
+public class AbortCompilation extends RuntimeException {
+
+       public CompilationResult compilationResult;
+       public Throwable exception;
+       public IProblem problem;
+       
+       /* special fields used to abort silently (e.g. when cancelling build process) */
+       public boolean isSilent;
+       public RuntimeException silentException;
+
+       private static final long serialVersionUID = -2047226595083244852L; // backward compatible
+       
+       public AbortCompilation() {
+               // empty
+       }
+
+       public AbortCompilation(CompilationResult compilationResult, IProblem problem) {
+               this();
+               this.compilationResult = compilationResult;
+               this.problem = problem;
+       }
+
+       public AbortCompilation(CompilationResult compilationResult, Throwable exception) {
+               this();
+               this.compilationResult = compilationResult;
+               this.exception = exception;
+       }
+
+       public AbortCompilation(boolean isSilent, RuntimeException silentException) {
+               this();
+               this.isSilent = isSilent;
+               this.silentException = silentException;
+       }
+       
+       public void updateContext(InvocationSite invocationSite, CompilationResult unitResult) {
+               if (this.problem == null) return;
+               if (this.problem.getSourceStart() != 0 || this.problem.getSourceEnd() != 0) return;
+               this.problem.setSourceStart(invocationSite.sourceStart());
+               this.problem.setSourceEnd(invocationSite.sourceEnd());
+               this.problem.setSourceLineNumber(ProblemHandler.searchLineNumber(unitResult.lineSeparatorPositions, invocationSite.sourceStart()));
+               this.compilationResult = unitResult;
+       }
+
+       public void updateContext(ASTNode astNode, CompilationResult unitResult) {
+               if (this.problem == null) return;
+               if (this.problem.getSourceStart() != 0 || this.problem.getSourceEnd() != 0) return;
+               this.problem.setSourceStart(astNode.sourceStart());
+               this.problem.setSourceEnd(astNode.sourceEnd());
+               this.problem.setSourceLineNumber(ProblemHandler.searchLineNumber(unitResult.lineSeparatorPositions, astNode.sourceStart()));
+               this.compilationResult = unitResult;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java b/src/java/org/eclipse/jdt/internal/compiler/problem/AbortCompilationUnit.java
new file mode 100644 (file)
index 0000000..d75e6ae
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.problem;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/*
+ * Special unchecked exception type used 
+ * to abort from the compilation process
+ *
+ * should only be thrown from within problem handlers.
+ */
+public class AbortCompilationUnit extends AbortCompilation {
+    
+       private static final long serialVersionUID = -4253893529982226734L; // backward compatible
+    
+public AbortCompilationUnit(CompilationResult compilationResult, IProblem problem) {
+       super(compilationResult, problem);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java b/src/java/org/eclipse/jdt/internal/compiler/problem/AbortMethod.java
new file mode 100644 (file)
index 0000000..7feb32e
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.problem;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/*
+ * Special unchecked exception type used 
+ * to abort from the compilation process
+ *
+ * should only be thrown from within problem handlers.
+ */
+public class AbortMethod extends AbortType {
+
+    private static final long serialVersionUID = -1480267398969840003L; // backward compatible 
+       
+public AbortMethod(CompilationResult compilationResult, IProblem problem) {
+       super(compilationResult, problem);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/AbortType.java b/src/java/org/eclipse/jdt/internal/compiler/problem/AbortType.java
new file mode 100644 (file)
index 0000000..f357469
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.problem;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+
+/*
+ * Special unchecked exception type used 
+ * to abort from the compilation process
+ *
+ * should only be thrown from within problem handlers.
+ */
+public class AbortType extends AbortCompilationUnit {
+    
+       private static final long serialVersionUID = -5882417089349134385L; // backward compatible
+    
+public AbortType(CompilationResult compilationResult, IProblem problem) {
+       super(compilationResult, problem);
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java b/src/java/org/eclipse/jdt/internal/compiler/problem/DefaultProblem.java
new file mode 100644 (file)
index 0000000..8ec8619
--- /dev/null
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * 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.problem;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class DefaultProblem implements ProblemSeverities, IProblem {
+       
+       private static final String LINE_DELIMITER = System.getProperty("line.separator"); //$NON-NLS-1$
+               
+       private char[] fileName;
+       private int id;
+       private int startPosition, endPosition, line;
+       private int severity;
+       private String[] arguments;
+       private String message;
+       
+       public DefaultProblem(
+               char[] originatingFileName,
+               String message,
+               int id,
+               String[] stringArguments,
+               int severity,
+               int startPosition,
+               int endPosition,
+               int line) {
+
+               this.fileName = originatingFileName;
+               this.message = message;
+               this.id = id;
+               this.arguments = stringArguments;
+               this.severity = severity;
+               this.startPosition = startPosition;
+               this.endPosition = endPosition;
+               this.line = line;
+       }
+       public String errorReportSource(char[] unitSource) {
+               //extra from the source the innacurate     token
+               //and "highlight" it using some underneath ^^^^^
+               //put some context around too.
+
+               //this code assumes that the font used in the console is fixed size
+
+               //sanity .....
+               if ((this.startPosition > this.endPosition)
+                       || ((this.startPosition < 0) && (this.endPosition < 0)))
+                       return Util.bind("problem.noSourceInformation"); //$NON-NLS-1$
+
+               StringBuffer errorBuffer = new StringBuffer(" "); //$NON-NLS-1$
+               errorBuffer.append(Util.bind("problem.atLine", String.valueOf(this.line))); //$NON-NLS-1$
+               errorBuffer.append(LINE_DELIMITER).append("\t"); //$NON-NLS-1$
+               
+               char c;
+               final char SPACE = '\u0020';
+               final char MARK = '^';
+               final char TAB = '\t';
+               //the next code tries to underline the token.....
+               //it assumes (for a good display) that token source does not
+               //contain any \r \n. This is false on statements ! 
+               //(the code still works but the display is not optimal !)
+
+               // expand to line limits
+               int length = unitSource.length, begin, end;
+               for (begin = this.startPosition >= length ? length - 1 : this.startPosition; begin > 0; begin--) {
+                       if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
+               }
+               for (end = this.endPosition >= length ? length - 1 : this.endPosition ; end+1 < length; end++) {
+                       if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
+               }
+               
+               // trim left and right spaces/tabs
+               while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
+               //while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated
+               
+               // copy source
+               errorBuffer.append(unitSource, begin, end-begin+1);
+               errorBuffer.append(LINE_DELIMITER).append("\t"); //$NON-NLS-1$
+
+               // compute underline
+               for (int i = begin; i <this.startPosition; i++) {
+                       errorBuffer.append((unitSource[i] == TAB) ? TAB : SPACE);
+               }
+               for (int i = this.startPosition; i <= (this.endPosition >= length ? length - 1 : this.endPosition); i++) {
+                       errorBuffer.append(MARK);
+               }
+               return errorBuffer.toString();
+       }
+
+       /**
+        * Answer back the original arguments recorded into the problem.
+        * @return java.lang.String[]
+        */
+       public String[] getArguments() {
+
+               return this.arguments;
+       }
+
+       /**
+        * Answer the type of problem.
+        * @see org.eclipse.jdt.core.compiler.IProblem#getID()
+        * @return int
+        */
+       public int getID() {
+
+               return this.id;
+       }
+
+       /**
+        * Answer a localized, human-readable message string which describes the problem.
+        * @return java.lang.String
+        */
+       public String getMessage() {
+
+               return this.message;
+       }
+
+       /**
+        * Answer the file name in which the problem was found.
+        * @return char[]
+        */
+       public char[] getOriginatingFileName() {
+
+               return this.fileName;
+       }
+
+       /**
+        * Answer the end position of the problem (inclusive), or -1 if unknown.
+        * @return int
+        */
+       public int getSourceEnd() {
+
+               return this.endPosition;
+       }
+
+       /**
+        * Answer the line number in source where the problem begins.
+        * @return int
+        */
+       public int getSourceLineNumber() {
+
+               return this.line;
+       }
+
+       /**
+        * Answer the start position of the problem (inclusive), or -1 if unknown.
+        * @return int
+        */
+       public int getSourceStart() {
+
+               return this.startPosition;
+       }
+
+       /*
+        * Helper method: checks the severity to see if the Error bit is set.
+        * @return boolean
+        */
+       public boolean isError() {
+
+               return (this.severity & ProblemSeverities.Error) != 0;
+       }
+
+       /*
+        * Helper method: checks the severity to see if the Error bit is not set.
+        * @return boolean
+        */
+       public boolean isWarning() {
+
+               return (this.severity & ProblemSeverities.Error) == 0;
+       }
+
+       public void setOriginatingFileName(char[] fileName) {
+               this.fileName = fileName;
+       }
+       
+       /**
+        * Set the end position of the problem (inclusive), or -1 if unknown.
+        *
+        * Used for shifting problem positions.
+        * @param sourceEnd the new value of the sourceEnd of the receiver
+        */
+       public void setSourceEnd(int sourceEnd) {
+
+               this.endPosition = sourceEnd;
+       }
+
+       /**
+        * Set the line number in source where the problem begins.
+        * @param lineNumber the new value of the line number of the receiver
+        */
+       public void setSourceLineNumber(int lineNumber) {
+
+               this.line = lineNumber;
+       }
+
+       /**
+        * Set the start position of the problem (inclusive), or -1 if unknown.
+        *
+        * Used for shifting problem positions.
+        * @param sourceStart the new value of the source start position of the receiver
+        */
+       public void setSourceStart(int sourceStart) {
+
+               this.startPosition = sourceStart;
+       }
+
+       public String toString() {
+
+               String s = "Pb(" + (this.id & IgnoreCategoriesMask) + ") "; //$NON-NLS-1$ //$NON-NLS-2$
+               if (this.message != null) {
+                       s += this.message;
+               } else {
+                       if (this.arguments != null)
+                               for (int i = 0; i < this.arguments.length; i++)
+                                       s += " " + this.arguments[i]; //$NON-NLS-1$
+               }
+               return s;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java b/src/java/org/eclipse/jdt/internal/compiler/problem/DefaultProblemFactory.java
new file mode 100644 (file)
index 0000000..065c525
--- /dev/null
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * 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.problem;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.eclipse.jdt.core.compiler.*;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.util.HashtableOfInt;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class DefaultProblemFactory implements IProblemFactory {
+
+       public HashtableOfInt messageTemplates;
+       private Locale locale;
+       private static HashtableOfInt DEFAULT_LOCALE_TEMPLATES;
+       private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+       private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+
+public DefaultProblemFactory() {
+       this(Locale.getDefault());
+}
+/**
+ * @param loc the locale used to get the right message
+ */
+public DefaultProblemFactory(Locale loc) {
+       this.locale = loc;
+       if (Locale.getDefault().equals(loc)){
+               if (DEFAULT_LOCALE_TEMPLATES == null){
+                       DEFAULT_LOCALE_TEMPLATES = loadMessageTemplates(loc);
+               }
+               this.messageTemplates = DEFAULT_LOCALE_TEMPLATES;
+       } else {
+               this.messageTemplates = loadMessageTemplates(loc);
+       }
+}
+/**
+ * Answer a new IProblem created according to the parameters value
+ * <ul>
+ * <li>originatingFileName the name of the file name from which the problem is originated
+ * <li>problemId the problem id
+ * <li>problemArguments the fully qualified arguments recorded inside the problem
+ * <li>messageArguments the arguments needed to set the error message (shorter names than problemArguments ones)
+ * <li>severity the severity of the problem
+ * <li>startPosition the starting position of the problem
+ * <li>endPosition the end position of the problem
+ * <li>lineNumber the line on which the problem occured
+ * </ul>
+ * @param originatingFileName char[]
+ * @param problemId int
+ * @param problemArguments String[]
+ * @param messageArguments String[]
+ * @param severity int
+ * @param startPosition int
+ * @param endPosition int
+ * @param lineNumber int
+ * @return org.eclipse.jdt.internal.compiler.IProblem
+ */
+public IProblem createProblem(
+       char[] originatingFileName, 
+       int problemId, 
+       String[] problemArguments, 
+       String[] messageArguments, 
+       int severity, 
+       int startPosition, 
+       int endPosition, 
+       int lineNumber) {
+
+       return new DefaultProblem(
+               originatingFileName, 
+               this.getLocalizedMessage(problemId, messageArguments),
+               problemId, 
+               problemArguments, 
+               severity, 
+               startPosition, 
+               endPosition, 
+               lineNumber); 
+}
+private final static int keyFromID(int id) {
+    return id + 1; // keys are offsetted by one in table, since it cannot handle 0 key
+}
+/**
+ * Answer the locale used to retrieve the error messages
+ * @return java.util.Locale
+ */
+public Locale getLocale() {
+       return this.locale;
+}
+public final String getLocalizedMessage(int id, String[] problemArguments) {
+       String message = (String) this.messageTemplates.get(keyFromID(id & IProblem.IgnoreCategoriesMask)); 
+       if (message == null) {
+               return "Unable to retrieve the error message for problem id: " //$NON-NLS-1$
+                       + (id & IProblem.IgnoreCategoriesMask)
+                       + ". Check compiler resources.";  //$NON-NLS-1$
+       }
+
+       // for compatibility with MessageFormat which eliminates double quotes in original message
+       char[] messageWithNoDoubleQuotes =
+               CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+
+       if (problemArguments == null) return new String(messageWithNoDoubleQuotes);
+
+       int length = messageWithNoDoubleQuotes.length;
+       int start = 0;
+       int end = length;
+       StringBuffer output = null;
+       if ((id & IProblem.Javadoc) != 0) {
+               if (output == null) output = new StringBuffer(10+length+problemArguments.length*20);
+               output.append((String) this.messageTemplates.get(keyFromID(IProblem.JavadocMessagePrefix & IProblem.IgnoreCategoriesMask)));
+       }
+       while (true) {
+               if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes, start)) > -1) {
+                       if (output == null) output = new StringBuffer(length+problemArguments.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(problemArguments[index]);
+                               } catch (NumberFormatException nfe) {
+                                       output.append(messageWithNoDoubleQuotes, end + 1, start - end);
+                               } catch (ArrayIndexOutOfBoundsException e) {
+                                       return "Cannot bind message for problem (id: " //$NON-NLS-1$
+                                               + (id & IProblem.IgnoreCategoriesMask)
+                                               + ") \""  //$NON-NLS-1$
+                                               + message
+                                               + "\" with arguments: {" //$NON-NLS-1$
+                                               + Util.toString(problemArguments)
+                                               +"}"; //$NON-NLS-1$
+                               }
+                               start++;
+                       } else {
+                               output.append(messageWithNoDoubleQuotes, end, length);
+                               break;
+                       }
+               } else {
+                       if (output == null) return new String(messageWithNoDoubleQuotes);
+                       output.append(messageWithNoDoubleQuotes, start, length - start);
+                       break;
+               }
+       }
+
+       return output.toString();
+}
+/**
+ * @param problem org.eclipse.jdt.internal.compiler.IProblem
+ * @return String
+ */
+public final String localizedMessage(IProblem problem) {
+       return getLocalizedMessage(problem.getID(), problem.getArguments());
+}
+
+/**
+ * This method initializes the MessageTemplates class variable according
+ * to the current Locale.
+ * @param loc Locale
+ * @return HashtableOfInt
+ */
+public static HashtableOfInt loadMessageTemplates(Locale loc) {
+       ResourceBundle bundle = null;
+       String bundleName = "org.eclipse.jdt.internal.compiler.problem.messages"; //$NON-NLS-1$
+       try {
+               bundle = ResourceBundle.getBundle(bundleName, loc); 
+       } catch(MissingResourceException e) {
+               System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + loc); //$NON-NLS-1$//$NON-NLS-2$
+               throw e;
+       }
+       HashtableOfInt templates = new HashtableOfInt(700);
+       Enumeration keys = bundle.getKeys();
+       while (keys.hasMoreElements()) {
+           String key = (String)keys.nextElement();
+           try {
+               int messageID = Integer.parseInt(key);
+                       templates.put(keyFromID(messageID), bundle.getString(key));
+           } catch(NumberFormatException e) {
+               // key ill-formed
+               } catch (MissingResourceException e) {
+                       // available ID
+           }
+       }
+       return templates;
+}
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java b/src/java/org/eclipse/jdt/internal/compiler/problem/ProblemHandler.java
new file mode 100644 (file)
index 0000000..5b334d2
--- /dev/null
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * 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.problem;
+
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
+import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
+import org.eclipse.jdt.internal.compiler.IProblemFactory;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+
+/*
+ * Compiler error handler, responsible to determine whether
+ * a problem is actually a warning or an error; also will
+ * decide whether the compilation task can be processed further or not.
+ *
+ * Behavior : will request its current policy if need to stop on
+ *     first error, and if should proceed (persist) with problems.
+ */
+
+public class ProblemHandler implements ProblemSeverities {
+
+       public final static String[] NoArgument = new String[0];
+       
+       final public IErrorHandlingPolicy policy;
+       public final IProblemFactory problemFactory;
+       public final CompilerOptions options;
+/*
+ * Problem handler can be supplied with a policy to specify
+ * its behavior in error handling. Also see static methods for
+ * built-in policies.
+ *
+ */
+public ProblemHandler(IErrorHandlingPolicy policy, CompilerOptions options, IProblemFactory problemFactory) {
+       this.policy = policy;
+       this.problemFactory = problemFactory;
+       this.options = options;
+}
+/*
+ * Given the current configuration, answers which category the problem
+ * falls into:
+ *             Error | Warning | Ignore
+ */
+public int computeSeverity(int problemId){
+       
+       return Error; // by default all problems are errors
+}
+public IProblem createProblem(
+       char[] fileName, 
+       int problemId, 
+       String[] problemArguments, 
+       String[] messageArguments,
+       int severity, 
+       int problemStartPosition, 
+       int problemEndPosition, 
+       int lineNumber) {
+
+       return this.problemFactory.createProblem(
+               fileName, 
+               problemId, 
+               problemArguments, 
+               messageArguments,
+               severity, 
+               problemStartPosition, 
+               problemEndPosition, 
+               lineNumber); 
+}
+public void handle(
+       int problemId, 
+       String[] problemArguments, 
+       String[] messageArguments,
+       int severity, 
+       int problemStartPosition, 
+       int problemEndPosition, 
+       ReferenceContext referenceContext, 
+       CompilationResult unitResult) {
+
+       if (severity == Ignore)
+               return;
+
+       // if no reference context, we need to abort from the current compilation process
+       if (referenceContext == null) {
+               if ((severity & Error) != 0) { // non reportable error is fatal
+                       IProblem problem = this.createProblem(null,     problemId,      problemArguments, messageArguments, severity, 0, 0, 0);                 
+                       throw new AbortCompilation(null, problem);
+               } else {
+                       return; // ignore non reportable warning
+               }
+       }
+
+       IProblem problem = 
+               this.createProblem(
+                       unitResult.getFileName(), 
+                       problemId, 
+                       problemArguments, 
+                       messageArguments,
+                       severity, 
+                       problemStartPosition, 
+                       problemEndPosition, 
+                       problemStartPosition >= 0
+                               ? searchLineNumber(unitResult.lineSeparatorPositions, problemStartPosition)
+                               : 0);
+       if (problem == null) return; // problem couldn't be created, ignore
+       
+       switch (severity & Error) {
+               case Error :
+                       this.record(problem, unitResult, referenceContext);
+                       referenceContext.tagAsHavingErrors();
+
+                       // should abort ?
+                       int abortLevel;
+                       if ((abortLevel = 
+                               (this.policy.stopOnFirstError() ? AbortCompilation : severity & Abort)) != 0) {
+
+                               referenceContext.abort(abortLevel, problem);
+                       }
+                       break;
+               case Warning :
+                       this.record(problem, unitResult, referenceContext);
+                       break;
+       }
+}
+/**
+ * Standard problem handling API, the actual severity (warning/error/ignore) is deducted
+ * from the problem ID and the current compiler options.
+ */
+public void handle(
+       int problemId, 
+       String[] problemArguments, 
+       String[] messageArguments,
+       int problemStartPosition, 
+       int problemEndPosition, 
+       ReferenceContext referenceContext, 
+       CompilationResult unitResult) {
+
+       this.handle(
+               problemId,
+               problemArguments,
+               messageArguments,
+               this.computeSeverity(problemId), // severity inferred using the ID
+               problemStartPosition,
+               problemEndPosition,
+               referenceContext,
+               unitResult);
+}
+public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
+       unitResult.record(problem, referenceContext);
+}
+/**
+ * Search the line number corresponding to a specific position
+ */
+public static final int searchLineNumber(int[] startLineIndexes, int position) {
+       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;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/src/java/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
new file mode 100644 (file)
index 0000000..ba31625
--- /dev/null
@@ -0,0 +1,4096 @@
+/*******************************************************************************
+ * 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.problem;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.*;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.parser.*;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ProblemReporter extends ProblemHandler implements ProblemReasons {
+       
+       public ReferenceContext referenceContext;
+       
+public ProblemReporter(IErrorHandlingPolicy policy, CompilerOptions options, IProblemFactory problemFactory) {
+       super(policy, options, problemFactory);
+}
+public void abortDueToInternalError(String errorMessage) {
+       String[] arguments = new String[] {errorMessage};
+       this.handle(
+               IProblem.Unclassified,
+               arguments,
+               arguments,
+               Error | Abort,
+               0,
+               0);
+}
+public void abortDueToInternalError(String errorMessage, ASTNode location) {
+       String[] arguments = new String[] {errorMessage};
+       this.handle(
+               IProblem.Unclassified,
+               arguments,
+               arguments,
+               Error | Abort,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void abstractMethodCannotBeOverridden(SourceTypeBinding type, MethodBinding concreteMethod) {
+
+       this.handle(
+               // %1 must be abstract since it cannot override the inherited package-private abstract method %2
+               IProblem.AbstractMethodCannotBeOverridden,
+               new String[] {
+                       new String(type.sourceName()), 
+                       new String(
+                                       CharOperation.concat(
+                                               concreteMethod.declaringClass.readableName(),
+                                               concreteMethod.readableName(),
+                                               '.'))},
+               new String[] {
+                       new String(type.sourceName()), 
+                       new String(
+                                       CharOperation.concat(
+                                               concreteMethod.declaringClass.shortReadableName(),
+                                               concreteMethod.shortReadableName(),
+                                               '.'))},
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void abstractMethodInAbstractClass(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {
+
+       String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+       this.handle(
+               IProblem.AbstractMethodInAbstractClass,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void abstractMethodMustBeImplemented(SourceTypeBinding type, MethodBinding abstractMethod) {
+       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.AbstractMethodMustBeImplemented,
+               new String[] {
+                       new String(
+                               CharOperation.concat(
+                                       abstractMethod.declaringClass.readableName(),
+                                       abstractMethod.readableName(),
+                                       '.'))},
+               new String[] {
+                       new String(
+                               CharOperation.concat(
+                                       abstractMethod.declaringClass.shortReadableName(),
+                                       abstractMethod.shortReadableName(),
+                                       '.'))},
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void abstractMethodNeedingNoBody(AbstractMethodDeclaration method) {
+       this.handle(
+               IProblem.BodyForAbstractMethod,
+               NoArgument,
+               NoArgument,
+               method.sourceStart,
+               method.sourceEnd,
+               method,
+               method.compilationResult());
+}
+public void alreadyDefinedLabel(char[] labelName, ASTNode location) {
+       String[] arguments = new String[] {new String(labelName)};
+       this.handle(
+               IProblem.DuplicateLabel,
+               arguments,
+               arguments,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void anonymousClassCannotExtendFinalClass(Expression expression, TypeBinding type) {
+       this.handle(
+               IProblem.AnonymousClassCannotExtendFinalClass,
+               new String[] {new String(type.readableName())},
+               new String[] {new String(type.shortReadableName())},
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void argumentTypeCannotBeVoid(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, Argument arg) {
+       String[] arguments = new String[] {new String(methodDecl.selector), new String(arg.name)};
+       this.handle(
+               IProblem.ArgumentTypeCannotBeVoid,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void argumentTypeCannotBeVoidArray(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, Argument arg) {
+       String[] arguments = new String[] {new String(methodDecl.selector), new String(arg.name)};
+       this.handle(
+               IProblem.ArgumentTypeCannotBeVoidArray,
+               arguments,
+               arguments,
+               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,
+               NoArgument,
+               NoArgument,
+               sourceStart,
+               sourceEnd);
+}
+public void assignmentHasNoEffect(Assignment assignment, char[] name){
+       String[] arguments = new String[] { new String(name) }; 
+       this.handle(
+                       IProblem.AssignmentHasNoEffect,
+                       arguments,
+                       arguments,
+                       assignment.sourceStart,
+                       assignment.sourceEnd);
+}
+public void attemptToReturnNonVoidExpression(ReturnStatement returnStatement, TypeBinding expectedType) {
+       this.handle(
+               IProblem.VoidMethodReturnsValue,
+               new String[] {new String(expectedType.readableName())},
+               new String[] {new String(expectedType.shortReadableName())},
+               returnStatement.sourceStart,
+               returnStatement.sourceEnd);
+}
+public void attemptToReturnVoidValue(ReturnStatement returnStatement) {
+       this.handle(
+               IProblem.MethodReturnsVoid,
+               NoArgument,
+               NoArgument,
+               returnStatement.sourceStart,
+               returnStatement.sourceEnd);
+}
+public void bytecodeExceeds64KLimit(AbstractMethodDeclaration location) {
+       String[] arguments = new String[] {new String(location.selector), parametersAsString(location.binding)};
+       if (location.isConstructor()) {
+               this.handle(
+                       IProblem.BytecodeExceeds64KLimitForConstructor,
+                       arguments,
+                       arguments,
+                       Error | Abort,
+                       location.sourceStart,
+                       location.sourceEnd);
+       } else {
+               this.handle(
+                       IProblem.BytecodeExceeds64KLimit,
+                       arguments,
+                       arguments,
+                       Error | Abort,
+                       location.sourceStart,
+                       location.sourceEnd);
+       }
+}
+public void bytecodeExceeds64KLimit(TypeDeclaration location) {
+       this.handle(
+               IProblem.BytecodeExceeds64KLimitForClinit,
+               NoArgument,
+               NoArgument,
+               Error | Abort,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void cannotAllocateVoidArray(Expression expression) {
+       this.handle(
+               IProblem.CannotAllocateVoidArray,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void cannotAssignToFinalField(FieldBinding field, ASTNode location) {
+       this.handle(
+               IProblem.FinalFieldAssignment,
+               new String[] {
+                       (field.declaringClass == null ? "array" : new String(field.declaringClass.readableName())), //$NON-NLS-1$
+                       new String(field.readableName())},
+               new String[] {
+                       (field.declaringClass == null ? "array" : new String(field.declaringClass.shortReadableName())), //$NON-NLS-1$
+                       new String(field.shortReadableName())},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void cannotAssignToFinalLocal(LocalVariableBinding local, ASTNode location) {
+       String[] arguments = new String[] { new String(local.readableName())};
+       this.handle(
+               IProblem.NonBlankFinalLocalAssignment,
+               arguments,
+               arguments,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void cannotAssignToFinalOuterLocal(LocalVariableBinding local, ASTNode location) {
+       String[] arguments = new String[] {new String(local.readableName())};
+       this.handle(
+               IProblem.FinalOuterLocalAssignment,
+               arguments,
+               arguments,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void cannotDeclareLocalInterface(char[] interfaceName, int sourceStart, int sourceEnd) {
+       String[] arguments = new String[] {new String(interfaceName)};
+       this.handle(
+               IProblem.CannotDefineInterfaceInLocalType,
+               arguments,
+               arguments,
+               sourceStart,
+               sourceEnd);
+}
+public void cannotDefineDimensionsAndInitializer(ArrayAllocationExpression expresssion) {
+       this.handle(
+               IProblem.CannotDefineDimensionExpressionsWithInit,
+               NoArgument,
+               NoArgument,
+               expresssion.sourceStart,
+               expresssion.sourceEnd);
+}
+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)},
+               messageSend.sourceStart,
+               messageSend.sourceEnd);
+}
+public void cannotImportPackage(ImportReference importRef) {
+       String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
+       this.handle(
+               IProblem.CannotImportPackage,
+               arguments,
+               arguments,
+               importRef.sourceStart,
+               importRef.sourceEnd);
+}
+public void cannotInstantiate(TypeReference typeRef, TypeBinding type) {
+       this.handle(
+               IProblem.InvalidClassInstantiation,
+               new String[] {new String(type.readableName())},
+               new String[] {new String(type.shortReadableName())},
+               typeRef.sourceStart,
+               typeRef.sourceEnd);
+}
+public void cannotReferToNonFinalOuterLocal(LocalVariableBinding local, ASTNode location) {
+       String[] arguments =new String[]{ new String(local.readableName())};
+       this.handle(
+               IProblem.OuterLocalMustBeFinal,
+               arguments,
+               arguments,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void cannotReturnInInitializer(ASTNode location) {
+       this.handle(
+               IProblem.CannotReturnInInitializer,
+               NoArgument,
+               NoArgument,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void cannotThrowNull(ThrowStatement statement) {
+       this.handle(
+               IProblem.CannotThrowNull,
+               NoArgument,
+               NoArgument,
+               statement.sourceStart,
+               statement.sourceEnd);
+}
+public void cannotThrowType(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, TypeReference exceptionType, TypeBinding expectedType) {
+       this.handle(
+               IProblem.CannotThrowType,
+               new String[] {new String(expectedType.readableName())},
+               new String[] {new String(expectedType.shortReadableName())},
+               exceptionType.sourceStart,
+               exceptionType.sourceEnd);
+}
+public void cannotUseSuperInJavaLangObject(ASTNode reference) {
+       this.handle(
+               IProblem.ObjectHasNoSuperclass,
+               NoArgument,
+               NoArgument,
+               reference.sourceStart,
+               reference.sourceEnd);
+}
+public void cannotUseSuperInCodeSnippet(int start, int end) {
+       this.handle(
+               IProblem.CannotUseSuperInCodeSnippet,
+               NoArgument,
+               NoArgument,
+               Error | Abort,
+               start,
+               end);
+}
+public void caseExpressionMustBeConstant(Expression expression) {
+       this.handle(
+               IProblem.NonConstantExpression,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void classExtendFinalClass(SourceTypeBinding type, TypeReference superclass, TypeBinding expectedType) {
+       String name = new String(type.sourceName());
+       String expectedFullName = new String(expectedType.readableName());
+       String expectedShortName = new String(expectedType.shortReadableName());
+       if (expectedShortName.equals(name)) expectedShortName = expectedFullName;
+       this.handle(
+               IProblem.ClassExtendFinalClass,
+               new String[] {expectedFullName, name},
+               new String[] {expectedShortName, name},
+               superclass.sourceStart,
+               superclass.sourceEnd);
+}
+public void codeSnippetMissingClass(String missing, int start, int end) {
+       String[] arguments = new String[]{missing};
+       this.handle(
+               IProblem.CodeSnippetMissingClass,
+               arguments,
+               arguments,
+               Error | Abort,
+               start,
+               end);
+}
+public void codeSnippetMissingMethod(String className, String missingMethod, String argumentTypes, int start, int end) {
+       String[] arguments = new String[]{ className, missingMethod, argumentTypes };
+       this.handle(
+               IProblem.CodeSnippetMissingMethod,
+               arguments,
+               arguments,
+               Error | Abort,
+               start,
+               end);
+}
+/*
+ * Given the current configuration, answers which category the problem
+ * falls into:
+ *             Error | Warning | Ignore
+ */
+public int computeSeverity(int problemId){
+
+       // severity can have been preset on the problem
+//     if ((problem.severity & Fatal) != 0){
+//             return Error;
+//     }
+
+       // if not then check whether it is a configurable problem
+       switch(problemId){
+
+               case IProblem.MaskedCatch : 
+                       return this.options.getSeverity(CompilerOptions.MaskedCatchBlock);
+
+               case IProblem.UnusedImport :
+                       return this.options.getSeverity(CompilerOptions.UnusedImport);
+                       
+               case IProblem.MethodButWithConstructorName :
+                       return this.options.getSeverity(CompilerOptions.MethodWithConstructorName);
+               
+               case IProblem.OverridingNonVisibleMethod :
+                       return this.options.getSeverity(CompilerOptions.OverriddenPackageDefaultMethod);
+
+               case IProblem.IncompatibleReturnTypeForNonInheritedInterfaceMethod :
+               case IProblem.IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod :
+                       return this.options.getSeverity(CompilerOptions.IncompatibleNonInheritedInterfaceMethod);
+
+               case IProblem.OverridingDeprecatedMethod :                              
+               case IProblem.UsingDeprecatedType :                             
+               case IProblem.UsingDeprecatedMethod :
+               case IProblem.UsingDeprecatedConstructor :
+               case IProblem.UsingDeprecatedField :
+                       return this.options.getSeverity(CompilerOptions.UsingDeprecatedAPI);
+               
+               case IProblem.LocalVariableIsNeverUsed :
+                       return this.options.getSeverity(CompilerOptions.UnusedLocalVariable);
+               
+               case IProblem.ArgumentIsNeverUsed :
+                       return this.options.getSeverity(CompilerOptions.UnusedArgument);
+
+               case IProblem.NoImplicitStringConversionForCharArrayExpression :
+                       return this.options.getSeverity(CompilerOptions.NoImplicitStringConversion);
+
+               case IProblem.NeedToEmulateFieldReadAccess :
+               case IProblem.NeedToEmulateFieldWriteAccess :
+               case IProblem.NeedToEmulateMethodAccess :
+               case IProblem.NeedToEmulateConstructorAccess :                  
+                       return this.options.getSeverity(CompilerOptions.AccessEmulation);
+
+               case IProblem.NonExternalizedStringLiteral :
+                       return this.options.getSeverity(CompilerOptions.NonExternalizedString);
+
+               case IProblem.UseAssertAsAnIdentifier :
+                       return this.options.getSeverity(CompilerOptions.AssertUsedAsAnIdentifier);
+
+               case IProblem.NonStaticAccessToStaticMethod :
+               case IProblem.NonStaticAccessToStaticField :
+                       return this.options.getSeverity(CompilerOptions.NonStaticAccessToStatic);
+
+               case IProblem.IndirectAccessToStaticMethod :
+               case IProblem.IndirectAccessToStaticField :
+               case IProblem.IndirectAccessToStaticType :
+                       return this.options.getSeverity(CompilerOptions.IndirectStaticAccess);
+
+               case IProblem.AssignmentHasNoEffect:
+                       return this.options.getSeverity(CompilerOptions.NoEffectAssignment);
+
+               case IProblem.UnusedPrivateConstructor:
+               case IProblem.UnusedPrivateMethod:
+               case IProblem.UnusedPrivateField:
+               case IProblem.UnusedPrivateType:
+                       return this.options.getSeverity(CompilerOptions.UnusedPrivateMember);
+
+               case IProblem.Task :
+                       return Warning;                 
+
+               case IProblem.LocalVariableHidingLocalVariable:
+               case IProblem.LocalVariableHidingField:
+               case IProblem.ArgumentHidingLocalVariable:
+               case IProblem.ArgumentHidingField:
+                       return this.options.getSeverity(CompilerOptions.LocalVariableHiding);
+
+               case IProblem.FieldHidingLocalVariable:
+               case IProblem.FieldHidingField:
+                       return this.options.getSeverity(CompilerOptions.FieldHiding);
+
+               case IProblem.PossibleAccidentalBooleanAssignment:
+                       return this.options.getSeverity(CompilerOptions.AccidentalBooleanAssign);
+
+               case IProblem.SuperfluousSemicolon:
+               case IProblem.EmptyControlFlowStatement:
+                       return this.options.getSeverity(CompilerOptions.EmptyStatement);
+
+               case IProblem.UndocumentedEmptyBlock:
+                       return this.options.getSeverity(CompilerOptions.UndocumentedEmptyBlock);
+                       
+               case IProblem.UnnecessaryCast:
+               case IProblem.UnnecessaryArgumentCast:
+               case IProblem.UnnecessaryInstanceof:
+                       return this.options.getSeverity(CompilerOptions.UnnecessaryTypeCheck);
+                       
+               case IProblem.FinallyMustCompleteNormally:
+                       return this.options.getSeverity(CompilerOptions.FinallyBlockNotCompleting);
+                       
+               case IProblem.UnusedMethodDeclaredThrownException:
+               case IProblem.UnusedConstructorDeclaredThrownException:
+                       return this.options.getSeverity(CompilerOptions.UnusedDeclaredThrownException);
+
+               case IProblem.UnqualifiedFieldAccess:
+                       return this.options.getSeverity(CompilerOptions.UnqualifiedFieldAccess);
+               
+               case IProblem.UnnecessaryElse:
+                       return this.options.getSeverity(CompilerOptions.UnnecessaryElse);
+
+               /*
+                * Javadoc syntax errors
+                */
+               // Javadoc explicit IDs
+               case IProblem.JavadocUnexpectedTag:
+               case IProblem.JavadocDuplicateReturnTag:
+               case IProblem.JavadocInvalidThrowsClass:
+               case IProblem.JavadocInvalidSeeReference:
+               case IProblem.JavadocMalformedSeeReference:
+               case IProblem.JavadocInvalidSeeHref:
+               case IProblem.JavadocInvalidSeeArgs:
+               case IProblem.JavadocInvalidTag:
+               case IProblem.JavadocUnterminatedInlineTag:
+                       if (this.options.docCommentSupport) {
+                               return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
+                       } else {
+                               return ProblemSeverities.Ignore;
+                       }
+
+               /*
+                * Javadoc tags resolved references errors
+                */
+               case IProblem.JavadocInvalidParamName:
+               case IProblem.JavadocDuplicateParamName:
+               case IProblem.JavadocMissingParamName:
+               case IProblem.JavadocInvalidThrowsClassName:
+               case IProblem.JavadocDuplicateThrowsClassName:
+               case IProblem.JavadocMissingThrowsClassName:
+               case IProblem.JavadocMissingSeeReference:
+               case IProblem.JavadocUsingDeprecatedField:
+               case IProblem.JavadocUsingDeprecatedConstructor:
+               case IProblem.JavadocUsingDeprecatedMethod:
+               case IProblem.JavadocUsingDeprecatedType:
+               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:
+               case IProblem.JavadocNoMessageSendOnBaseType:
+               case IProblem.JavadocInheritedMethodHidesEnclosingName:
+               case IProblem.JavadocInheritedFieldHidesEnclosingName:
+               case IProblem.JavadocInheritedNameHidesEnclosingTypeName:
+                       if (this.options.docCommentSupport && this.options.reportInvalidJavadocTags) {
+                               return this.options.getSeverity(CompilerOptions.InvalidJavadoc);
+                       } else {
+                               return ProblemSeverities.Ignore;
+                       }
+
+               /*
+                * Javadoc missing tags errors
+                */
+               case IProblem.JavadocMissingParamTag:
+               case IProblem.JavadocMissingReturnTag:
+               case IProblem.JavadocMissingThrowsTag:
+                       if (this.options.docCommentSupport) {
+                               return this.options.getSeverity(CompilerOptions.MissingJavadocTags);
+                       } else {
+                               return ProblemSeverities.Ignore;
+                       }
+
+               /*
+                * Missing Javadoc errors
+                */
+               case IProblem.JavadocMissing:
+                       if (this.options.docCommentSupport) {
+                               return this.options.getSeverity(CompilerOptions.MissingJavadocComments);
+                       } else {
+                               return ProblemSeverities.Ignore;
+                       }
+
+               // by default problems are errors.
+               default:
+                       return Error;
+       }
+}
+public void conditionalArgumentsIncompatibleTypes(ConditionalExpression expression, TypeBinding trueType, TypeBinding falseType) {
+       this.handle(
+               IProblem.IncompatibleTypesInConditionalOperator,
+               new String[] {new String(trueType.readableName()), new String(falseType.readableName())},
+               new String[] {new String(trueType.sourceName()), new String(falseType.sourceName())},
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void conflictingImport(ImportReference importRef) {
+       String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
+       this.handle(
+               IProblem.ConflictingImport,
+               arguments,
+               arguments,
+               importRef.sourceStart,
+               importRef.sourceEnd);
+}
+public void constantOutOfFormat(NumberLiteral literal) {
+       // the literal is not in a correct format
+       // this code is called on IntLiteral and LongLiteral 
+       // example 000811 ...the 8 is uncorrect.
+
+       if ((literal instanceof LongLiteral) || (literal instanceof IntLiteral)) {
+               char[] source = literal.source();
+               try {
+                       final String Radix;
+                       final int radix;
+                       if ((source[1] == 'x') || (source[1] == 'X')) {
+                               radix = 16;
+                               Radix = "Hex"; //$NON-NLS-1$
+                       } else {
+                               radix = 8;
+                               Radix = "Octal"; //$NON-NLS-1$
+                       }
+                       //look for the first digit that is incorrect
+                       int place = -1;
+                       label : for (int i = radix == 8 ? 1 : 2; i < source.length; i++) {
+                               if (Character.digit(source[i], radix) == -1) {
+                                       place = i;
+                                       break label;
+                               }
+                       }
+                       String[] arguments = new String[] {
+                               new String(literal.literalType(null).readableName()), // numeric literals do not need scope to reach type
+                               Radix + " " + new String(source) + " (digit " + new String(new char[] {source[place]}) + ")"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+                       this.handle(
+                               IProblem.NumericValueOutOfRange,
+                               arguments,
+                               arguments,
+                               literal.sourceStart,
+                               literal.sourceEnd);
+                       return;
+               } catch (IndexOutOfBoundsException ex) {
+                       // should never happen
+               }
+       
+               // just in case .... use a predefined error..
+               // we should never come here...(except if the code changes !)
+               this.constantOutOfRange(literal, literal.literalType(null)); // numeric literals do not need scope to reach type
+       }
+}
+public void constantOutOfRange(Literal literal, TypeBinding literalType) {
+       String[] arguments = new String[] {new String(literalType.readableName()), new String(literal.source())};
+       this.handle(
+               IProblem.NumericValueOutOfRange,
+               arguments,
+               arguments,
+               literal.sourceStart,
+               literal.sourceEnd);
+}
+public void deprecatedField(FieldBinding field, ASTNode location) {
+       this.handle(
+               IProblem.UsingDeprecatedField,
+               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 deprecatedMethod(MethodBinding method, ASTNode location) {
+       if (method.isConstructor()) {
+               this.handle(
+                       IProblem.UsingDeprecatedConstructor,
+                       new String[] {new String(method.declaringClass.readableName()), parametersAsString(method)},
+                       new String[] {new String(method.declaringClass.shortReadableName()), parametersAsShortString(method)},
+                       location.sourceStart,
+                       location.sourceEnd);
+       } else {
+               this.handle(
+                       IProblem.UsingDeprecatedMethod,
+                       new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
+                       new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+                       location.sourceStart,
+                       location.sourceEnd);
+       }
+}
+public void deprecatedType(TypeBinding type, ASTNode location) {
+       if (location == null) return; // 1G828DN - no type ref for synthetic arguments
+       this.handle(
+               IProblem.UsingDeprecatedType,
+               new String[] {new String(type.readableName())},
+               new String[] {new String(type.shortReadableName())},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void duplicateCase(CaseStatement caseStatement) {
+       this.handle(
+               IProblem.DuplicateCase,
+               NoArgument,
+               NoArgument,
+               caseStatement.sourceStart,
+               caseStatement.sourceEnd);
+}
+public void duplicateDefaultCase(ASTNode statement) {
+       this.handle(
+               IProblem.DuplicateDefaultCase,
+               NoArgument,
+               NoArgument,
+               statement.sourceStart,
+               statement.sourceEnd);
+}
+public void duplicateFieldInType(SourceTypeBinding type, FieldDeclaration fieldDecl) {
+       this.handle(
+               IProblem.DuplicateField,
+               new String[] {new String(type.sourceName()), new String(fieldDecl.name)},
+               new String[] {new String(type.shortReadableName()), new String(fieldDecl.name)},
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void duplicateImport(ImportReference importRef) {
+       String[] arguments = new String[] {CharOperation.toString(importRef.tokens)};
+       this.handle(
+               IProblem.DuplicateImport,
+               arguments,
+               arguments,
+               importRef.sourceStart,
+               importRef.sourceEnd);
+}
+public void duplicateInitializationOfBlankFinalField(FieldBinding field, Reference reference) {
+       String[] arguments = new String[]{ new String(field.readableName())};
+       this.handle(
+               IProblem.DuplicateBlankFinalFieldInitialization,
+               arguments,
+               arguments,
+               reference.sourceStart,
+               reference.sourceEnd);
+}
+public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, ASTNode location) {
+       String[] arguments = new String[] { new String(local.readableName())};
+       this.handle(
+               IProblem.DuplicateFinalLocalInitialization,
+               arguments,
+               arguments,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void duplicateMethodInType(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(methodDecl.selector), new String(type.sourceName())};
+       this.handle(
+               IProblem.DuplicateMethod,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void duplicateModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+/* to highlight modifiers use:
+       this.handle(
+               new Problem(
+                       DuplicateModifierForField,
+                       new String[] {new String(fieldDecl.name)},
+                       fieldDecl.modifiers.sourceStart,
+                       fieldDecl.modifiers.sourceEnd));
+*/
+       String[] arguments = new String[] {new String(fieldDecl.name)};
+       this.handle(
+               IProblem.DuplicateModifierForField,
+               arguments,
+               arguments,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void duplicateModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+       this.handle(
+               IProblem.DuplicateModifierForMethod,
+               new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+               new String[] {new String(type.shortReadableName()), new String(methodDecl.selector)},
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void duplicateModifierForType(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.DuplicateModifierForType,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void duplicateModifierForVariable(LocalDeclaration localDecl, boolean complainForArgument) {
+       String[] arguments = new String[] {new String(localDecl.name)};
+       this.handle(
+               complainForArgument
+                       ? IProblem.DuplicateModifierForArgument 
+                       : IProblem.DuplicateModifierForVariable,
+               arguments,
+               arguments,
+               localDecl.sourceStart,
+               localDecl.sourceEnd);
+}
+public void duplicateNestedType(TypeDeclaration typeDecl) {
+       String[] arguments = new String[] {new String(typeDecl.name)};
+       this.handle(
+               IProblem.DuplicateNestedType,
+               arguments,
+               arguments,
+               typeDecl.sourceStart,
+               typeDecl.sourceEnd);
+}
+public void duplicateSuperinterface(SourceTypeBinding type, TypeDeclaration typeDecl, ReferenceBinding superType) {
+       this.handle(
+               IProblem.DuplicateSuperInterface,
+               new String[] {
+                       new String(superType.readableName()),
+                       new String(type.sourceName())},
+               new String[] {
+                       new String(superType.shortReadableName()),
+                       new String(type.sourceName())},
+               typeDecl.sourceStart,
+               typeDecl.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
+       this.handle(
+               IProblem.DuplicateTypes,
+               arguments,
+               arguments,
+               typeDecl.sourceStart,
+               typeDecl.sourceEnd,
+               compUnitDecl.compilationResult);
+}
+public void emptyControlFlowStatement(int sourceStart, int sourceEnd) {
+       this.handle(
+               IProblem.EmptyControlFlowStatement,
+               NoArgument,
+               NoArgument,
+               sourceStart,
+               sourceEnd);     
+}
+public void errorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params) {
+       StringBuffer buffer = new StringBuffer();
+       StringBuffer shortBuffer = new StringBuffer();
+       for (int i = 0, length = params.length; i < length; i++) {
+               if (i != 0){
+                       buffer.append(", "); //$NON-NLS-1$
+                       shortBuffer.append(", "); //$NON-NLS-1$
+               }
+               buffer.append(new String(params[i].readableName()));
+               shortBuffer.append(new String(params[i].shortReadableName()));
+       }
+
+       int id = recType.isArrayType() ? IProblem.NoMessageSendOnArrayType : IProblem.NoMessageSendOnBaseType;
+       /*
+       if ((messageSend.bits & ASTNode.InsideJavadoc) != 0) {
+               id |= IProblem.Javadoc;
+               if (!reportInvalidJavadocTagsVisibility()) return;
+       }
+       */
+       this.handle(
+               id,
+               new String[] {new String(recType.readableName()), new String(messageSend.selector), buffer.toString()},
+               new String[] {new String(recType.shortReadableName()), new String(messageSend.selector), shortBuffer.toString()},
+               messageSend.sourceStart,
+               messageSend.sourceEnd);
+}
+public void errorThisSuperInStatic(ASTNode reference) {
+       String[] arguments = new String[] {reference.isSuper() ? "super" : "this"}; //$NON-NLS-2$ //$NON-NLS-1$
+       this.handle(
+               IProblem.ThisInStaticContext,
+               arguments,
+               arguments,
+               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 expressionShouldBeAVariable(Expression expression) {
+       this.handle(
+               IProblem.ExpressionShouldBeAVariable,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void fieldHiding(FieldDeclaration fieldDecl, Binding hiddenVariable) {
+       FieldBinding field = fieldDecl.binding;
+       if (CharOperation.equals(TypeConstants.SERIALVERSIONUID, field.name)
+                       && field.isStatic()
+                       && field.isFinal()
+                       && BaseTypes.LongBinding == field.type) {
+                               return; // do not report unused serialVersionUID field
+       }
+       if (CharOperation.equals(TypeConstants.SERIALPERSISTENTFIELDS, field.name)
+                       && field.isStatic()
+                       && field.isFinal()
+                       && field.type.dimensions() == 1
+                       && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTSTREAMFIELD, field.type.leafComponentType().readableName())) {
+                               return; // do not report unused serialPersistentFields field
+       }
+       
+       if (hiddenVariable instanceof LocalVariableBinding) {
+               this.handle(
+                       IProblem.FieldHidingLocalVariable,
+                       new String[] {new String(field.declaringClass.readableName()), new String(field.name) },
+                       new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name) },
+                       fieldDecl.sourceStart,
+                       fieldDecl.sourceEnd);
+       } else if (hiddenVariable instanceof FieldBinding) {
+               FieldBinding hiddenField = (FieldBinding) hiddenVariable;
+               this.handle(
+                       IProblem.FieldHidingField,
+                       new String[] {new String(field.declaringClass.readableName()), new String(field.name) , new String(hiddenField.declaringClass.readableName())  },
+                       new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name) , new String(hiddenField.declaringClass.shortReadableName()) },
+                       fieldDecl.sourceStart,
+                       fieldDecl.sourceEnd);
+       }
+}
+private int fieldLocation(FieldBinding field, ASTNode node) {
+       if (node instanceof QualifiedNameReference) {
+               QualifiedNameReference ref = (QualifiedNameReference) node;
+               FieldBinding[] bindings = ref.otherBindings;
+               if (bindings != null)
+                       for (int i = bindings.length; --i >= 0;)
+                               if (bindings[i] == field)
+                                       return (int) ref.sourcePositions[i + 1]; // first position is for the primary field
+       }
+       return node.sourceEnd;
+}
+public void fieldsOrThisBeforeConstructorInvocation(ThisReference reference) {
+       this.handle(
+               IProblem.ThisSuperDuringConstructorInvocation,
+               NoArgument,
+               NoArgument,
+               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,
+               NoArgument,
+               NoArgument,
+               finallyBlock.sourceStart,
+               finallyBlock.sourceEnd);
+}
+public void finalMethodCannotBeOverridden(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+       this.handle(
+               // Cannot override the final method from %1
+               // 8.4.3.3 - Final methods cannot be overridden or hidden.
+               IProblem.FinalMethodCannotBeOverridden,
+               new String[] {new String(inheritedMethod.declaringClass.readableName())},
+               new String[] {new String(inheritedMethod.declaringClass.shortReadableName())},
+               currentMethod.sourceStart(),
+               currentMethod.sourceEnd());
+}
+public void forwardReference(Reference reference, int indexInQualification, TypeBinding type) {
+       this.handle(
+               IProblem.ReferenceToForwardField,
+               NoArgument,
+               NoArgument,
+               reference.sourceStart,
+               reference.sourceEnd);
+}
+// use this private API when the compilation unit result can be found through the
+// reference context. Otherwise, use the other API taking a problem and a compilation result
+// as arguments
+private void handle(
+       int problemId, 
+       String[] problemArguments,
+       String[] messageArguments,
+       int problemStartPosition, 
+       int problemEndPosition){
+
+       this.handle(
+                       problemId,
+                       problemArguments,
+                       messageArguments,
+                       problemStartPosition,
+                       problemEndPosition,
+                       this.referenceContext, 
+                       this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
+       this.referenceContext = null;
+}
+// use this private API when the compilation unit result can be found through the
+// reference context. Otherwise, use the other API taking a problem and a compilation result
+// as arguments
+private void handle(
+       int problemId, 
+       String[] problemArguments,
+       String[] messageArguments,
+       int severity,
+       int problemStartPosition, 
+       int problemEndPosition){
+
+       this.handle(
+                       problemId,
+                       problemArguments,
+                       messageArguments,
+                       severity,
+                       problemStartPosition,
+                       problemEndPosition,
+                       this.referenceContext, 
+                       this.referenceContext == null ? null : this.referenceContext.compilationResult()); 
+       this.referenceContext = null;
+}
+// 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 problemStartPosition, 
+       int problemEndPosition,
+       CompilationResult unitResult){
+
+       this.handle(
+                       problemId,
+                       problemArguments,
+                       messageArguments,
+                       problemStartPosition,
+                       problemEndPosition,
+                       this.referenceContext, 
+                       unitResult); 
+       this.referenceContext = null;
+}
+public void hiddenCatchBlock(ReferenceBinding exceptionType, ASTNode location) {
+       this.handle(
+               IProblem.MaskedCatch,
+               new String[] {
+                       new String(exceptionType.readableName()),
+                }, 
+               new String[] {
+                       new String(exceptionType.shortReadableName()),
+                }, 
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void hidingEnclosingType(TypeDeclaration typeDecl) {
+       String[] arguments = new String[] {new String(typeDecl.name)};
+       this.handle(
+               IProblem.HidingEnclosingType,
+               arguments,
+               arguments,
+               typeDecl.sourceStart,
+               typeDecl.sourceEnd);
+}
+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},
+                       start,
+                       end);
+       else
+               this.handle(
+                       IProblem.HierarchyCircularity,
+                       new String[] {new String(sourceType.sourceName()), typeName},
+                       new String[] {new String(sourceType.sourceName()), shortTypeName},
+                       start,
+                       end);
+}
+public void hierarchyHasProblems(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.HierarchyHasProblems,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalAbstractModifierCombinationForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+       this.handle(
+               IProblem.IllegalAbstractModifierCombinationForMethod,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void illegalModifierCombinationFinalAbstractForClass(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalModifierCombinationFinalAbstractForClass,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalModifierCombinationFinalVolatileForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+       String[] arguments = new String[] {new String(fieldDecl.name)};
+
+       this.handle(
+               IProblem.IllegalModifierCombinationFinalVolatileForField,
+               arguments,
+               arguments,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+
+public void illegalModifierForClass(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalModifierForClass,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+       String[] arguments = new String[] {new String(fieldDecl.name)};
+       this.handle(
+               IProblem.IllegalModifierForField,
+               arguments,
+               arguments,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void illegalModifierForInterface(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalModifierForInterface,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalModifierForInterfaceField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+       String[] arguments = new String[] {new String(fieldDecl.name)};
+       this.handle(
+               IProblem.IllegalModifierForInterfaceField,
+               arguments,
+               arguments,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void illegalModifierForInterfaceMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+       this.handle(
+               IProblem.IllegalModifierForInterfaceMethod,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void illegalModifierForLocalClass(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalModifierForLocalClass,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalModifierForMemberClass(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalModifierForMemberClass,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalModifierForMemberInterface(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalModifierForMemberInterface,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+       this.handle(
+               IProblem.IllegalModifierForMethod,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void illegalModifierForVariable(LocalDeclaration localDecl, boolean complainAsArgument) {
+       String[] arguments = new String[] {new String(localDecl.name)};
+       this.handle(
+               complainAsArgument
+                       ? IProblem.IllegalModifierForArgument
+                       : IProblem.IllegalModifierForVariable,
+               arguments,
+               arguments,
+               localDecl.sourceStart,
+               localDecl.sourceEnd);
+}
+public void illegalPrimitiveOrArrayTypeForEnclosingInstance(TypeBinding enclosingType, ASTNode location) {
+       this.handle(
+               IProblem.IllegalPrimitiveOrArrayTypeForEnclosingInstance,
+               new String[] {new String(enclosingType.readableName())},
+               new String[] {new String(enclosingType.shortReadableName())},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void illegalStaticModifierForMemberType(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalStaticModifierForMemberType,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalVisibilityModifierCombinationForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+       String[] arguments = new String[] {new String(fieldDecl.name)};
+       this.handle(
+               IProblem.IllegalVisibilityModifierCombinationForField,
+               arguments,
+               arguments,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void illegalVisibilityModifierCombinationForMemberType(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalVisibilityModifierCombinationForMemberType,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalVisibilityModifierCombinationForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+       this.handle(
+               IProblem.IllegalVisibilityModifierCombinationForMethod,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void illegalVisibilityModifierForInterfaceMemberType(SourceTypeBinding type) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+       this.handle(
+               IProblem.IllegalVisibilityModifierForInterfaceMemberType,
+               arguments,
+               arguments,
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void illegalVoidExpression(ASTNode location) {
+       this.handle(
+               IProblem.InvalidVoidExpression,
+               NoArgument,
+               NoArgument,
+               location.sourceStart,
+               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;
+       }
+       char[][] tokens = expectedImport instanceof ProblemReferenceBinding
+               ? ((ProblemReferenceBinding) expectedImport).compoundName
+               : importRef.tokens;
+       String[] arguments = new String[]{CharOperation.toString(tokens)};
+       this.handle(id, arguments, arguments, importRef.sourceStart, (int) importRef.sourcePositions[tokens.length - 1]);
+}
+public void incompatibleExceptionInThrowsClause(SourceTypeBinding type, MethodBinding currentMethod, MethodBinding inheritedMethod, ReferenceBinding exceptionType) {
+       if (type == currentMethod.declaringClass) {
+               int id;
+               if (currentMethod.declaringClass.isInterface() 
+                               && !inheritedMethod.isPublic()){ // interface inheriting Object protected method
+                       id = IProblem.IncompatibleExceptionInThrowsClauseForNonInheritedInterfaceMethod;
+               } else {
+                       id = IProblem.IncompatibleExceptionInThrowsClause;
+               }
+               this.handle(
+                       // Exception %1 is not compatible with throws clause in %2
+                       // 9.4.4 - The type of exception in the throws clause is incompatible.
+                       id,
+                       new String[] {
+                               new String(exceptionType.sourceName()),
+                               new String(
+                                       CharOperation.concat(
+                                               inheritedMethod.declaringClass.readableName(),
+                                               inheritedMethod.readableName(),
+                                               '.'))},
+                       new String[] {
+                               new String(exceptionType.sourceName()),
+                               new String(
+                                       CharOperation.concat(
+                                               inheritedMethod.declaringClass.shortReadableName(),
+                                               inheritedMethod.shortReadableName(),
+                                               '.'))},
+                       currentMethod.sourceStart(),
+                       currentMethod.sourceEnd());
+       } else  
+               this.handle(
+                       // Exception %1 in throws clause of %2 is not compatible with %3
+                       // 9.4.4 - The type of exception in the throws clause is incompatible.
+                       IProblem.IncompatibleExceptionInInheritedMethodThrowsClause,
+                       new String[] {
+                               new String(exceptionType.sourceName()),
+                               new String(
+                                       CharOperation.concat(
+                                               currentMethod.declaringClass.sourceName(),
+                                               currentMethod.readableName(),
+                                               '.')),
+                               new String(
+                                       CharOperation.concat(
+                                               inheritedMethod.declaringClass.readableName(),
+                                               inheritedMethod.readableName(),
+                                               '.'))},
+                       new String[] {
+                               new String(exceptionType.sourceName()),
+                               new String(
+                                       CharOperation.concat(
+                                               currentMethod.declaringClass.sourceName(),
+                                               currentMethod.shortReadableName(),
+                                               '.')),
+                               new String(
+                                       CharOperation.concat(
+                                               inheritedMethod.declaringClass.shortReadableName(),
+                                               inheritedMethod.shortReadableName(),
+                                               '.'))},
+                       type.sourceStart(),
+                       type.sourceEnd());
+}
+public void incompatibleReturnType(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+       StringBuffer methodSignature = new StringBuffer();
+       methodSignature
+               .append(inheritedMethod.declaringClass.readableName())
+               .append('.')
+               .append(inheritedMethod.readableName());
+
+       StringBuffer shortSignature = new StringBuffer();
+       shortSignature
+               .append(inheritedMethod.declaringClass.shortReadableName())
+               .append('.')
+               .append(inheritedMethod.shortReadableName());
+
+       int id;
+       if (currentMethod.declaringClass.isInterface() 
+                       && !inheritedMethod.isPublic()){ // interface inheriting Object protected method
+               id = IProblem.IncompatibleReturnTypeForNonInheritedInterfaceMethod;
+       } else {
+               id = IProblem.IncompatibleReturnType;
+       }
+       this.handle(
+               id,
+               new String[] {methodSignature.toString()},
+               new String[] {shortSignature.toString()},
+               currentMethod.sourceStart(),
+               currentMethod.sourceEnd());
+}
+public void incorrectLocationForEmptyDimension(ArrayAllocationExpression expression, int index) {
+       this.handle(
+               IProblem.IllegalDimension,
+               NoArgument,
+               NoArgument,
+               expression.dimensions[index + 1].sourceStart,
+               expression.dimensions[index + 1].sourceEnd);
+}
+public void indirectAccessToStaticField(ASTNode location, FieldBinding field){
+       this.handle(
+               IProblem.IndirectAccessToStaticField,
+               new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+               new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+               location.sourceStart,
+               fieldLocation(field, location));
+}
+public void indirectAccessToStaticMethod(ASTNode location, MethodBinding method) {
+       this.handle(
+               IProblem.IndirectAccessToStaticMethod,
+               new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
+               new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void indirectAccessToStaticType(ASTNode location, ReferenceBinding type) {
+       this.handle(
+               IProblem.IndirectAccessToStaticMethod,
+               new String[] {new String(type.enclosingType().readableName()), new String(type.sourceName) },
+               new String[] {new String(type.enclosingType().shortReadableName()), new String(type.sourceName) },
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void incorrectSwitchType(Expression expression, TypeBinding testType) {
+       this.handle(
+               IProblem.IncorrectSwitchType,
+               new String[] {new String(testType.readableName())},
+               new String[] {new String(testType.shortReadableName())},
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void inheritedMethodReducesVisibility(SourceTypeBinding type, MethodBinding concreteMethod, MethodBinding[] abstractMethods) {
+       StringBuffer concreteSignature = new StringBuffer();
+       concreteSignature
+               .append(concreteMethod.declaringClass.readableName())
+               .append('.')
+               .append(concreteMethod.readableName());
+       StringBuffer shortSignature = new StringBuffer();
+       shortSignature
+               .append(concreteMethod.declaringClass.shortReadableName())
+               .append('.')
+               .append(concreteMethod.shortReadableName());
+       this.handle(
+               // The inherited method %1 cannot hide the public abstract method in %2
+               IProblem.InheritedMethodReducesVisibility,
+               new String[] {
+                       concreteSignature.toString(),
+                       new String(abstractMethods[0].declaringClass.readableName())},
+               new String[] {
+                       new String(shortSignature.toString()),
+                       new String(abstractMethods[0].declaringClass.shortReadableName())},
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void inheritedMethodsHaveIncompatibleReturnTypes(SourceTypeBinding type, MethodBinding[] inheritedMethods, int length) {
+       StringBuffer methodSignatures = new StringBuffer();
+       StringBuffer shortSignatures = new StringBuffer();
+       for (int i = length; --i >= 0;) {
+               methodSignatures
+                       .append(inheritedMethods[i].declaringClass.readableName())
+                       .append('.')
+                       .append(inheritedMethods[i].readableName());
+               shortSignatures
+                       .append(inheritedMethods[i].declaringClass.shortReadableName())
+                       .append('.')
+                       .append(inheritedMethods[i].shortReadableName());
+               if (i != 0){
+                       methodSignatures.append(", "); //$NON-NLS-1$
+                       shortSignatures.append(", "); //$NON-NLS-1$
+               }
+       }
+
+       this.handle(
+               // Return type is incompatible with %1
+               // 9.4.2 - The return type from the method is incompatible with the declaration.
+               IProblem.IncompatibleReturnType,
+               new String[] {methodSignatures.toString()},
+               new String[] {shortSignatures.toString()},
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void initializerMustCompleteNormally(FieldDeclaration fieldDecl) {
+       this.handle(
+               IProblem.InitializerMustCompleteNormally,
+               NoArgument,
+               NoArgument,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void innerTypesCannotDeclareStaticInitializers(ReferenceBinding innerType, ASTNode location) {
+       this.handle(
+               IProblem.CannotDefineStaticInitializerInLocalType,
+               new String[] {new String(innerType.readableName())},
+               new String[] {new String(innerType.shortReadableName())},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void interfaceCannotHaveConstructors(ConstructorDeclaration constructor) {
+       this.handle(
+               IProblem.InterfaceCannotHaveConstructors,
+               NoArgument,
+               NoArgument,
+               constructor.sourceStart,
+               constructor.sourceEnd,
+               constructor,
+               constructor.compilationResult());
+}
+public void interfaceCannotHaveInitializers(SourceTypeBinding type, FieldDeclaration fieldDecl) {
+       String[] arguments = new String[] {new String(type.sourceName())};
+
+       this.handle(
+               IProblem.InterfaceCannotHaveInitializers,
+               arguments,
+               arguments,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void invalidBreak(ASTNode location) {
+       this.handle(
+               IProblem.InvalidBreak,
+               NoArgument,
+               NoArgument,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void invalidConstructor(Statement statement, MethodBinding targetConstructor) {
+
+       boolean insideDefaultConstructor = 
+               (this.referenceContext instanceof ConstructorDeclaration)
+                       && ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor();
+       boolean insideImplicitConstructorCall =
+               (statement instanceof ExplicitConstructorCall)
+                       && (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper);
+
+       int id = IProblem.UndefinedConstructor; //default...
+       switch (targetConstructor.problemId()) {
+               case NotFound :
+                       if (insideDefaultConstructor){
+                               id = IProblem.UndefinedConstructorInDefaultConstructor;
+                       } else if (insideImplicitConstructorCall){
+                               id = IProblem.UndefinedConstructorInImplicitConstructorCall;
+                       } else {
+                               id = IProblem.UndefinedConstructor;
+                       }
+                       break;
+               case NotVisible :
+                       if (insideDefaultConstructor){
+                               id = IProblem.NotVisibleConstructorInDefaultConstructor;
+                       } else if (insideImplicitConstructorCall){
+                               id = IProblem.NotVisibleConstructorInImplicitConstructorCall;
+                       } else {
+                               id = IProblem.NotVisibleConstructor;
+                       }
+                       break;
+               case Ambiguous :
+                       if (insideDefaultConstructor){
+                               id = IProblem.AmbiguousConstructorInDefaultConstructor;
+                       } else if (insideImplicitConstructorCall){
+                               id = IProblem.AmbiguousConstructorInImplicitConstructorCall;
+                       } else {
+                               id = IProblem.AmbiguousConstructor;
+                       }
+                       break;
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       break;
+       }
+
+       this.handle(
+               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);
+}
+public void invalidContinue(ASTNode location) {
+       this.handle(
+               IProblem.InvalidContinue,
+               NoArgument,
+               NoArgument,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void invalidEnclosingType(Expression expression, TypeBinding type, ReferenceBinding enclosingType) {
+
+       if (enclosingType.isAnonymousType()) enclosingType = enclosingType.superclass();
+       int flag = IProblem.UndefinedType; // default
+       switch (type.problemId()) {
+               case NotFound : // 1
+                       flag = IProblem.UndefinedType;
+                       break;
+               case NotVisible : // 2
+                       flag = IProblem.NotVisibleType;
+                       break;
+               case Ambiguous : // 3
+                       flag = IProblem.AmbiguousType;
+                       break;
+               case InternalNameProvided :
+                       flag = IProblem.InternalTypeNameProvided;
+                       break;
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       break;
+       }
+
+       this.handle(
+               flag,
+               new String[] {new String(enclosingType.readableName()) + "." + new String(type.readableName())}, //$NON-NLS-1$
+               new String[] {new String(enclosingType.shortReadableName()) + "." + new String(type.shortReadableName())}, //$NON-NLS-1$
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void invalidExpressionAsStatement(Expression expression){
+       this.handle(
+               IProblem.InvalidExpressionAsStatement,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void invalidField(FieldReference fieldRef, TypeBinding searchedType) {
+       int id = IProblem.UndefinedField;
+       FieldBinding field = fieldRef.binding;
+       switch (field.problemId()) {
+               case NotFound :
+                       id = IProblem.UndefinedField;
+/* also need to check that the searchedType is the receiver type
+                       if (searchedType.isHierarchyInconsistent())
+                               severity = SecondaryError;
+*/
+                       break;
+               case NotVisible :
+                       id = IProblem.NotVisibleField;
+                       break;
+               case Ambiguous :
+                       id = IProblem.AmbiguousField;
+                       break;
+               case NonStaticReferenceInStaticContext :
+                       id = IProblem.NonStaticFieldFromStaticInvocation;
+                       break;
+               case NonStaticReferenceInConstructorInvocation :
+                       id = IProblem.InstanceFieldDuringConstructorInvocation;
+                       break;
+               case InheritedNameHidesEnclosingName :
+                       id = IProblem.InheritedFieldHidesEnclosingName;
+                       break;
+               case ReceiverTypeNotVisible :
+                       this.handle(
+                               IProblem.NotVisibleType, // cannot occur in javadoc comments
+                               new String[] {new String(searchedType.leafComponentType().readableName())},
+                               new String[] {new String(searchedType.leafComponentType().shortReadableName())},
+                               fieldRef.receiver.sourceStart,
+                               fieldRef.receiver.sourceEnd);
+                       return;
+                       
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       break;
+       }
+
+       String[] arguments = new String[] {new String(field.readableName())};
+       this.handle(
+               id,
+               arguments,
+               arguments,
+               fieldRef.sourceStart,
+               fieldRef.sourceEnd);
+}
+public void invalidField(NameReference nameRef, FieldBinding field) {
+       int id = IProblem.UndefinedField;
+       switch (field.problemId()) {
+               case NotFound :
+                       id = IProblem.UndefinedField;
+                       break;
+               case NotVisible :
+                       id = IProblem.NotVisibleField;
+                       break;
+               case Ambiguous :
+                       id = IProblem.AmbiguousField;
+                       break;
+               case NonStaticReferenceInStaticContext :
+                       id = IProblem.NonStaticFieldFromStaticInvocation;
+                       break;
+               case NonStaticReferenceInConstructorInvocation :
+                       id = IProblem.InstanceFieldDuringConstructorInvocation;
+                       break;
+               case InheritedNameHidesEnclosingName :
+                       id = IProblem.InheritedFieldHidesEnclosingName;
+                       break;
+               case ReceiverTypeNotVisible :
+                       this.handle(
+                               IProblem.NotVisibleType,
+                               new String[] {new String(field.declaringClass.leafComponentType().readableName())},
+                               new String[] {new String(field.declaringClass.leafComponentType().shortReadableName())},
+                               nameRef.sourceStart,
+                               nameRef.sourceEnd);
+                       return;
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       break;
+       }
+       String[] arguments = new String[] {new String(field.readableName())};
+       this.handle(
+               id,
+               arguments,
+               arguments,
+               nameRef.sourceStart,
+               nameRef.sourceEnd);
+}
+public void invalidField(QualifiedNameReference nameRef, FieldBinding field, int index, TypeBinding searchedType) {
+       //the resolution of the index-th field of qname failed
+       //qname.otherBindings[index] is the binding that has produced the error
+
+       //The different targetted errors should be :
+       //UndefinedField
+       //NotVisibleField
+       //AmbiguousField
+
+       if (searchedType.isBaseType()) {
+               this.handle(
+                       IProblem.NoFieldOnBaseType,
+                       new String[] {
+                               new String(searchedType.readableName()),
+                               CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index)),
+                               new String(nameRef.tokens[index])},
+                       new String[] {
+                               new String(searchedType.sourceName()),
+                               CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index)),
+                               new String(nameRef.tokens[index])},
+                       nameRef.sourceStart,
+                       (int) nameRef.sourcePositions[index]);
+               return;
+       }
+
+       int id = IProblem.UndefinedField;
+       switch (field.problemId()) {
+               case NotFound :
+                       id = IProblem.UndefinedField;
+/* also need to check that the searchedType is the receiver type
+                       if (searchedType.isHierarchyInconsistent())
+                               severity = SecondaryError;
+*/
+                       break;
+               case NotVisible :
+                       id = IProblem.NotVisibleField;
+                       break;
+               case Ambiguous :
+                       id = IProblem.AmbiguousField;
+                       break;
+               case NonStaticReferenceInStaticContext :
+                       id = IProblem.NonStaticFieldFromStaticInvocation;
+                       break;
+               case NonStaticReferenceInConstructorInvocation :
+                       id = IProblem.InstanceFieldDuringConstructorInvocation;
+                       break;
+               case InheritedNameHidesEnclosingName :
+                       id = IProblem.InheritedFieldHidesEnclosingName;
+                       break;
+               case ReceiverTypeNotVisible :
+                       this.handle(
+                               IProblem.NotVisibleType,
+                               new String[] {new String(searchedType.leafComponentType().readableName())},
+                               new String[] {new String(searchedType.leafComponentType().shortReadableName())},
+                               nameRef.sourceStart,
+                               nameRef.sourceEnd);
+                       return;
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       break;
+       }
+       String[] arguments = new String[] {CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index + 1))};
+       this.handle(
+               id, 
+               arguments,
+               arguments,
+               nameRef.sourceStart, 
+               (int) nameRef.sourcePositions[index]);
+}
+public void invalidMethod(MessageSend messageSend, MethodBinding method) {
+       // CODE should be UPDATED according to error coding in the different method binding errors
+       // The different targetted errors should be :
+       //      UndefinedMethod
+       //      NotVisibleMethod
+       //      AmbiguousMethod
+       //  InheritedNameHidesEnclosingName
+       //      InstanceMethodDuringConstructorInvocation
+       // StaticMethodRequested
+
+       int id = IProblem.UndefinedMethod; //default...
+       switch (method.problemId()) {
+               case NotFound :
+                       id = IProblem.UndefinedMethod;
+                       break;
+               case NotVisible :
+                       id = IProblem.NotVisibleMethod;
+                       break;
+               case Ambiguous :
+                       id = IProblem.AmbiguousMethod;
+                       break;
+               case InheritedNameHidesEnclosingName :
+                       id = IProblem.InheritedMethodHidesEnclosingName;
+                       break;
+               case NonStaticReferenceInConstructorInvocation :
+                       id = IProblem.InstanceMethodDuringConstructorInvocation;
+                       break;
+               case NonStaticReferenceInStaticContext :
+                       id = IProblem.StaticMethodRequested;
+                       break;
+               case ReceiverTypeNotVisible :
+                       this.handle(
+                               IProblem.NotVisibleType,        // cannot occur in javadoc comments
+                               new String[] {new String(method.declaringClass.leafComponentType().readableName())},
+                               new String[] {new String(method.declaringClass.leafComponentType().shortReadableName())},
+                               messageSend.receiver.sourceStart,
+                               messageSend.receiver.sourceEnd);
+                       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[] {
+                       new String(method.declaringClass.shortReadableName()),
+                       new String(method.selector), parametersAsShortString(method)},
+               (int) (messageSend.nameSourcePosition >>> 32),
+               (int) messageSend.nameSourcePosition);
+}
+public void invalidNullToSynchronize(Expression expression) {
+       this.handle(
+               IProblem.InvalidNullToSynchronized,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void invalidOperator(BinaryExpression 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.InvalidOperator,
+               new String[] {
+                       expression.operatorToString(),
+                       leftName + ", " + rightName}, //$NON-NLS-1$
+               new String[] {
+                       expression.operatorToString(),
+                       leftShortName + ", " + rightShortName}, //$NON-NLS-1$
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void invalidOperator(CompoundAssignment assign, 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.InvalidOperator,
+               new String[] {
+                       assign.operatorToString(),
+                       leftName + ", " + rightName}, //$NON-NLS-1$
+               new String[] {
+                       assign.operatorToString(),
+                       leftShortName + ", " + rightShortName}, //$NON-NLS-1$
+               assign.sourceStart,
+               assign.sourceEnd);
+}
+public void invalidOperator(UnaryExpression expression, TypeBinding type) {
+       this.handle(
+               IProblem.InvalidOperator,
+               new String[] {expression.operatorToString(), new String(type.readableName())},
+               new String[] {expression.operatorToString(), new String(type.shortReadableName())},
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void invalidParenthesizedExpression(ASTNode reference) {
+       this.handle(
+               IProblem.InvalidParenthesizedExpression,
+               NoArgument,
+               NoArgument,
+               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()) {
+               case NotFound :
+                       id = IProblem.UndefinedType;
+                       break;
+               case NotVisible :
+                       id = IProblem.NotVisibleType;
+                       break;
+               case Ambiguous :
+                       id = IProblem.AmbiguousType;
+                       break;
+               case InternalNameProvided :
+                       id = IProblem.InternalTypeNameProvided;
+                       break;
+               case InheritedNameHidesEnclosingName :
+                       id = IProblem.InheritedTypeHidesEnclosingName;
+                       break;
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       break;
+       }
+       
+       int end = location.sourceEnd;
+       if (location instanceof QualifiedNameReference) {
+               QualifiedNameReference ref = (QualifiedNameReference) location;
+               if (ref.indexOfFirstFieldBinding >= 1)
+                       end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1];
+       }
+       this.handle(
+               id,
+               new String[] {new String(type.readableName())},
+               new String[] {new String(type.shortReadableName())},
+               location.sourceStart,
+               end);
+}
+public void invalidTypeReference(Expression expression) {
+       this.handle(
+               IProblem.InvalidTypeExpression,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void invalidTypeToSynchronize(Expression expression, TypeBinding type) {
+       this.handle(
+               IProblem.InvalidTypeToSynchronized,
+               new String[] {new String(type.readableName())},
+               new String[] {new String(type.shortReadableName())},
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void invalidUnaryExpression(Expression expression) {
+       this.handle(
+               IProblem.InvalidUnaryExpression,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl) {
+       this.referenceContext = compUnitDecl;
+       String[] arguments = new String[] {CharOperation.toString(wellKnownTypeName)};
+       this.handle(
+               IProblem.IsClassPathCorrect,
+               arguments, 
+               arguments,
+               AbortCompilation | Error,
+               0,
+               0);
+}
+public void javadocDuplicatedReturnTag(int sourceStart, int sourceEnd){
+       this.handle(IProblem.JavadocDuplicateReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocDeprecatedField(FieldBinding field, ASTNode location, int modifiers) {
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               this.handle(
+                       IProblem.JavadocUsingDeprecatedField,
+                       new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+                       new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+                       location.sourceStart,
+                       location.sourceEnd);
+       }
+}
+public void javadocDeprecatedMethod(MethodBinding method, ASTNode location, int modifiers) {
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               if (method.isConstructor()) {
+                       this.handle(
+                               IProblem.JavadocUsingDeprecatedConstructor,
+                               new String[] {new String(method.declaringClass.readableName()), parametersAsString(method)},
+                               new String[] {new String(method.declaringClass.shortReadableName()), parametersAsShortString(method)},
+                               location.sourceStart,
+                               location.sourceEnd);
+               } else {
+                       this.handle(
+                               IProblem.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)},
+                               location.sourceStart,
+                               location.sourceEnd);
+               }
+       }
+}
+public void javadocDeprecatedType(TypeBinding type, ASTNode location, int modifiers) {
+       if (location == null) return; // 1G828DN - no type ref for synthetic arguments
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               this.handle(
+                       IProblem.JavadocUsingDeprecatedType,
+                       new String[] {new String(type.readableName())},
+                       new String[] {new String(type.shortReadableName())},
+                       location.sourceStart,
+                       location.sourceEnd);
+       }
+}
+public void javadocDuplicatedParamTag(JavadocSingleNameReference param, int modifiers) {
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               String[] arguments = new String[] {String.valueOf(param.token)};
+               this.handle(IProblem.JavadocDuplicateParamName, arguments, arguments, param.sourceStart, param.sourceEnd);
+       }
+}
+public void javadocDuplicatedThrowsClassName(TypeReference typeReference, int modifiers) {
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               String[] arguments = new String[] {String.valueOf(typeReference.resolvedType.sourceName())};
+               this.handle(IProblem.JavadocDuplicateThrowsClassName, arguments, arguments, typeReference.sourceStart, typeReference.sourceEnd);
+       }
+}
+public void javadocErrorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params, int modifiers) {
+       StringBuffer buffer = new StringBuffer();
+       StringBuffer shortBuffer = new StringBuffer();
+       for (int i = 0, length = params.length; i < length; i++) {
+               if (i != 0){
+                       buffer.append(", "); //$NON-NLS-1$
+                       shortBuffer.append(", "); //$NON-NLS-1$
+               }
+               buffer.append(new String(params[i].readableName()));
+               shortBuffer.append(new String(params[i].shortReadableName()));
+       }
+
+       int id = recType.isArrayType() ? IProblem.JavadocNoMessageSendOnArrayType : IProblem.JavadocNoMessageSendOnBaseType;
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               this.handle(
+                       id,
+                       new String[] {new String(recType.readableName()), new String(messageSend.selector), buffer.toString()},
+                       new String[] {new String(recType.shortReadableName()), new String(messageSend.selector), shortBuffer.toString()},
+                       messageSend.sourceStart,
+                       messageSend.sourceEnd);
+       }
+}
+public void javadocInvalidConstructor(Statement statement, MethodBinding targetConstructor, int modifiers) {
+
+       if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               return;
+       }
+//     boolean insideDefaultConstructor = 
+//             (this.referenceContext instanceof ConstructorDeclaration)
+//                     && ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor();
+//     boolean insideImplicitConstructorCall =
+//             (statement instanceof ExplicitConstructorCall)
+//                     && (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper);
+
+       int id = IProblem.JavadocUndefinedConstructor; //default...
+       switch (targetConstructor.problemId()) {
+               case NotFound :
+//                     if (insideDefaultConstructor){
+//                             id = IProblem.JavadocUndefinedConstructorInDefaultConstructor;
+//                     } else if (insideImplicitConstructorCall){
+//                             id = IProblem.JavadocUndefinedConstructorInImplicitConstructorCall;
+//                     } else {
+                               id = IProblem.JavadocUndefinedConstructor;
+//                     }
+                       break;
+               case NotVisible :
+//                     if (insideDefaultConstructor){
+//                             id = IProblem.JavadocNotVisibleConstructorInDefaultConstructor;
+//                     } else if (insideImplicitConstructorCall){
+//                             id = IProblem.JavadocNotVisibleConstructorInImplicitConstructorCall;
+//                     } else {
+                               id = IProblem.JavadocNotVisibleConstructor;
+//                     }
+                       break;
+               case Ambiguous :
+//                     if (insideDefaultConstructor){
+//                             id = IProblem.AmbiguousConstructorInDefaultConstructor;
+//                     } else if (insideImplicitConstructorCall){
+//                             id = IProblem.AmbiguousConstructorInImplicitConstructorCall;
+//                     } else {
+                               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)},
+               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:
+ *     - NonStaticReferenceInStaticContext :
+ *     - NonStaticReferenceInConstructorInvocation :
+ *     - ReceiverTypeNotVisible :
+ */
+public void javadocInvalidField(int sourceStart, int sourceEnd, Binding fieldBinding, TypeBinding searchedType, int modifiers) {
+       int id = IProblem.JavadocUndefinedField;
+       switch (fieldBinding.problemId()) {
+               case NotFound :
+                       id = IProblem.JavadocUndefinedField;
+                       break;
+               case NotVisible :
+                       id = IProblem.JavadocNotVisibleField;
+                       break;
+               case Ambiguous :
+                       id = IProblem.JavadocAmbiguousField;
+                       break;
+               case InheritedNameHidesEnclosingName :
+                       id = IProblem.JavadocInheritedFieldHidesEnclosingName;
+                       break;
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       break;
+       }
+
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               String[] arguments = new String[] {new String(fieldBinding.readableName())};
+               handle(id, arguments, arguments, sourceStart, sourceEnd);
+       }
+}
+/*
+ * Similar implementation than invalidMethod(MessageSend...)
+ * Note that following problem id cannot occur for Javadoc:
+ *     - NonStaticReferenceInStaticContext :
+ *     - NonStaticReferenceInConstructorInvocation :
+ *     - ReceiverTypeNotVisible :
+ */
+public void javadocInvalidMethod(MessageSend messageSend, MethodBinding method, int modifiers) {
+       if (!javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               return;
+       }
+       int id = IProblem.JavadocUndefinedMethod; //default...
+       switch (method.problemId()) {
+               case NotFound :
+                       id = IProblem.JavadocUndefinedMethod;
+                       break;
+               case NotVisible :
+                       id = IProblem.JavadocNotVisibleMethod;
+                       break;
+               case Ambiguous :
+                       id = IProblem.JavadocAmbiguousMethod;
+                       break;
+               case InheritedNameHidesEnclosingName :
+                       id = IProblem.JavadocInheritedMethodHidesEnclosingName;
+                       break;
+               case NoError : // 0
+               default :
+                       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);
+                               if (closestParameterTypeShortNames.equals(parameterTypeShortNames)){
+                                       closestParameterTypeShortNames = closestParameterTypeNames;
+                                       parameterTypeShortNames = parameterTypeNames;
+                               }
+                               this.handle(
+                                       IProblem.JavadocParameterMismatch,
+                                       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[] {
+                       new String(method.declaringClass.shortReadableName()),
+                       new String(method.selector), parametersAsShortString(method)},
+               (int) (messageSend.nameSourcePosition >>> 32),
+               (int) messageSend.nameSourcePosition);
+}
+public void javadocInvalidParamName(JavadocSingleNameReference param, int modifiers) {
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               String[] arguments = new String[] {String.valueOf(param.token)};
+               this.handle(IProblem.JavadocInvalidParamName, arguments, arguments, param.sourceStart, param.sourceEnd);
+       }
+}
+public void javadocInvalidSeeReference(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocInvalidSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSeeReferenceArgs(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocInvalidSeeArgs, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidSeeUrlReference(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocInvalidSeeHref, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidTag(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocInvalidTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidThrowsClass(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocInvalidThrowsClass, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocInvalidThrowsClassName(TypeReference typeReference, int modifiers) {
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               String[] arguments = new String[] {String.valueOf(typeReference.resolvedType.sourceName())};
+               this.handle(IProblem.JavadocInvalidThrowsClassName, arguments, arguments, typeReference.sourceStart, typeReference.sourceEnd);
+       }
+}
+public void javadocInvalidType(ASTNode location, TypeBinding type, int modifiers) {
+       if (javadocVisibility(this.options.reportInvalidJavadocTagsVisibility, modifiers)) {
+               int id = IProblem.JavadocUndefinedType; // default
+               switch (type.problemId()) {
+                       case NotFound :
+                               id = IProblem.JavadocUndefinedType;
+                               break;
+                       case NotVisible :
+                               id = IProblem.JavadocNotVisibleType;
+                               break;
+                       case Ambiguous :
+                               id = IProblem.JavadocAmbiguousType;
+                               break;
+                       case InternalNameProvided :
+                               id = IProblem.JavadocInternalTypeNameProvided;
+                               break;
+                       case InheritedNameHidesEnclosingName :
+                               id = IProblem.JavadocInheritedNameHidesEnclosingTypeName;
+                               break;
+                       case NoError : // 0
+                       default :
+                               needImplementation(); // want to fail to see why we were here...
+                               break;
+               }
+               this.handle(
+                       id,
+                       new String[] {new String(type.readableName())},
+                       new String[] {new String(type.shortReadableName())},
+                       location.sourceStart,
+                       location.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 report = (this.options.getSeverity(CompilerOptions.MissingJavadocComments) != ProblemSeverities.Ignore)
+                                       && (!overriding || this.options.reportMissingJavadocCommentsOverriding);
+       if (report) {
+               String arg = javadocVisibilityArgument(this.options.reportMissingJavadocCommentsVisibility, modifiers);
+               if (arg != null) {
+                       String[] arguments = new String[] { arg };
+                       this.handle(IProblem.JavadocMissing, arguments, arguments, sourceStart, sourceEnd);
+               }
+       }
+}
+public void javadocMissingParamName(int sourceStart, int sourceEnd){
+       this.handle(IProblem.JavadocMissingParamName, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocMissingParamTag(Argument param, int modifiers) {
+       boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+       boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
+                                       && (!overriding || this.options.reportMissingJavadocTagsOverriding);
+       if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
+               String[] arguments = new String[] { String.valueOf(param.name) };
+               this.handle(IProblem.JavadocMissingParamTag, arguments, arguments, param.sourceStart, param.sourceEnd);
+       }
+}
+public void javadocMissingReturnTag(int sourceStart, int sourceEnd, int modifiers){
+       boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+       boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
+                                       && (!overriding || this.options.reportMissingJavadocTagsOverriding);
+       if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
+               this.handle(IProblem.JavadocMissingReturnTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+       }
+}
+public void javadocMissingSeeReference(int sourceStart, int sourceEnd){
+       this.handle(IProblem.JavadocMissingSeeReference, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocMissingThrowsClassName(int sourceStart, int sourceEnd){
+       this.handle(IProblem.JavadocMissingThrowsClassName, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocMissingThrowsTag(TypeReference typeRef, int modifiers){
+       boolean overriding = (modifiers & (CompilerModifiers.AccImplementing+CompilerModifiers.AccOverriding)) != 0;
+       boolean report = (this.options.getSeverity(CompilerOptions.MissingJavadocTags) != ProblemSeverities.Ignore)
+                                       && (!overriding || this.options.reportMissingJavadocTagsOverriding);
+       if (report && javadocVisibility(this.options.reportMissingJavadocTagsVisibility, modifiers)) {
+               String[] arguments = new String[] { String.valueOf(typeRef.resolvedType.sourceName()) };
+               this.handle(IProblem.JavadocMissingThrowsTag, arguments, arguments, typeRef.sourceStart, typeRef.sourceEnd);
+       }
+}
+public void javadocUnexpectedTag(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocUnexpectedTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+public void javadocUnterminatedInlineTag(int sourceStart, int sourceEnd) {
+       this.handle(IProblem.JavadocUnterminatedInlineTag, NoArgument, NoArgument, sourceStart, sourceEnd);
+}
+private boolean javadocVisibility(int visibility, int modifiers) {
+       switch (modifiers & CompilerModifiers.AccVisibilityMASK) {
+               case IConstants.AccPublic :
+                       return true;
+               case IConstants.AccProtected:
+                       return (visibility != IConstants.AccPublic);
+               case IConstants.AccDefault:
+                       return (visibility == IConstants.AccDefault || visibility == IConstants.AccPrivate);
+               case IConstants.AccPrivate:
+                       return (visibility == IConstants.AccPrivate);
+       }
+       return true;
+}
+private String javadocVisibilityArgument(int visibility, int modifiers) {
+       String argument = null;
+       switch (modifiers & CompilerModifiers.AccVisibilityMASK) {
+               case IConstants.AccPublic :
+                       argument = CompilerOptions.PUBLIC;
+                       break;
+               case IConstants.AccProtected:
+                       if (visibility != IConstants.AccPublic) {
+                               argument = CompilerOptions.PROTECTED;
+                       }
+                       break;
+               case IConstants.AccDefault:
+                       if (visibility == IConstants.AccDefault || visibility == IConstants.AccPrivate) {
+                               argument = CompilerOptions.DEFAULT;
+                       }
+                       break;
+               case IConstants.AccPrivate:
+                       if (visibility == IConstants.AccPrivate) {
+                               argument = CompilerOptions.PRIVATE;
+                       }
+                       break;
+       }
+       return argument;
+}
+public void localVariableHiding(LocalDeclaration local, Binding hiddenVariable, boolean  isSpecialArgHidingField) {
+       if (hiddenVariable instanceof LocalVariableBinding) {
+               String[] arguments = new String[] {new String(local.name)  };
+               this.handle(
+                       (local instanceof Argument) 
+                               ? IProblem.ArgumentHidingLocalVariable 
+                               : IProblem.LocalVariableHidingLocalVariable,
+                       arguments,
+                       arguments,
+                       local.sourceStart,
+                       local.sourceEnd);
+       } else if (hiddenVariable instanceof FieldBinding) {
+               if (isSpecialArgHidingField && !this.options.reportSpecialParameterHidingField){
+                       return;
+               }
+               FieldBinding field = (FieldBinding) hiddenVariable;
+               this.handle(
+                       (local instanceof Argument)
+                               ? IProblem.ArgumentHidingField
+                               : IProblem.LocalVariableHidingField,
+                       new String[] {new String(local.name) , new String(field.declaringClass.readableName()) },
+                       new String[] {new String(local.name), new String(field.declaringClass.shortReadableName()) },
+                       local.sourceStart,
+                       local.sourceEnd);
+       }
+}
+public void methodNeedBody(AbstractMethodDeclaration methodDecl) {
+       this.handle(
+               IProblem.MethodRequiresBody,
+               NoArgument,
+               NoArgument,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void methodNeedingNoBody(MethodDeclaration methodDecl) {
+       this.handle(
+               ((methodDecl.modifiers & IConstants.AccNative) != 0) ? IProblem.BodyForNativeMethod : IProblem.BodyForAbstractMethod,
+               NoArgument,
+               NoArgument,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void methodWithConstructorName(MethodDeclaration methodDecl) {
+       this.handle(
+               IProblem.MethodButWithConstructorName,
+               NoArgument,
+               NoArgument,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void missingReturnType(AbstractMethodDeclaration methodDecl) {
+       this.handle(
+               IProblem.MissingReturnType,
+               NoArgument,
+               NoArgument,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void missingSemiColon(Expression expression){
+       this.handle(
+               IProblem.MissingSemiColon,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void mustDefineDimensionsOrInitializer(ArrayAllocationExpression expression) {
+       this.handle(
+               IProblem.MustDefineEitherDimensionExpressionsOrInitializer,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void mustSpecifyPackage(CompilationUnitDeclaration compUnitDecl) {
+       String[] arguments = new String[] {new String(compUnitDecl.getFileName())};
+       this.handle(
+               IProblem.MustSpecifyPackage,
+               arguments,
+               arguments,
+               compUnitDecl.sourceStart,
+               compUnitDecl.sourceStart + 1);  
+}
+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)},
+               messageSend.sourceStart,
+               messageSend.sourceEnd);
+}
+
+public void nativeMethodsCannotBeStrictfp(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+       this.handle(
+               IProblem.NativeMethodsCannotBeStrictfp,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+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) {
+       this.handle(
+               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,
+               location.sourceEnd);
+}
+public void needToEmulateMethodAccess(
+       MethodBinding method, 
+       ASTNode location) {
+
+       if (method.isConstructor())
+               this.handle(
+                       IProblem.NeedToEmulateConstructorAccess, 
+                       new String[] {
+                               new String(method.declaringClass.readableName()), 
+                               parametersAsString(method)
+                        }, 
+                       new String[] {
+                               new String(method.declaringClass.shortReadableName()), 
+                               parametersAsShortString(method)
+                        }, 
+                       location.sourceStart, 
+                       location.sourceEnd); 
+       else
+               this.handle(
+                       IProblem.NeedToEmulateMethodAccess, 
+                       new String[] {
+                               new String(method.declaringClass.readableName()), 
+                               new String(method.selector), 
+                               parametersAsString(method)
+                        }, 
+                       new String[] {
+                               new String(method.declaringClass.shortReadableName()), 
+                               new String(method.selector), 
+                               parametersAsShortString(method)
+                        }, 
+                       location.sourceStart, 
+                       location.sourceEnd); 
+}
+public void nestedClassCannotDeclareInterface(TypeDeclaration typeDecl) {
+       String[] arguments = new String[] {new String(typeDecl.name)};
+       this.handle(
+               IProblem.CannotDefineInterfaceInLocalType,
+               arguments,
+               arguments,
+               typeDecl.sourceStart,
+               typeDecl.sourceEnd);
+}
+public void noMoreAvailableSpaceForArgument(LocalVariableBinding local, ASTNode location) {
+       String[] arguments = new String[]{ new String(local.name) };
+       this.handle(
+               local instanceof SyntheticArgumentBinding
+                       ? IProblem.TooManySyntheticArgumentSlots
+                       : IProblem.TooManyArgumentSlots,
+               arguments,
+               arguments,
+               Abort | Error,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void noMoreAvailableSpaceForLocal(LocalVariableBinding local, ASTNode location) {
+       String[] arguments = new String[]{ new String(local.name) };
+       this.handle(
+               IProblem.TooManyLocalVariableSlots,
+               arguments,
+               arguments,
+               Abort | Error,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void nonStaticAccessToStaticMethod(ASTNode location, MethodBinding method) {
+       this.handle(
+               IProblem.NonStaticAccessToStaticMethod,
+               new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(method)},
+               new String[] {new String(method.declaringClass.shortReadableName()), new String(method.selector), parametersAsShortString(method)},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void nonStaticAccessToStaticField(ASTNode location, FieldBinding field) {
+       this.handle(
+               IProblem.NonStaticAccessToStaticField,
+               new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+               new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+               location.sourceStart,
+               fieldLocation(field, location));
+}
+public void noSuchEnclosingInstance(TypeBinding targetType, ASTNode location, boolean isConstructorCall) {
+
+       int id;
+
+       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)
+                               && ((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper) {
+               //20 = No enclosing instance of type {0} is accessible to invoke the super constructor. Must define a constructor and explicitly qualify its super constructor invocation with an instance of {0} (e.g. x.super() where x is an instance of {0}).
+               id = IProblem.MissingEnclosingInstanceForConstructorCall;
+       } else if (location instanceof AllocationExpression 
+                               && (((AllocationExpression) location).binding.declaringClass.isMemberType()
+                                       || (((AllocationExpression) location).binding.declaringClass.isAnonymousType() 
+                                               && ((AllocationExpression) location).binding.declaringClass.superclass().isMemberType()))) {
+               //21 = No enclosing instance of type {0} is accessible. Must qualify the allocation with an enclosing instance of type {0} (e.g. x.new A() where x is an instance of {0}).
+               id = IProblem.MissingEnclosingInstance;
+       } else { // default
+               //22 = No enclosing instance of the type {0} is accessible in scope
+               id = IProblem.IncorrectEnclosingInstanceReference;
+       }
+
+       this.handle(
+               id,
+               new String[] { new String(targetType.readableName())}, 
+               new String[] { new String(targetType.shortReadableName())}, 
+               location.sourceStart, 
+               location.sourceEnd); 
+}
+public void notCompatibleTypesError(EqualExpression 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.IncompatibleTypesInEqualityOperator,
+               new String[] {leftName, rightName },
+               new String[] {leftShortName, rightShortName },
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void notCompatibleTypesError(InstanceOfExpression 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.IncompatibleTypesInConditionalOperator,
+               new String[] {leftName, rightName },
+               new String[] {leftShortName, rightShortName },
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void objectCannotHaveSuperTypes(SourceTypeBinding type) {
+       this.handle(
+               IProblem.ObjectCannotHaveSuperTypes,
+               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());
+       String leftShortName = new String(leftType.shortReadableName());
+       String rightShortName = new String(rightType.shortReadableName());
+       if (leftShortName.equals(rightShortName)){
+               leftShortName = leftName;
+               rightShortName = rightName;
+       }
+       this.handle(
+               IProblem.TypeMismatch,
+               new String[] {leftName, rightName },
+               new String[] {leftShortName, rightShortName },
+               assignment.sourceStart,
+               assignment.sourceEnd);
+}
+public void overridesDeprecatedMethod(MethodBinding localMethod, MethodBinding inheritedMethod) {
+       this.handle(
+               IProblem.OverridingDeprecatedMethod,
+               new String[] {
+                       new String(
+                                       CharOperation.concat(
+                                               localMethod.declaringClass.readableName(),
+                                               localMethod.readableName(),
+                                               '.')),
+                       new String(inheritedMethod.declaringClass.readableName())},
+               new String[] {
+                       new String(
+                                       CharOperation.concat(
+                                               localMethod.declaringClass.shortReadableName(),
+                                               localMethod.shortReadableName(),
+                                               '.')),
+                       new String(inheritedMethod.declaringClass.shortReadableName())},
+               localMethod.sourceStart(),
+               localMethod.sourceEnd());
+}
+public void overridesPackageDefaultMethod(MethodBinding localMethod, MethodBinding inheritedMethod) {
+       this.handle(
+               IProblem.OverridingNonVisibleMethod,
+               new String[] {
+                       new String(
+                                       CharOperation.concat(
+                                               localMethod.declaringClass.readableName(),
+                                               localMethod.readableName(),
+                                               '.')),
+                       new String(inheritedMethod.declaringClass.readableName())},
+               new String[] {
+                       new String(
+                                       CharOperation.concat(
+                                               localMethod.declaringClass.shortReadableName(),
+                                               localMethod.shortReadableName(),
+                                               '.')),
+                       new String(inheritedMethod.declaringClass.shortReadableName())},
+               localMethod.sourceStart(),
+               localMethod.sourceEnd());
+}
+public void packageCollidesWithType(CompilationUnitDeclaration compUnitDecl) {
+       String[] arguments = new String[] {CharOperation.toString(compUnitDecl.currentPackage.tokens)};
+       this.handle(
+               IProblem.PackageCollidesWithType,
+               arguments,
+               arguments,
+               compUnitDecl.currentPackage.sourceStart,
+               compUnitDecl.currentPackage.sourceEnd);
+}
+public void packageIsNotExpectedPackage(CompilationUnitDeclaration compUnitDecl) {
+       String[] arguments = new String[] {CharOperation.toString(compUnitDecl.compilationResult.compilationUnit.getPackageName())};
+       this.handle(
+               IProblem.PackageIsNotExpectedPackage,
+               arguments,
+               arguments,
+               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()));
+       }
+       return buffer.toString();
+}
+public void parseError(
+       int startPosition, 
+       int endPosition, 
+       int currentToken,
+       char[] currentTokenSource, 
+       String errorTokenName, 
+       String[] possibleTokens) {
+               
+       if (possibleTokens.length == 0) { //no suggestion available
+               if (isKeyword(currentToken)) {
+                       String[] arguments = new String[] {new String(currentTokenSource)};
+                       this.handle(
+                               IProblem.ParsingErrorOnKeywordNoSuggestion,
+                               arguments,
+                               arguments,
+                               // this is the current -invalid- token position
+                               startPosition,
+                               endPosition);
+                       return;
+               } else {
+                       String[] arguments = new String[] {errorTokenName};
+                       this.handle(
+                               IProblem.ParsingErrorNoSuggestion,
+                               arguments,
+                               arguments,
+                               // this is the current -invalid- token position
+                               startPosition,
+                               endPosition);
+                       return;
+               }
+       }
+
+       //build a list of probable right tokens
+       StringBuffer list = new StringBuffer(20);
+       for (int i = 0, max = possibleTokens.length; i < max; i++) {
+               if (i > 0)
+                       list.append(", "); //$NON-NLS-1$
+               list.append('"');
+               list.append(possibleTokens[i]);
+               list.append('"');
+       }
+
+       if (isKeyword(currentToken)) {
+               String[] arguments = new String[] {new String(currentTokenSource), list.toString()};
+               this.handle(
+                       IProblem.ParsingErrorOnKeyword,
+                       arguments,
+                       arguments,
+                       // this is the current -invalid- token position
+                       startPosition,
+                       endPosition);
+               return;
+       }
+       //extract the literal when it's a literal  
+       if (isLiteral(currentToken) ||
+               isIdentifier(currentToken)) { //$NON-NLS-1$
+                       errorTokenName = new String(currentTokenSource);
+       }
+
+       String[] arguments = new String[] {errorTokenName, list.toString()};
+       this.handle(
+               IProblem.ParsingError,
+               arguments,
+               arguments,
+               // this is the current -invalid- token position
+               startPosition,
+               endPosition);
+}
+public void possibleAccidentalBooleanAssignment(Assignment assignment) {
+       String[] arguments = new String[] {};
+       this.handle(
+               IProblem.PossibleAccidentalBooleanAssignment,
+               arguments,
+               arguments,
+               assignment.sourceStart,
+               assignment.sourceEnd);
+}
+public void publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
+       this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
+       String[] arguments = new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)};
+       this.handle(
+               IProblem.PublicClassMustMatchFileName,
+               arguments,
+               arguments,
+               typeDecl.sourceStart,
+               typeDecl.sourceEnd,
+               compUnitDecl.compilationResult);
+}
+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 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 returnTypeProblem(SourceTypeBinding type, MethodDeclaration methodDecl, TypeBinding expectedType) {
+       int problemId = expectedType.problemId();
+       int id;
+       switch (problemId) {
+               case NotFound : // 1
+                       id = IProblem.ReturnTypeNotFound;
+                       break;
+               case NotVisible : // 2
+                       id = IProblem.ReturnTypeNotVisible;
+                       break;
+               case Ambiguous : // 3
+                       id = IProblem.ReturnTypeAmbiguous;
+                       break;
+               case InternalNameProvided : // 4
+                       id = IProblem.ReturnTypeInternalNameProvided;
+                       break;
+               case InheritedNameHidesEnclosingName : // 5
+                       id = IProblem.ReturnTypeInheritedNameHidesEnclosingName;
+                       break;
+               case NoError : // 0
+               default :
+                       needImplementation(); // want to fail to see why we were here...
+                       return;
+       }
+       this.handle(
+               id,
+               new String[] {new String(methodDecl.selector), new String(expectedType.readableName())},
+               new String[] {new String(methodDecl.selector), new String(expectedType.shortReadableName())},
+               methodDecl.returnType.sourceStart,
+               methodDecl.returnType.sourceEnd);
+}
+public void scannerError(Parser parser, String errorTokenName) {
+       Scanner scanner = parser.scanner;
+
+       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;
+       else if (errorTokenName.equals(Scanner.UNTERMINATED_COMMENT))
+               flag = IProblem.UnterminatedComment;
+       else if (errorTokenName.equals(Scanner.INVALID_CHAR_IN_STRING))
+               flag = IProblem.UnterminatedString;
+       else if (errorTokenName.equals(Scanner.INVALID_INPUT))
+               flag = IProblem.InvalidInput;
+
+       String[] arguments = flag == IProblem.ParsingErrorNoSuggestion 
+                       ? new String[] {errorTokenName}
+                       : NoArgument;
+       this.handle(
+               flag, 
+               arguments,
+               arguments,
+               // this is the current -invalid- token position
+               startPos, 
+               scanner.currentPosition - 1,
+               parser.compilationUnit.compilationResult);
+}
+public void shouldReturn(TypeBinding returnType, ASTNode location) {
+       this.handle(
+               IProblem.ShouldReturnValue,
+               new String[] { new String (returnType.readableName())},
+               new String[] { new String (returnType.shortReadableName())},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void signalNoImplicitStringConversionForCharArrayExpression(Expression expression) {
+       this.handle(
+               IProblem.NoImplicitStringConversionForCharArrayExpression,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void staticAndInstanceConflict(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+       if (currentMethod.isStatic())
+               this.handle(
+                       // This static method cannot hide the instance method from %1
+                       // 8.4.6.4 - If a class inherits more than one method with the same signature a static (non-abstract) method cannot hide an instance method.
+                       IProblem.CannotHideAnInstanceMethodWithAStaticMethod,
+                       new String[] {new String(inheritedMethod.declaringClass.readableName())},
+                       new String[] {new String(inheritedMethod.declaringClass.shortReadableName())},
+                       currentMethod.sourceStart(),
+                       currentMethod.sourceEnd());
+       else
+               this.handle(
+                       // This instance method cannot override the static method from %1
+                       // 8.4.6.4 - If a class inherits more than one method with the same signature an instance (non-abstract) method cannot override a static method.
+                       IProblem.CannotOverrideAStaticMethodWithAnInstanceMethod,
+                       new String[] {new String(inheritedMethod.declaringClass.readableName())},
+                       new String[] {new String(inheritedMethod.declaringClass.shortReadableName())},
+                       currentMethod.sourceStart(),
+                       currentMethod.sourceEnd());
+}
+public void staticFieldAccessToNonStaticVariable(ASTNode location, FieldBinding field) {
+       String[] arguments = new String[] {new String(field.readableName())};
+       this.handle(
+               IProblem.NonStaticFieldFromStaticInvocation,
+               arguments,
+               arguments,
+               location.sourceStart,
+               fieldLocation(field, location)); 
+}
+public void staticInheritedMethodConflicts(SourceTypeBinding type, MethodBinding concreteMethod, MethodBinding[] abstractMethods) {
+       this.handle(
+               // The static method %1 conflicts with the abstract method in %2
+               // 8.4.6.4 - If a class inherits more than one method with the same signature it is an error for one to be static (non-abstract) and the other abstract.
+               IProblem.StaticInheritedMethodConflicts,
+               new String[] {
+                       new String(concreteMethod.readableName()),
+                       new String(abstractMethods[0].declaringClass.readableName())},
+               new String[] {
+                       new String(concreteMethod.readableName()),
+                       new String(abstractMethods[0].declaringClass.shortReadableName())},
+               type.sourceStart(),
+               type.sourceEnd());
+}
+public void stringConstantIsExceedingUtf8Limit(ASTNode location) {
+       this.handle(
+               IProblem.StringConstantIsExceedingUtf8Limit,
+               NoArgument,
+               NoArgument,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void superclassMustBeAClass(SourceTypeBinding type, TypeReference superclassRef, ReferenceBinding superType) {
+       this.handle(
+               IProblem.SuperclassMustBeAClass,
+               new String[] {new String(superType.readableName()), new String(type.sourceName())},
+               new String[] {new String(superType.shortReadableName()), new String(type.sourceName())},
+               superclassRef.sourceStart,
+               superclassRef.sourceEnd);
+}
+public void superfluousSemicolon(int sourceStart, int sourceEnd) {
+       this.handle(
+               IProblem.SuperfluousSemicolon,
+               NoArgument,
+               NoArgument,
+               sourceStart,
+               sourceEnd);     
+}
+public void superinterfaceMustBeAnInterface(SourceTypeBinding type, TypeDeclaration typeDecl, ReferenceBinding superType) {
+       this.handle(
+               IProblem.SuperInterfaceMustBeAnInterface,
+               new String[] {new String(superType.readableName()), new String(type.sourceName())},
+               new String[] {new String(superType.shortReadableName()), new String(type.sourceName())},
+               typeDecl.sourceStart,
+               typeDecl.sourceEnd);
+}
+public void task(String tag, String message, String priority, int start, int end){
+       this.handle(
+               IProblem.Task,
+               new String[] { tag, message, priority/*secret argument that is not surfaced in getMessage()*/},
+               new String[] { tag, message, priority/*secret argument that is not surfaced in getMessage()*/}, 
+               start,
+               end);
+}
+public void tooManyDimensions(ASTNode expression) {
+       this.handle(
+               IProblem.TooManyArrayDimensions,
+               NoArgument,
+               NoArgument,
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void tooManyFields(TypeDeclaration typeDeclaration) {
+       this.handle(
+               IProblem.TooManyFields,
+               new String[]{ new String(typeDeclaration.binding.readableName())},
+               new String[]{ new String(typeDeclaration.binding.shortReadableName())},
+               Abort | Error,
+               typeDeclaration.sourceStart,
+               typeDeclaration.sourceEnd);
+}
+public void tooManyMethods(TypeDeclaration typeDeclaration) {
+       this.handle(
+               IProblem.TooManyMethods,
+               new String[]{ new String(typeDeclaration.binding.readableName())},
+               new String[]{ new String(typeDeclaration.binding.shortReadableName())},
+               Abort | Error,
+               typeDeclaration.sourceStart,
+               typeDeclaration.sourceEnd);
+}
+public void typeCastError(CastExpression 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.IllegalCast,
+               new String[] { rightName, leftName },
+               new String[] { rightShortName, leftShortName },
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void typeCollidesWithPackage(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.TypeCollidesWithPackage,
+               arguments,
+               arguments,
+               typeDecl.sourceStart,
+               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;
+       }
+       this.handle(
+               IProblem.TypeMismatch,
+               new String[] {resultTypeName, expectedTypeName},
+               new String[] {resultTypeShortName, expectedTypeShortName},
+               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;
+       }
+       this.handle(
+               IProblem.TypeMismatch,
+               new String[] {constantTypeName, expectedTypeName},
+               new String[] {constantTypeShortName, expectedTypeShortName},
+               expression.sourceStart,
+               expression.sourceEnd);
+}
+public void undefinedLabel(BranchStatement statement) {
+       String[] arguments = new String[] {new String(statement.label)};
+       this.handle(
+               IProblem.UndefinedLabel,
+               arguments,
+               arguments,
+               statement.sourceStart,
+               statement.sourceEnd);
+}
+public void undocumentedEmptyBlock(int blockStart, int blockEnd) {
+       String[] arguments = new String[] {};
+       this.handle(
+               IProblem.UndocumentedEmptyBlock,
+               arguments,
+               arguments,
+               blockStart,
+               blockEnd);
+}
+public void unexpectedStaticModifierForField(SourceTypeBinding type, FieldDeclaration fieldDecl) {
+       String[] arguments = new String[] {new String(fieldDecl.name)};
+       this.handle(
+               IProblem.UnexpectedStaticModifierForField,
+               arguments,
+               arguments,
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void unexpectedStaticModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+       String[] arguments = new String[] {new String(type.sourceName()), new String(methodDecl.selector)};
+       this.handle(
+               IProblem.UnexpectedStaticModifierForMethod,
+               arguments,
+               arguments,
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void unhandledException(TypeBinding exceptionType, ASTNode location) {
+
+       boolean insideDefaultConstructor = 
+               (this.referenceContext instanceof ConstructorDeclaration)
+                       && ((ConstructorDeclaration)this.referenceContext).isDefaultConstructor();
+       boolean insideImplicitConstructorCall =
+               (location instanceof ExplicitConstructorCall)
+                       && (((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper);
+
+       this.handle(
+               insideDefaultConstructor
+                       ? IProblem.UnhandledExceptionInDefaultConstructor
+                       : (insideImplicitConstructorCall 
+                                       ? IProblem.UndefinedConstructorInImplicitConstructorCall
+                                       : IProblem.UnhandledException),
+               new String[] {new String(exceptionType.readableName())},
+               new String[] {new String(exceptionType.shortReadableName())},
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void uninitializedBlankFinalField(FieldBinding binding, ASTNode location) {
+       String[] arguments = new String[] {new String(binding.readableName())};
+       this.handle(
+               IProblem.UninitializedBlankFinalField,
+               arguments,
+               arguments,
+               location.sourceStart,
+               fieldLocation(binding, location));
+}
+public void uninitializedLocalVariable(LocalVariableBinding binding, ASTNode location) {
+       String[] arguments = new String[] {new String(binding.readableName())};
+       this.handle(
+               IProblem.UninitializedLocalVariable,
+               arguments,
+               arguments,
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void unmatchedBracket(int position, ReferenceContext context, CompilationResult compilationResult) {
+       this.handle(
+               IProblem.UnmatchedBracket, 
+               NoArgument,
+               NoArgument,
+               position, 
+               position,
+               context,
+               compilationResult);
+}
+public void unnecessaryCast(CastExpression castExpression) {
+       TypeBinding castedExpressionType = castExpression.expression.resolvedType;
+       this.handle(
+               IProblem.UnnecessaryCast,
+               new String[]{ new String(castedExpressionType.readableName()), new String(castExpression.resolvedType.readableName())},
+               new String[]{ new String(castedExpressionType.shortReadableName()), new String(castExpression.resolvedType.shortReadableName())},
+               castExpression.sourceStart,
+               castExpression.sourceEnd);
+}
+public void unnecessaryCastForArgument(CastExpression castExpression, TypeBinding parameterType) {
+       TypeBinding castedExpressionType = castExpression.expression.resolvedType;
+       this.handle(
+               IProblem.UnnecessaryArgumentCast,
+               new String[]{ new String(castedExpressionType.readableName()), new String(castExpression.resolvedType.readableName()), new String(parameterType.readableName())},
+               new String[]{ new String(castedExpressionType.shortReadableName()), new String(castExpression.resolvedType.shortReadableName()), new String(parameterType.shortReadableName())},
+               castExpression.sourceStart,
+               castExpression.sourceEnd);
+}
+public void unnecessaryInstanceof(InstanceOfExpression instanceofExpression, TypeBinding checkType) {
+       TypeBinding expressionType = instanceofExpression.expression.resolvedType;
+       this.handle(
+               IProblem.UnnecessaryInstanceof,
+               new String[]{ new String(expressionType.readableName()), new String(checkType.readableName())},
+               new String[]{ new String(expressionType.shortReadableName()), new String(checkType.shortReadableName())},
+               instanceofExpression.sourceStart,
+               instanceofExpression.sourceEnd);
+}
+public void unqualifiedFieldAccess(NameReference reference, FieldBinding field) {
+       int end = reference.sourceEnd;
+       if (reference instanceof QualifiedNameReference) {
+               QualifiedNameReference qref = (QualifiedNameReference) reference;
+               end = (int) qref.sourcePositions[0];
+       }
+       this.handle(
+               IProblem.UnqualifiedFieldAccess,
+               new String[] {new String(field.declaringClass.readableName()), new String(field.name)},
+               new String[] {new String(field.declaringClass.shortReadableName()), new String(field.name)},
+               reference.sourceStart,
+               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,
+               new String[] {
+                       new String(exceptionType.readableName()),
+                }, 
+               new String[] {
+                       new String(exceptionType.shortReadableName()),
+                }, 
+               location.sourceStart,
+               location.sourceEnd);
+}
+public void unreachableCode(Statement statement) {
+       this.handle(
+               IProblem.CodeCannotBeReached,
+               NoArgument,
+               NoArgument,
+               statement.sourceStart,
+               statement.sourceEnd);
+}
+public void unresolvableReference(NameReference nameRef, Binding binding) {
+       int severity = Error;
+/* also need to check that the searchedType is the receiver type
+       if (binding instanceof ProblemBinding) {
+               ProblemBinding problem = (ProblemBinding) binding;
+               if (problem.searchType != null && problem.searchType.isHierarchyInconsistent())
+                       severity = SecondaryError;
+       }
+*/
+       String[] arguments = new String[] {new String(binding.readableName())};
+       int end = nameRef.sourceEnd;
+       if (nameRef instanceof QualifiedNameReference) {
+               QualifiedNameReference ref = (QualifiedNameReference) nameRef;
+               if (ref.indexOfFirstFieldBinding >= 1)
+                       end = (int) ref.sourcePositions[ref.indexOfFirstFieldBinding - 1];
+       }
+       this.handle(
+               IProblem.UndefinedName,
+               arguments,
+               arguments,
+               severity,
+               nameRef.sourceStart,
+               end);
+}
+public void unusedArgument(LocalDeclaration localDecl) {
+
+       String[] arguments = new String[] {new String(localDecl.name)};
+       this.handle(
+               IProblem.ArgumentIsNeverUsed,
+               arguments,
+               arguments,
+               localDecl.sourceStart,
+               localDecl.sourceEnd);
+}
+public void unusedDeclaredThrownException(ReferenceBinding exceptionType, AbstractMethodDeclaration method, ASTNode location) {
+       if (method.isConstructor()) {
+               this.handle(
+                       IProblem.UnusedConstructorDeclaredThrownException,
+                       new String[] {
+                               new String(method.binding.declaringClass.readableName()),
+                               parametersAsString(method.binding),
+                               new String(exceptionType.readableName()),
+                        }, 
+                       new String[] {
+                               new String(method.binding.declaringClass.shortReadableName()),
+                               parametersAsShortString(method.binding),
+                               new String(exceptionType.shortReadableName()),
+                        }, 
+                       location.sourceStart,
+                       location.sourceEnd);
+       } else {
+               this.handle(
+                       IProblem.UnusedMethodDeclaredThrownException,
+                       new String[] {
+                               new String(method.binding.declaringClass.readableName()),
+                               new String(method.selector),
+                               parametersAsString(method.binding),
+                               new String(exceptionType.readableName()),
+                        }, 
+                       new String[] {
+                               new String(method.binding.declaringClass.shortReadableName()),
+                               new String(method.selector),
+                               parametersAsShortString(method.binding),
+                               new String(exceptionType.shortReadableName()),
+                        }, 
+                       location.sourceStart,
+                       location.sourceEnd);
+       }
+}
+public void unusedImport(ImportReference importRef) {
+       String[] arguments = new String[] { CharOperation.toString(importRef.tokens) };
+       this.handle(
+               IProblem.UnusedImport,
+               arguments,
+               arguments,
+               importRef.sourceStart,
+               importRef.sourceEnd); 
+}
+public void unusedLocalVariable(LocalDeclaration localDecl) {
+       String[] arguments = new String[] {new String(localDecl.name)};
+       this.handle(
+               IProblem.LocalVariableIsNeverUsed,
+               arguments,
+               arguments,
+               localDecl.sourceStart,
+               localDecl.sourceEnd);
+}
+public void unusedPrivateConstructor(ConstructorDeclaration constructorDecl) {
+       
+       if (computeSeverity(IProblem.UnusedPrivateConstructor) == Ignore) return;
+
+       // no complaint for no-arg constructors (or default ones) - known pattern to block instantiation
+       if (constructorDecl.arguments == null || constructorDecl.arguments.length == 0) return;
+                                       
+       MethodBinding constructor = constructorDecl.binding;
+       this.handle(
+                       IProblem.UnusedPrivateConstructor,
+               new String[] {
+                       new String(constructor.declaringClass.readableName()),
+                       parametersAsString(constructor)
+                }, 
+               new String[] {
+                       new String(constructor.declaringClass.shortReadableName()),
+                       parametersAsShortString(constructor)
+                }, 
+               constructorDecl.sourceStart,
+               constructorDecl.sourceEnd);
+}
+public void unusedPrivateField(FieldDeclaration fieldDecl) {
+       
+       if (computeSeverity(IProblem.UnusedPrivateField) == Ignore) return;
+
+       FieldBinding field = fieldDecl.binding;
+       
+       if (CharOperation.equals(TypeConstants.SERIALVERSIONUID, field.name)
+                       && field.isStatic()
+                       && field.isFinal()
+                       && BaseTypes.LongBinding == field.type) {
+                               return; // do not report unused serialVersionUID field
+       }
+       if (CharOperation.equals(TypeConstants.SERIALPERSISTENTFIELDS, field.name)
+                       && field.isStatic()
+                       && field.isFinal()
+                       && field.type.dimensions() == 1
+                       && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTSTREAMFIELD, field.type.leafComponentType().readableName())) {
+                               return; // do not report unused serialPersistentFields field
+       }
+       this.handle(
+                       IProblem.UnusedPrivateField,
+               new String[] {
+                       new String(field.declaringClass.readableName()),
+                       new String(field.name),
+                }, 
+               new String[] {
+                       new String(field.declaringClass.shortReadableName()),
+                       new String(field.name),
+                }, 
+               fieldDecl.sourceStart,
+               fieldDecl.sourceEnd);
+}
+public void unusedPrivateMethod(AbstractMethodDeclaration methodDecl) {
+
+       if (computeSeverity(IProblem.UnusedPrivateMethod) == Ignore) return;
+       
+       MethodBinding method = methodDecl.binding;
+       
+       // no report for serialization support 'void readObject(ObjectInputStream)'
+       if (!method.isStatic()
+                       && BaseTypes.VoidBinding == method.returnType
+                       && method.parameters.length == 1
+                       && method.parameters[0].dimensions() == 0
+                       && CharOperation.equals(method.selector, TypeConstants.READOBJECT)
+                       && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTINPUTSTREAM, method.parameters[0].readableName())) {
+               return;
+       }
+       // no report for serialization support 'void writeObject(ObjectOutputStream)'
+       if (!method.isStatic()
+                       && BaseTypes.VoidBinding == method.returnType
+                       && method.parameters.length == 1
+                       && method.parameters[0].dimensions() == 0
+                       && CharOperation.equals(method.selector, TypeConstants.WRITEOBJECT)
+                       && CharOperation.equals(TypeConstants.CharArray_JAVA_IO_OBJECTOUTPUTSTREAM, method.parameters[0].readableName())) {
+               return;
+       }
+       // no report for serialization support 'Object readResolve()'
+       if (!method.isStatic()
+                       && TypeIds.T_Object == method.returnType.id
+                       && method.parameters.length == 0
+                       && CharOperation.equals(method.selector, TypeConstants.READRESOLVE)) {
+               return;
+       }
+       // no report for serialization support 'Object writeReplace()'
+       if (!method.isStatic()
+                       && TypeIds.T_Object == method.returnType.id
+                       && method.parameters.length == 0
+                       && CharOperation.equals(method.selector, TypeConstants.WRITEREPLACE)) {
+               return;
+       }
+       this.handle(
+                       IProblem.UnusedPrivateMethod,
+               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)
+                }, 
+               methodDecl.sourceStart,
+               methodDecl.sourceEnd);
+}
+public void unusedPrivateType(TypeDeclaration typeDecl) {
+       
+       if (computeSeverity(IProblem.UnusedPrivateType) == Ignore) return;
+
+       ReferenceBinding type = typeDecl.binding;
+       this.handle(
+                       IProblem.UnusedPrivateType,
+               new String[] {
+                       new String(type.readableName()),
+                }, 
+               new String[] {
+                       new String(type.shortReadableName()),
+                }, 
+               typeDecl.sourceStart,
+               typeDecl.sourceEnd);
+}
+public void useAssertAsAnIdentifier(int sourceStart, int sourceEnd) {
+       this.handle(
+               IProblem.UseAssertAsAnIdentifier,
+               NoArgument,
+               NoArgument,
+               sourceStart,
+               sourceEnd);     
+}
+
+public void variableTypeCannotBeVoid(AbstractVariableDeclaration varDecl) {
+       String[] arguments = new String[] {new String(varDecl.name)};
+       this.handle(
+               IProblem.VariableTypeCannotBeVoid,
+               arguments,
+               arguments,
+               varDecl.sourceStart,
+               varDecl.sourceEnd);
+}
+public void variableTypeCannotBeVoidArray(AbstractVariableDeclaration varDecl) {
+       String[] arguments = new String[] {new String(varDecl.name)};
+       this.handle(
+               IProblem.VariableTypeCannotBeVoidArray,
+               arguments,
+               arguments,
+               varDecl.sourceStart,
+               varDecl.sourceEnd);
+}
+public void visibilityConflict(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+       this.handle(
+               //      Cannot reduce the visibility of the inherited method from %1
+               // 8.4.6.3 - The access modifier of an hiding method must provide at least as much access as the hidden method.
+               // 8.4.6.3 - The access modifier of an overiding method must provide at least as much access as the overriden method.
+               IProblem.MethodReducesVisibility,
+               new String[] {new String(inheritedMethod.declaringClass.readableName())},
+               new String[] {new String(inheritedMethod.declaringClass.shortReadableName())},
+               currentMethod.sourceStart(),
+               currentMethod.sourceEnd());
+}
+public void nonExternalizedStringLiteral(ASTNode location) {
+       this.handle(
+               IProblem.NonExternalizedStringLiteral,
+               NoArgument,
+               NoArgument,
+               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$
+       }
+       this.handle(
+               IProblem.ParsingErrorUnexpectedEOF,
+               arguments,
+               arguments,
+               start,
+               end);
+}
+public void parseErrorMergeTokens(
+       int start,
+       int end,
+       String expectedToken){
+       String[] arguments = new String[] {expectedToken};
+       this.handle(
+               IProblem.ParsingErrorMergeTokens,
+               arguments,
+               arguments,
+               start,
+               end);
+}
+public void parseErrorMisplacedConstruct(
+       int start,
+       int end){
+       this.handle(
+               IProblem.ParsingErrorMisplacedConstruct,
+               NoArgument,
+               NoArgument,
+               start,
+               end);
+}
+public void parseErrorNoSuggestion(
+       int start,
+       int end,
+       int currentKind,
+       char[] errorTokenSource,
+       String errorTokenName){
+       this.syntaxError(
+               IProblem.ParsingErrorNoSuggestion,
+               start, 
+               end, 
+               currentKind,
+               errorTokenSource, 
+               errorTokenName,
+               null); 
+}
+public void parseErrorDeleteTokens(
+       int start,
+       int end){
+       this.handle(
+               IProblem.ParsingErrorDeleteTokens,
+               NoArgument,
+               NoArgument,
+               start,
+               end);
+}
+public void parseErrorNoSuggestionForTokens(
+       int start,
+       int end){
+       this.handle(
+               IProblem.ParsingErrorNoSuggestionForTokens,
+               NoArgument,
+               NoArgument,
+               start,
+               end);
+}
+public void parseErrorReplaceTokens(
+       int start,
+       int end,
+       String expectedToken){
+       String[] arguments = new String[] {expectedToken};
+       this.handle(
+               IProblem.ParsingErrorReplaceTokens,
+               arguments,
+               arguments,
+               start,
+               end);
+}
+public void parseErrorInsertToComplete(
+       int start,
+       int end,
+       String inserted,
+       String completed){
+       String[] arguments = new String[] {inserted, completed};
+       this.handle(
+               IProblem.ParsingErrorInsertToComplete,
+               arguments,
+               arguments,
+               start,
+               end);
+}
+public void parseErrorInsertToCompleteScope(
+       int start,
+       int end,
+       String inserted){
+       String[] arguments = new String[] {inserted};
+       this.handle(
+               IProblem.ParsingErrorInsertToCompleteScope,
+               arguments,
+               arguments,
+               start,
+               end);
+}
+public void parseErrorInsertToCompletePhrase(
+       int start,
+       int end,
+       String inserted){
+       String[] arguments = new String[] {inserted};
+       this.handle(
+               IProblem.ParsingErrorInsertToCompletePhrase,
+               arguments,
+               arguments,
+               start,
+               end);
+}
+public void wrongSequenceOfExceptionTypesError(TryStatement statement, TypeBinding exceptionType, int under, TypeBinding hidingExceptionType) {
+       //the two catch block under and upper are in an incorrect order.
+       //under should be define BEFORE upper in the source
+
+       TypeReference typeRef = statement.catchArguments[under].type;
+       this.handle(
+               IProblem.InvalidCatchBlockSequence,
+               new String[] {
+                       new String(exceptionType.readableName()),
+                       new String(hidingExceptionType.readableName()),
+                }, 
+               new String[] {
+                       new String(exceptionType.shortReadableName()),
+                       new String(hidingExceptionType.shortReadableName()),
+                }, 
+               typeRef.sourceStart,
+               typeRef.sourceEnd);
+}
+
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java b/src/java/org/eclipse/jdt/internal/compiler/problem/ProblemSeverities.java
new file mode 100644 (file)
index 0000000..d2cf193
--- /dev/null
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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.problem;
+
+public interface ProblemSeverities {
+       
+       final int Ignore = -1; // during handling only
+       final int Warning = 0; // during handling only
+
+       final int Error = 1; // when bit is set: problem is error, if not it is a warning
+       final int AbortCompilation = 2;
+       final int AbortCompilationUnit = 4;
+       final int AbortType = 8;
+       final int AbortMethod = 16;
+       final int Abort = 30; // 2r11110
+       final int SecondaryError = 64;
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java b/src/java/org/eclipse/jdt/internal/compiler/problem/ShouldNotImplement.java
new file mode 100644 (file)
index 0000000..a6533e5
--- /dev/null
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.problem;
+
+/*
+ * Special unchecked exception type used 
+ * to denote implementation that should never be reached.
+ *
+ *     (internal only)
+ */
+public class ShouldNotImplement extends RuntimeException {
+    
+       private static final long serialVersionUID = 2669970476264283736L; // backward compatible
+
+       public ShouldNotImplement(String message) {
+               super(message);
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/problem/messages.properties b/src/java/org/eclipse/jdt/internal/compiler/problem/messages.properties
new file mode 100644 (file)
index 0000000..e45ae5d
--- /dev/null
@@ -0,0 +1,381 @@
+###############################################################################
+# 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
+###############################################################################
+0 = {0}
+1 = super cannot be used in java.lang.Object
+2 = {0} cannot be resolved or is not a type
+3 = The type {0} is not visible
+4 = The type {0} is ambiguous
+5 = The type {0} is deprecated
+6 = The nested type {0} cannot be referenced using its binary name
+7 = The private type {0} is never used locally
+
+15 = Incompatible operand types {0} and {1}
+16 = Incompatible conditional operand types {0} and {1}
+17 = Type mismatch: cannot convert from {0} to {1}
+18 = The static member type {0}.{1} should be accessed directly
+
+20 = No enclosing instance of type {0} is accessible to invoke the super constructor. Must define a constructor and explicitly qualify its super constructor invocation with an instance of {0} (e.g. x.super() where x is an instance of {0}).
+21 = No enclosing instance of type {0} is accessible. Must qualify the allocation with an enclosing instance of type {0} (e.g. x.new A() where x is an instance of {0}).
+22 = No enclosing instance of the type {0} is accessible in scope
+23 = Illegal enclosing instance specification for type {0}
+24 = Cannot define static initializer in inner type {0}
+25 = Cannot refer to a non-final variable {0} inside an inner class defined in a different method
+26 = The member interface {0} can only be defined inside a top-level class or interface
+27 = Cannot use an expression of the type {0} as a valid enclosing instance
+28 = No enclosing instance of type {0} is available due to some intermediate constructor invocation
+29 = An anonymous class cannot subclass the final class {0}
+
+50 = {0} cannot be resolved
+51 = The local variable {0} may not have been initialized
+52 = void is an invalid type for the variable {0}
+53 = An array of void is an invalid type for the variable {0}
+54 = An array of void is an invalid type
+55 = Duplicate local variable {0}
+56 = Duplicate parameter {0}
+57 = The final local variable {0} may already have been assigned
+58 = The final local variable {0} cannot be assigned. It must be blank and not using a compound assignment
+
+60 = The final local variable {0} cannot be assigned, since it is defined in an enclosing type
+61 = The local variable {0} is never read
+62 = The parameter {0} is never read
+63 = The code of method {0}({1}) is exceeding the 65535 bytes limit
+64 = The code for the static initializer is exceeding the 65535 bytes limit
+65 = Too many parameters, parameter {0} is exceeding the limit of 255 words eligible for method parameters
+66 = Too many local variables, local variable {0} is exceeding the limit of 65535 words eligible for method local variables
+67 = Too many synthetic parameters, emulated parameter {0} is exceeding the limit of 255 words eligible for method parameters
+68 = Too many array dimensions. Maximum is 255
+69 = The code of constructor {0}({1}) is exceeding the 65535 bytes limit
+70 = {0} cannot be resolved or is not a field
+71 = The field {0} is not visible
+72 = The field {0} is ambiguous
+73 = The field {0}.{1} is deprecated
+74 = Cannot make a static reference to the non-static field {0}
+75 = Cannot reference a field before it is defined
+76 = The static field {0}.{1} should be accessed in a static way
+77 = The private field {0}.{1} is never read locally
+78 = The static field {0}.{1} should be accessed directly
+79 = Unqualified access to the field {0}.{1} 
+80 = The final field {0}.{1} cannot be assigned. It must be blank in this context, not qualified and not in compound assignment
+81 = The blank final field {0} may not have been initialized
+82 = The final field {0} may already have been assigned
+
+90 = The local variable {0} is hiding another local variable defined in an enclosing type scope
+91 = The local variable {0} is hiding a field from type {1}
+92 = The field {0}.{1} is hiding another local variable defined in an enclosing type scope
+93 = The field {0}.{1} is hiding a field from type {2}
+94 = The parameter {0} is hiding another local variable defined in an enclosing type scope
+95 = The parameter {0} is hiding a field from type {1}
+
+100 = The method {1}({2}) is undefined for the type {0}
+101 = The method {1}({2}) from the type {0} is not visible
+102 = The method {1}({2}) is ambiguous for the type {0}
+103 = The method {1}({2}) from the type {0} is deprecated
+104 = Cannot directly invoke the abstract method {1}({2}) for the type {0}
+105 = Void methods cannot return a value
+106 = Cannot return a void result
+107 = This method requires a body instead of a semicolon
+108 = This method must return a result of type {0}
+
+110 = This method has a constructor name
+111 = Return type for the method is missing
+112 = Native methods do not specify a body
+113 = Abstract methods do not specify a body
+114 = Cannot invoke {1}({2}) on the primitive type {0}
+115 = The method {1}({2}) in the type {0} is not applicable for the arguments ({3})
+116 = Cannot invoke {1}({2}) on the array type {0}
+117 = The static method {1}({2}) from the type {0} should be accessed in a static way
+118 = The private method {1}({2}) from the type {0} is never used locally
+119 = The static method {1}({2}) from the type {0} should be accessed directly 
+
+130 = The constructor {0}({1}) is undefined
+131 = The constructor {0}({1}) is not visible
+132 = The constructor {0}({1}) is ambiguous
+133 = The constructor {0}({1}) is deprecated
+134 = The private constructor {0}({1}) is never used locally
+135 = Cannot refer to an instance field {0} while explicitly invoking a constructor
+136 = Cannot refer to an instance method while explicitly invoking a constructor
+137 = Recursive constructor invocation {0}({1})
+138 = Cannot refer to ''this'' nor ''super'' while explicitly invoking a constructor
+139 = Constructor call must be the first statement in a constructor
+140 = Implicit super constructor {0}({1}) is undefined for default constructor. Must define an explicit constructor
+141 = Implicit super constructor {0}({1}) is not visible for default constructor. Must define an explicit constructor
+142 = Implicit super constructor {0}({1}) is ambiguous for default constructor. Must define an explicit constructor
+143 = Implicit super constructor {0}({1}) is undefined. Must explicitly invoke another constructor
+144 = Implicit super constructor {0}({1}) is not visible. Must explicitly invoke another constructor
+145 = Implicit super constructor {0}({1}) is ambiguous. Must explicitly invoke another constructor
+146 = Default constructor cannot handle exception type {0} thrown by implicit super constructor. Must define an explicit constructor
+147 = Unhandled exception type {0} thrown by implicit super constructor
+
+150 = The type of the expression must be an array type but it resolved to {0}
+151 = Must explicitly convert the char[] to a String
+152 = String constant is exceeding the limit of 65535 bytes of UTF8 encoding
+153 = case expressions must be constant expressions
+154 = 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
+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}
+161 = Unreachable code
+162 = Cannot return from within an initializer
+163 = Initializer does not complete normally
+164 = Expression must return a value
+165 = Unreachable catch block for {0}. Only more specific exceptions are thrown and handled by previous catch block(s).
+166 = The default case is already defined
+167 = Unreachable catch block for {0}. This exception is never thrown from the try statement body
+168 = Unhandled exception type {0}
+169 = case constant must be a char, byte, short, or int instead of {0}
+170 = Duplicate case
+171 = Duplicate label {0}
+172 = break cannot be used outside of a loop or a switch
+173 = continue cannot be used outside of a loop
+174 = The label {0} is missing
+175 = {0} is not a valid type''s argument for the synchronized statement
+176 = null is not a valid argument for the synchronized statement
+177 = Cannot throw null
+178 = The assignment to variable {0} has no effect
+179 = Possible accidental assignment in place of a comparison. A condition expression should not be reduced to an assignment
+180 = Unnecessary semicolon
+181 = Unnecessary cast to type {1} for expression of type {0}
+182 = Unnecessary cast to type {1} for expression of type {0}. It is already compatible with the argument type {2}
+183 = The expression of type {0} is already an instance of type {1}
+184 = finally block does not complete normally
+185 = The declared exception {3} is not actually thrown by the method {1}({2}) from type {0}
+186 = The declared exception {2} is not actually thrown by the constructor {0}({1})
+187 = Unreachable catch block for {0}. It is already handled by the catch block for {1}
+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
+193 = Access to enclosing constructor {0}({1}) 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
+
+200 = Cannot use {0} in a static context 
+201 = The method {1}({2}) from the type {0} is not static
+202 = Cannot specify an array dimension after an empty dimension
+203 = Invalid cast type expression
+204 = Syntax error on token "{0}", {1} expected
+205 = Syntax error on token "{0}", no accurate correction available
+206 = Invalid argument to operation ++/--
+207 = Interfaces cannot have constructors
+208 = Array constants can only be used in initializers
+209 = Syntax error on keyword "{0}"; {1} expected
+210 = Syntax error on keyword "{0}", no accurate correction available
+
+220 = Unmatched bracket
+221 = The primitive type {0} of {1} does not have a field {2}
+222 = Invalid expression as statement
+223 = The left-hand side of an assignment must be a variable
+224 = Missing semicolon
+225 = Invalid parenthesized expression
+
+230 = Syntax error on token "{0}", {1} expected before this token
+231 = Syntax error on token "{0}", {1} expected after this token
+232 = Syntax error on token "{0}", delete this token
+233 = Syntax error on tokens, delete these tokens
+234 = Syntax error on tokens, they can be merge to form {0}
+235 = Syntax error on token "{0}", invalid {1}
+236 = Syntax error on token(s), misplaced construct(s)
+237 = Syntax error on tokens, {0} expected instead
+238 = Syntax error on tokens, no accurate correction available
+239 = Syntax error, unexpected {0}
+240 = Syntax error, insert "{0}" to complete {1}
+241 = Syntax error, insert "{0}" to complete scope
+242 = Syntax error, insert "{0}" to complete phrase
+
+250 = Unexpected end of file
+251 = Invalid hex literal number
+252 = Invalid octal literal number
+253 = Invalid character constant
+254 = Invalid escape sequence (valid ones are  \\b  \\t  \\n  \\f  \\r  \\"  \\''  \\\\ )
+255 = Invalid input
+256 = Invalid unicode
+257 = Invalid float literal number
+258 = Null source string
+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>$
+
+300 = The interface {0} cannot define an initializer
+301 = Duplicate modifier for the type {0}
+302 = Illegal modifier for the class {0}; only public, abstract & final are permitted
+303 = Illegal modifier for the interface {0}; only public & abstract are permitted
+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
+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
+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}
+318 = Nested type {0} hides an enclosing type
+319 = Duplicate nested type {0}
+320 = Cannot throw the type {0}
+321 = The package {0} collides with a type
+322 = The type {1} collides with a package
+323 = The type {1} is already defined
+324 = The type {0} cannot be resolved. It is indirectly referenced from required .class files
+325 = The public type {1} must be defined in its own file
+326 = A package must be specified in {0} or a default package created
+327 = The hierarchy of the type {0} is inconsistent
+328 = The declared package does not match the expected package {0}
+329 = The type java.lang.Object cannot have a superclass or superinterfaces
+
+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
+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}
+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
+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
+363 = The abstract method {1} in type {0} can only be defined by an abstract class
+364 = void is an invalid type for the parameter {1} of the method {0}
+365 = An array of void is an invalid type for the parameter {1} of the method {0}
+366 = An array of void is an invalid return type for the method {0}
+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
+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
+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}
+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}
+404 = The return type is incompatible with {0}
+405 = The inherited method {0} cannot hide the public abstract method in {1}
+406 = This instance method cannot override the static method from {0}
+407 = This static method cannot hide the instance method from {0}
+408 = The static method {0} conflicts with the abstract method in {1}
+409 = Cannot reduce the visibility of the inherited method from {0}
+410 = The method {0} does not override the inherited method from {1} since it is private to a different package.
+411 = This class must implement the inherited abstract method {1}, but cannot override it since it is not visible from {0}. Either make the type abstract or make the inherited method visible.
+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
+
+420 = Code snippet support cannot find the class {0}
+421 = Code snippet support cannot find the method {0}.{1}({2}) 
+422 = super cannot be used in the code snippet code
+
+430 = Too many constants, the constant pool for {0} would exceed 65536 entries
+431 = The type generates a string that requires more than 65535 bytes to encode in Utf8 format in the constant pool
+
+432 = Too many fields for type {0}. Maximum is 65535
+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
+
+450 = {0} {1}
+
+460 = Empty block should be documented
+
+470 = Unexpected tag
+471 = Missing tag for parameter {0}
+472 = Missing parameter name
+473 = Duplicate tag for parameter
+474 = Parameter {0} is not declared
+475 = Missing tag for return type
+476 = Duplicate tag for return type
+477 = Missing tag for declared exception {0}
+478 = Missing class name
+479 = Invalid class name
+480 = Duplicate tag for thrown exception
+481 = Exception {0} is not declared
+482 = Missing reference
+483 = Invalid reference
+484 = Invalid URL link format
+485 = Invalid parameters declaration
+486 = Missing comment for {0} declaration
+487 = Invalid tag
+488 = {0} cannot be resolved or is not a field
+489 = The field {0} is not visible
+490 = The field {0} is ambiguous
+491 = The field {0}.{1} is deprecated
+492 = The constructor {0}({1}) is undefined
+493 = The constructor {0}({1}) is not visible
+494 = The constructor {0}({1}) is ambiguous
+495 = The constructor {0}({1}) is deprecated
+496 = The method {1}({2}) is undefined for the type {0}
+497 = The method {1}({2}) from the type {0} is not visible
+498 = The method {1}({2}) is ambiguous for the type {0}
+499 = The method {1}({2}) from the type {0} is deprecated
+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
+504 = The type {0} is not visible
+505 = The type {0} is ambiguous
+506 = The type {0} is deprecated
+507 = The nested type {0} cannot be referenced using its binary name
+508 = The method {1} is defined in an inherited type and an enclosing scope
+509 = The field {0} is defined in an inherited type and an enclosing scope 
+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: 
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/CompoundNameVector.java b/src/java/org/eclipse/jdt/internal/compiler/util/CompoundNameVector.java
new file mode 100644 (file)
index 0000000..66adf23
--- /dev/null
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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;
+
+public final class CompoundNameVector {
+       static int INITIAL_SIZE = 10;
+    
+       public int size;
+       int maxSize;
+       char[][][] elements;
+public CompoundNameVector() {
+       maxSize = INITIAL_SIZE;
+       size = 0;
+       elements = new char[maxSize][][];
+}
+public void add(char[][] newElement) {
+       if (size == maxSize)    // knows that size starts <= maxSize
+               System.arraycopy(elements, 0, (elements = new char[maxSize *= 2][][]), 0, size);
+       elements[size++] = newElement;
+}
+public void addAll(char[][][] newElements) {
+       if (size + newElements.length >= maxSize) {
+               maxSize = size + newElements.length;    // assume no more elements will be added
+               System.arraycopy(elements, 0, (elements = new char[maxSize][][]), 0, size);
+       }
+       System.arraycopy(newElements, 0, elements, size, newElements.length);
+       size += newElements.length;
+}
+public boolean contains(char[][] element) {
+       for (int i = size; --i >= 0;)
+               if (CharOperation.equals(element, elements[i]))
+                       return true;
+       return false;
+}
+public char[][] elementAt(int index) {
+       return elements[index];
+}
+public char[][] remove(char[][] element) {
+       // assumes only one occurrence of the element exists
+       for (int i = size; --i >= 0;)
+               if (element == elements[i]) {
+                       // shift the remaining elements down one spot
+                       System.arraycopy(elements, i + 1, elements, i, --size - i);
+                       elements[size] = null;
+                       return element;
+               }
+       return null;
+}
+public void removeAll() {
+       for (int i = size; --i >= 0;)
+               elements[i] = null;
+       size = 0;
+}
+public String toString() {
+       StringBuffer buffer = new StringBuffer();
+       for (int i = 0; i < size; i++) {
+               buffer.append(CharOperation.toString(elements[i])).append("\n"); //$NON-NLS-1$
+       }
+       return buffer.toString();
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfInt.java b/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfInt.java
new file mode 100644 (file)
index 0000000..6ea5078
--- /dev/null
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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 int keys.
+  */
+  
+public final class HashtableOfInt {
+       // to avoid using Enumerations, walk the individual tables skipping nulls
+       public int[] keyTable;
+       public Object[] valueTable;
+
+       public int elementSize; // number of elements in the table
+       int threshold;
+public HashtableOfInt() {
+       this(13);
+}
+public HashtableOfInt(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 int[extraRoom];
+       this.valueTable = new Object[extraRoom];
+}
+public boolean containsKey(int key) {
+       int index = key % valueTable.length;
+       int currentKey;
+       while ((currentKey = keyTable[index]) != 0) {
+               if (currentKey == key)
+                       return true;
+               index = (index + 1) % keyTable.length;
+       }
+       return false;
+}
+public Object get(int key) {
+       int index = key % valueTable.length;
+       int currentKey;
+       while ((currentKey = keyTable[index]) != 0) {
+               if (currentKey == key)  return valueTable[index];
+               index = (index + 1) % keyTable.length;
+       }
+       return null;
+}
+public Object put(int key, Object value) {
+       int index = key % valueTable.length;
+       int 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() {
+       HashtableOfInt newHashtable = new HashtableOfInt(elementSize * 2); // double the number of expected elements
+       int 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/java/org/eclipse/jdt/internal/compiler/util/HashtableOfIntValues.java b/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfIntValues.java
new file mode 100644 (file)
index 0000000..7c42adb
--- /dev/null
@@ -0,0 +1,148 @@
+/*******************************************************************************
+ * 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/java/org/eclipse/jdt/internal/compiler/util/HashtableOfLong.java b/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfLong.java
new file mode 100644 (file)
index 0000000..7437a6d
--- /dev/null
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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/java/org/eclipse/jdt/internal/compiler/util/HashtableOfObject.java b/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfObject.java
new file mode 100644 (file)
index 0000000..1acef0a
--- /dev/null
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * 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[] --> Object }
+ */
+public final class HashtableOfObject implements Cloneable {
+       
+       // to avoid using Enumerations, walk the individual tables skipping nulls
+       public char[] keyTable[];
+       public Object valueTable[];
+
+       public int elementSize; // number of elements in the table
+       int threshold;
+
+       public HashtableOfObject() {
+               this(13);
+       }
+
+       public HashtableOfObject(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 Object[extraRoom];
+       }
+
+       public Object clone() throws CloneNotSupportedException {
+               HashtableOfObject result = (HashtableOfObject) 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 Object[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 Object 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 null;
+       }
+
+       public Object put(char[] key, Object 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 Object 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)) {
+                               Object value = valueTable[index];
+                               elementSize--;
+                               keyTable[index] = null;
+                               valueTable[index] = null;
+                               rehash();
+                               return value;
+                       }
+                       index = (index + 1) % keyTable.length;
+               }
+               return null;
+       }
+
+       private void rehash() {
+
+               HashtableOfObject newHashtable = new HashtableOfObject(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$
+               Object object;
+               for (int i = 0, length = valueTable.length; i < length; i++)
+                       if ((object = valueTable[i]) != null)
+                               s += new String(keyTable[i]) + " -> " + object.toString() + "\n";       //$NON-NLS-2$ //$NON-NLS-1$
+               return s;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java b/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfPackage.java
new file mode 100644 (file)
index 0000000..3fd642a
--- /dev/null
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+
+public final class HashtableOfPackage {
+       // to avoid using Enumerations, walk the individual tables skipping nulls
+       public char[] keyTable[];
+       public PackageBinding valueTable[];
+
+       public int elementSize; // number of elements in the table
+       int threshold;
+public HashtableOfPackage() {
+       this(3); // usually not very large
+}
+public HashtableOfPackage(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 PackageBinding[extraRoom];
+}
+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 PackageBinding 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 null;
+}
+public PackageBinding put(char[] key, PackageBinding 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;
+}
+private void rehash() {
+       HashtableOfPackage newHashtable = new HashtableOfPackage(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$
+       PackageBinding pkg;
+       for (int i = 0, length = valueTable.length; i < length; i++)
+               if ((pkg = valueTable[i]) != null)
+                       s += pkg.toString() + "\n"; //$NON-NLS-1$
+       return s;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java b/src/java/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java
new file mode 100644 (file)
index 0000000..a64e8ea
--- /dev/null
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+
+public final class HashtableOfType {
+       // to avoid using Enumerations, walk the individual tables skipping nulls
+       public char[] keyTable[];
+       public ReferenceBinding valueTable[];
+
+       public int elementSize; // number of elements in the table
+       int threshold;
+public HashtableOfType() {
+       this(3);
+}
+public HashtableOfType(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 ReferenceBinding[extraRoom];
+}
+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 ReferenceBinding 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 null;
+}
+public ReferenceBinding put(char[] key, ReferenceBinding 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;
+}
+private void rehash() {
+       HashtableOfType newHashtable = new HashtableOfType(elementSize < 100 ? 100 : 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$
+       ReferenceBinding type;
+       for (int i = 0, length = valueTable.length; i < length; i++)
+               if ((type = valueTable[i]) != null)
+                       s += type.toString() + "\n"; //$NON-NLS-1$
+       return s;
+}
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/ObjectVector.java b/src/java/org/eclipse/jdt/internal/compiler/util/ObjectVector.java
new file mode 100644 (file)
index 0000000..50c93b0
--- /dev/null
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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;
+
+public final class ObjectVector {
+       
+       static int INITIAL_SIZE = 10;
+
+       public int size;
+       int maxSize;
+       Object[] elements;
+       
+       public ObjectVector() {
+
+               this.maxSize = INITIAL_SIZE;
+               this.size = 0;
+               this.elements = new Object[this.maxSize];
+       }
+
+       public void add(Object newElement) {
+
+               if (this.size == this.maxSize) // knows that size starts <= maxSize
+                       System.arraycopy(this.elements, 0, (this.elements = new Object[this.maxSize *= 2]), 0, this.size);
+               this.elements[this.size++] = newElement;
+       }
+
+       public void addAll(Object[] newElements) {
+
+               if (this.size + newElements.length >= this.maxSize) {
+                       maxSize = this.size + newElements.length; // assume no more elements will be added
+                       System.arraycopy(this.elements, 0, (this.elements = new Object[this.maxSize]), 0, this.size);
+               }
+               System.arraycopy(newElements, 0, this.elements, size, newElements.length);
+               this.size += newElements.length;
+       }
+
+       public void addAll(ObjectVector newVector) {
+
+               if (this.size + newVector.size >= this.maxSize) {
+                       maxSize = this.size + newVector.size; // assume no more elements will be added
+                       System.arraycopy(this.elements, 0, (this.elements = new Object[this.maxSize]), 0, this.size);
+               }
+               System.arraycopy(newVector.elements, 0, this.elements, size, newVector.size);
+               this.size += newVector.size;
+       }
+
+       /**
+        * Identity check
+        */
+       public boolean containsIdentical(Object element) {
+
+               for (int i = this.size; --i >= 0;)
+                       if (element == this.elements[i])
+                               return true;
+               return false;
+       }
+
+       /**
+        * Equality check
+        */
+       public boolean contains(Object element) {
+
+               for (int i = this.size; --i >= 0;)
+                       if (element.equals(this.elements[i]))
+                               return true;
+               return false;
+       }
+
+       public void copyInto(Object[] targetArray){
+               
+               this.copyInto(targetArray, 0);
+       }
+       
+       public void copyInto(Object[] targetArray, int index){
+               
+               System.arraycopy(this.elements, 0, targetArray, index, this.size);
+       }       
+       
+       public Object elementAt(int index) {
+
+               return this.elements[index];
+       }
+
+       public Object find(Object element) {
+
+               for (int i = this.size; --i >= 0;)
+                       if (element.equals(this.elements[i]))
+                               return element;
+               return null;
+       }
+
+       public Object remove(Object element) {
+
+               // assumes only one occurrence of the element exists
+               for (int i = this.size; --i >= 0;)
+                       if (element.equals(this.elements[i])) {
+                               // shift the remaining elements down one spot
+                               System.arraycopy(this.elements, i + 1, this.elements, i, --this.size - i);
+                               this.elements[this.size] = null;
+                               return element;
+                       }
+               return null;
+       }
+
+       public void removeAll() {
+               
+               for (int i = this.size; --i >= 0;)
+                       this.elements[i] = null;
+               this.size = 0;
+       }
+
+       public int size(){
+               
+               return this.size;
+       }
+       
+       public String toString() {
+               
+               String s = ""; //$NON-NLS-1$
+               for (int i = 0; i < this.size; i++)
+                       s += this.elements[i].toString() + "\n"; //$NON-NLS-1$
+               return s;
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/SimpleNameVector.java b/src/java/org/eclipse/jdt/internal/compiler/util/SimpleNameVector.java
new file mode 100644 (file)
index 0000000..0c5b80b
--- /dev/null
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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;
+
+public final class SimpleNameVector {
+       
+       static int INITIAL_SIZE = 10;
+
+       public int size;
+       int maxSize;
+       char[][] elements;
+       
+       public SimpleNameVector() {
+               
+               this.maxSize = INITIAL_SIZE;
+               this.size = 0;
+               this.elements = new char[this.maxSize][];
+       }
+       
+       public void add(char[] newElement) {
+               
+               if (this.size == this.maxSize) // knows that size starts <= maxSize
+                       System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize *= 2][]), 0, this.size);
+               this.elements[size++] = newElement;
+       }
+       
+       public void addAll(char[][] newElements) {
+               
+               if (this.size + newElements.length >= this.maxSize) {
+                       this.maxSize = this.size + newElements.length; // assume no more elements will be added
+                       System.arraycopy(this.elements, 0, (this.elements = new char[this.maxSize][]), 0, this.size);
+               }
+               System.arraycopy(newElements, 0, this.elements, this.size, newElements.length);
+               this.size += newElements.length;
+       }
+       
+       public void copyInto(Object[] targetArray){
+               
+               System.arraycopy(this.elements, 0, targetArray, 0, this.size);
+       }
+       
+       public boolean contains(char[] element) {
+               
+               for (int i = this.size; --i >= 0;)
+                       if (CharOperation.equals(element, this.elements[i]))
+                               return true;
+               return false;
+       }
+       
+       public char[] elementAt(int index) {
+               return this.elements[index];
+       }
+       
+       public char[] remove(char[] element) {
+               
+               // assumes only one occurrence of the element exists
+               for (int i = this.size; --i >= 0;)
+                       if (element == this.elements[i]) {
+                               // shift the remaining elements down one spot
+                               System.arraycopy(this.elements, i + 1, this.elements, i, --this.size - i);
+                               this.elements[this.size] = null;
+                               return element;
+                       }
+               return null;
+       }
+       
+       public void removeAll() {
+               
+               for (int i = this.size; --i >= 0;)
+                       this.elements[i] = null;
+               this.size = 0;
+       }
+       
+       public int size(){
+               
+               return this.size;
+       }
+       
+       public String toString() {
+               StringBuffer buffer = new StringBuffer();
+               for (int i = 0; i < this.size; i++) {
+                       buffer.append(this.elements[i]).append("\n"); //$NON-NLS-1$
+               }
+               return buffer.toString();
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java b/src/java/org/eclipse/jdt/internal/compiler/util/SuffixConstants.java
new file mode 100644 (file)
index 0000000..609cffb
--- /dev/null
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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;
+
+public interface SuffixConstants {
+       public final static String EXTENSION_class = "class"; //$NON-NLS-1$
+       public final static String EXTENSION_CLASS = "CLASS"; //$NON-NLS-1$
+       public final static String EXTENSION_java = "java"; //$NON-NLS-1$
+       public final static String EXTENSION_JAVA = "JAVA"; //$NON-NLS-1$
+       
+       public final static String SUFFIX_STRING_class = "." + EXTENSION_class; //$NON-NLS-1$
+       public final static String SUFFIX_STRING_CLASS = "." + EXTENSION_CLASS; //$NON-NLS-1$
+       public final static String SUFFIX_STRING_java = "." + EXTENSION_java; //$NON-NLS-1$
+       public final static String SUFFIX_STRING_JAVA = "." + EXTENSION_JAVA; //$NON-NLS-1$
+       
+       public final static char[] SUFFIX_class = SUFFIX_STRING_class.toCharArray();
+       public final static char[] SUFFIX_CLASS = SUFFIX_STRING_CLASS.toCharArray();
+       public final static char[] SUFFIX_java = SUFFIX_STRING_java.toCharArray();
+       public final static char[] SUFFIX_JAVA = SUFFIX_STRING_JAVA.toCharArray();
+       
+       public final static String EXTENSION_jar = "jar"; //$NON-NLS-1$
+       public final static String EXTENSION_JAR = "JAR"; //$NON-NLS-1$
+       public final static String EXTENSION_zip = "zip"; //$NON-NLS-1$
+       public final static String EXTENSION_ZIP = "ZIP"; //$NON-NLS-1$
+
+       public final static String SUFFIX_STRING_jar = "." + EXTENSION_jar; //$NON-NLS-1$
+       public final static String SUFFIX_STRING_JAR = "." + EXTENSION_JAR; //$NON-NLS-1$
+       public final static String SUFFIX_STRING_zip = "." + EXTENSION_zip; //$NON-NLS-1$
+       public final static String SUFFIX_STRING_ZIP = "." + EXTENSION_ZIP; //$NON-NLS-1$
+
+       public final static char[] SUFFIX_jar = SUFFIX_STRING_jar.toCharArray();
+       public final static char[] SUFFIX_JAR = SUFFIX_STRING_JAR.toCharArray();
+       public final static char[] SUFFIX_zip = SUFFIX_STRING_zip.toCharArray(); 
+       public final static char[] SUFFIX_ZIP = SUFFIX_STRING_ZIP.toCharArray();
+}
\ No newline at end of file
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/Util.java b/src/java/org/eclipse/jdt/internal/compiler/util/Util.java
new file mode 100644 (file)
index 0000000..94b7567
--- /dev/null
@@ -0,0 +1,523 @@
+/*******************************************************************************
+ * 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 java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import org.eclipse.jdt.core.compiler.CharOperation;
+
+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;
+
+       /* Bundle containing messages */
+       protected static ResourceBundle bundle;
+       private final static String bundleName =
+               "org.eclipse.jdt.internal.compiler.util.messages"; //$NON-NLS-1$
+       static {
+               relocalize();
+       }
+       /**
+        * Lookup the message with the given ID in this catalog and bind its
+        * substitution locations with the given strings.
+        */
+       public static String bind(String id, String binding1, String binding2) {
+               return bind(id, new String[] { binding1, binding2 });
+       }
+       /**
+        * Lookup the message with the given ID in this catalog and bind its
+        * substitution locations with the given string.
+        */
+       public static String bind(String id, String binding) {
+               return bind(id, new String[] { binding });
+       }
+       /**
+        * Lookup the message with the given ID in this catalog and bind its
+        * substitution locations with the given string values.
+        */
+       public static String bind(String id, String[] bindings) {
+               if (id == null)
+                       return "No message available"; //$NON-NLS-1$
+               String message = null;
+               try {
+                       message = bundle.getString(id);
+               } catch (MissingResourceException e) {
+                       // If we got an exception looking for the message, fail gracefully by just returning
+                       // the id we were looking for.  In most cases this is semi-informative so is not too bad.
+                       return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+               }
+               // for compatibility with MessageFormat which eliminates double quotes in original message
+               char[] messageWithNoDoubleQuotes =
+                       CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+       
+               if (bindings == null) return new String(messageWithNoDoubleQuotes);
+       
+               int length = messageWithNoDoubleQuotes.length;
+               int start = 0;
+               int end = length;
+               StringBuffer output = null;
+               while (true) {
+                       if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes, start)) > -1) {
+                               if (output == null) output = new StringBuffer(length+bindings.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]);
+                                       } 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)
+                                                       }
+                                               }
+                                               if (!done) output.append(messageWithNoDoubleQuotes, end + 1, start - end);
+                                       } catch (ArrayIndexOutOfBoundsException e) {
+                                               output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
+                                       }
+                                       start++;
+                               } else {
+                                       output.append(messageWithNoDoubleQuotes, end, length);
+                                       break;
+                               }
+                       } else {
+                               if (output == null) return new String(messageWithNoDoubleQuotes);
+                               output.append(messageWithNoDoubleQuotes, start, length - start);
+                               break;
+                       }
+               }
+               return output.toString();
+       }
+       /**
+        * Lookup the message with the given ID in this catalog 
+        */
+       public static String bind(String id) {
+               return bind(id, (String[]) null);
+       }
+       /**
+        * Creates a NLS catalog for the given locale.
+        */
+       public static void relocalize() {
+               try {
+                       bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+               } catch(MissingResourceException e) {
+                       System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
+                       throw e;
+               }
+       }
+       /**
+        * 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 {
+
+               return getInputStreamAsCharArray(new ByteArrayInputStream(bytes), bytes.length, encoding);
+
+       }
+       /**
+        * Returns the contents of the given file as a byte array.
+        * @throws IOException if a problem occured reading the file.
+        */
+       public static byte[] getFileByteContent(File file) throws IOException {
+               InputStream stream = null;
+               try {
+                       stream = new BufferedInputStream(new FileInputStream(file));
+                       return getInputStreamAsByteArray(stream, (int) file.length());
+               } finally {
+                       if (stream != null) {
+                               try {
+                                       stream.close();
+                               } catch (IOException e) {
+                                       // ignore
+                               }
+                       }
+               }
+       }
+       /**
+        * Returns the contents of the given file as a char array.
+        * When encoding is null, then the platform default one is used
+        * @throws IOException if a problem occured reading the file.
+        */
+       public static char[] getFileCharContent(File file, String encoding) throws IOException {
+               InputStream stream = null;
+               try {
+                       stream = new BufferedInputStream(new FileInputStream(file));
+                       return getInputStreamAsCharArray(stream, (int) file.length(), encoding);
+               } finally {
+                       if (stream != null) {
+                               try {
+                                       stream.close();
+                               } catch (IOException e) {
+                                       // ignore
+                               }
+                       }
+               }
+       }
+       /*
+        * NIO support to get input stream as byte array.
+        * Not used as with JDK 1.4.2 this support is slower than standard IO one...
+        * Keep it as comment for future in case of next JDK versions improve performance
+        * in this area...
+        *
+       public static byte[] getInputStreamAsByteArray(FileInputStream stream, int length)
+               throws IOException {
+
+               FileChannel channel = stream.getChannel();
+               int size = (int)channel.size();
+               if (length >= 0 && length < size) size = length;
+               byte[] contents = new byte[size];
+               ByteBuffer buffer = ByteBuffer.wrap(contents);
+               channel.read(buffer);
+               return contents;
+       }
+       */
+       /**
+        * Returns the given input stream's contents as a byte array.
+        * If a length is specified (ie. if length != -1), only length bytes
+        * are returned. Otherwise all bytes in the stream are returned.
+        * Note this doesn't close the stream.
+        * @throws IOException if a problem occured reading the stream.
+        */
+       public static byte[] getInputStreamAsByteArray(InputStream stream, int length)
+               throws IOException {
+               byte[] contents;
+               if (length == -1) {
+                       contents = new byte[0];
+                       int contentsLength = 0;
+                       int amountRead = -1;
+                       do {
+                               int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);  // read at least 8K
+                               
+                               // resize contents if needed
+                               if (contentsLength + amountRequested > contents.length) {
+                                       System.arraycopy(
+                                               contents,
+                                               0,
+                                               contents = new byte[contentsLength + amountRequested],
+                                               0,
+                                               contentsLength);
+                               }
+
+                               // read as many bytes as possible
+                               amountRead = stream.read(contents, contentsLength, amountRequested);
+
+                               if (amountRead > 0) {
+                                       // remember length of contents
+                                       contentsLength += amountRead;
+                               }
+                       } while (amountRead != -1); 
+
+                       // resize contents if necessary
+                       if (contentsLength < contents.length) {
+                               System.arraycopy(
+                                       contents,
+                                       0,
+                                       contents = new byte[contentsLength],
+                                       0,
+                                       contentsLength);
+                       }
+               } else {
+                       contents = new byte[length];
+                       int len = 0;
+                       int readSize = 0;
+                       while ((readSize != -1) && (len != length)) {
+                               // See PR 1FMS89U
+                               // We record first the read size. In this case len is the actual read size.
+                               len += readSize;
+                               readSize = stream.read(contents, len, length - len);
+                       }
+               }
+
+               return contents;
+       }
+       /*
+        * NIO support to get input stream as char array.
+        * Not used as with JDK 1.4.2 this support is slower than standard IO one...
+        * Keep it as comment for future in case of next JDK versions improve performance
+        * in this area...
+       public static char[] getInputStreamAsCharArray(FileInputStream stream, int length, String encoding)
+               throws IOException {
+               
+               FileChannel channel = stream.getChannel();
+               int size = (int)channel.size();
+               if (length >= 0 && length < size) size = length;
+               Charset charset = encoding==null?systemCharset:Charset.forName(encoding);
+               if (charset != null) {
+                       MappedByteBuffer bbuffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
+                   CharsetDecoder decoder = charset.newDecoder();
+                   CharBuffer buffer = decoder.decode(bbuffer);
+                   char[] contents = new char[buffer.limit()];
+                   buffer.get(contents);
+                   return contents;
+               }
+               throw new UnsupportedCharsetException(SYSTEM_FILE_ENCODING);
+       }
+       */
+       /**
+        * Returns the given input stream's contents as a character array.
+        * If a length is specified (ie. if length != -1), only length chars
+        * are returned. Otherwise all chars in the stream are returned.
+        * Note this doesn't close the stream.
+        * @throws IOException if a problem occured reading the stream.
+        */
+       public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding)
+               throws IOException {
+               InputStreamReader reader = null;
+               reader = encoding == null
+                                       ? new InputStreamReader(stream)
+                                       : new InputStreamReader(stream, encoding);
+               char[] contents;
+               if (length == -1) {
+                       contents = CharOperation.NO_CHAR;
+                       int contentsLength = 0;
+                       int amountRead = -1;
+                       do {
+                               int amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE);  // read at least 8K
+
+                               // resize contents if needed
+                               if (contentsLength + amountRequested > contents.length) {
+                                       System.arraycopy(
+                                               contents,
+                                               0,
+                                               contents = new char[contentsLength + amountRequested],
+                                               0,
+                                               contentsLength);
+                               }
+
+                               // read as many chars as possible
+                               amountRead = reader.read(contents, contentsLength, amountRequested);
+
+                               if (amountRead > 0) {
+                                       // remember length of contents
+                                       contentsLength += amountRead;
+                               }
+                       } while (amountRead != -1);
+
+                       // Do not keep first character for UTF-8 BOM encoding
+                       int start = 0;
+                       if (contentsLength > 0 && "UTF-8".equals(encoding)) { //$NON-NLS-1$
+                               if (contents[0] == 0xFEFF) { // if BOM char then skip
+                                       contentsLength--;
+                                       start = 1;
+                               }
+                       }
+                       // resize contents if necessary
+                       if (contentsLength < contents.length) {
+                               System.arraycopy(
+                                       contents,
+                                       start,
+                                       contents = new char[contentsLength],
+                                       0,
+                                       contentsLength);
+                       }
+               } else {
+                       contents = new char[length];
+                       int len = 0;
+                       int readSize = 0;
+                       while ((readSize != -1) && (len != length)) {
+                               // See PR 1FMS89U
+                               // We record first the read size. In this case len is the actual read size.
+                               len += readSize;
+                               readSize = reader.read(contents, len, length - len);
+                       }
+                       // Do not keep first character for UTF-8 BOM encoding
+                       int start = 0;
+                       if (length > 0 && "UTF-8".equals(encoding)) { //$NON-NLS-1$
+                               if (contents[0] == 0xFEFF) { // if BOM char then skip
+                                       len--;
+                                       start = 1;
+                               }
+                       }
+                       // See PR 1FMS89U
+                       // Now we need to resize in case the default encoding used more than one byte for each
+                       // character
+                       if (len != length)
+                               System.arraycopy(contents, start, (contents = new char[len]), 0, len);
+               }
+
+               return contents;
+       }
+       
+       /**
+        * Returns the contents of the given zip entry as a byte array.
+        * @throws IOException if a problem occured reading the zip entry.
+        */
+       public static byte[] getZipEntryByteContent(ZipEntry ze, ZipFile zip)
+               throws IOException {
+
+               InputStream stream = null;
+               try {
+                       stream = new BufferedInputStream(zip.getInputStream(ze));
+                       return getInputStreamAsByteArray(stream, (int) ze.getSize());
+               } finally {
+                       if (stream != null) {
+                               try {
+                                       stream.close();
+                               } catch (IOException e) {
+                                       // ignore
+                               }
+                       }
+               }
+       }
+       /**
+        * Returns true iff str.toLowerCase().endsWith(".jar") || str.toLowerCase().endsWith(".zip")
+        * implementation is not creating extra strings.
+        */
+       public final static boolean isArchiveFileName(String name) {
+               int nameLength = name == null ? 0 : name.length();
+               int suffixLength = SUFFIX_JAR.length;
+               if (nameLength < suffixLength) return false;
+
+               // try to match as JAR file
+               for (int i = 0; i < suffixLength; i++) {
+                       char c = name.charAt(nameLength - i - 1);
+                       int suffixIndex = suffixLength - i - 1;
+                       if (c != SUFFIX_jar[suffixIndex] && c != SUFFIX_JAR[suffixIndex]) {
+
+                               // try to match as ZIP file
+                               suffixLength = SUFFIX_ZIP.length;
+                               if (nameLength < suffixLength) return false;
+                               for (int j = 0; j < suffixLength; j++) {
+                                       c = name.charAt(nameLength - j - 1);
+                                       suffixIndex = suffixLength - j - 1;
+                                       if (c != SUFFIX_zip[suffixIndex] && c != SUFFIX_ZIP[suffixIndex]) return false;
+                               }
+                               return true;
+                       }
+               }
+               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;
+               if (nameLength < suffixLength) return false;
+
+               for (int i = 0; i < suffixLength; i++) {
+                       char c = name.charAt(nameLength - i - 1);
+                       int suffixIndex = suffixLength - i - 1;
+                       if (c != SUFFIX_class[suffixIndex] && c != SUFFIX_CLASS[suffixIndex]) return false;
+               }
+               return true;            
+       }       
+       /**
+        * Returns true iff str.toLowerCase().endsWith(".class")
+        * implementation is not creating extra strings.
+        */
+       public final static boolean isClassFileName(char[] name) {
+               int nameLength = name == null ? 0 : name.length;
+               int suffixLength = SUFFIX_CLASS.length;
+               if (nameLength < suffixLength) return false;
+
+               for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+                       char c = name[offset + i];
+                       if (c != SUFFIX_class[i] && c != SUFFIX_CLASS[i]) return false;
+               }
+               return true;            
+       }       
+       /**
+        * Returns true iff str.toLowerCase().endsWith(".java")
+        * implementation is not creating extra strings.
+        */
+       public final static boolean isJavaFileName(String name) {
+               int nameLength = name == null ? 0 : name.length();
+               int suffixLength = SUFFIX_JAVA.length;
+               if (nameLength < suffixLength) return false;
+
+               for (int i = 0; i < suffixLength; i++) {
+                       char c = name.charAt(nameLength - i - 1);
+                       int suffixIndex = suffixLength - i - 1;
+                       if (c != SUFFIX_java[suffixIndex] && c != SUFFIX_JAVA[suffixIndex]) return false;
+               }
+               return true;            
+       }
+       /**
+        * Returns true iff str.toLowerCase().endsWith(".java")
+        * implementation is not creating extra strings.
+        */
+       public final static boolean isJavaFileName(char[] name) {
+               int nameLength = name == null ? 0 : name.length;
+               int suffixLength = SUFFIX_JAVA.length;
+               if (nameLength < suffixLength) return false;
+
+               for (int i = 0, offset = nameLength - suffixLength; i < suffixLength; i++) {
+                       char c = name[offset + i];
+                       if (c != SUFFIX_java[i] && c != SUFFIX_JAVA[i]) return false;
+               }
+               return true;            
+       }
+       /**
+        * Converts an array of Objects into String.
+        */
+       public static String toString(Object[] objects) {
+               return toString(objects, 
+                       new Displayable(){ 
+                               public String displayString(Object o) { 
+                                       if (o == null) return "null"; //$NON-NLS-1$
+                                       return o.toString(); 
+                               }
+                       });
+       }
+
+       /**
+        * Converts an array of Objects into String.
+        */
+       public static String toString(Object[] objects, Displayable renderer) {
+               if (objects == null) return ""; //$NON-NLS-1$
+               StringBuffer buffer = new StringBuffer(10);
+               for (int i = 0; i < objects.length; i++){
+                       if (i > 0) buffer.append(", "); //$NON-NLS-1$
+                       buffer.append(renderer.displayString(objects[i]));
+               }
+               return buffer.toString();
+       }
+
+       /**
+        * Converts a boolean value into Boolean.
+        * @param bool The boolean to convert
+        * @return The corresponding Boolean object (TRUE or FALSE).
+        */
+       public static Boolean toBoolean(boolean bool) {
+               if (bool) {
+                       return Boolean.TRUE;
+               } else {
+                       return Boolean.FALSE;
+               }
+       }
+}
diff --git a/src/java/org/eclipse/jdt/internal/compiler/util/messages.properties b/src/java/org/eclipse/jdt/internal/compiler/util/messages.properties
new file mode 100644 (file)
index 0000000..8a1f05c
--- /dev/null
@@ -0,0 +1,69 @@
+###############################################################################
+# 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
+###############################################################################
+### Eclipse Java Core Compiler messages.
+
+### compilation
+compilation.unresolvedProblem =  Unresolved compilation problem: \n
+compilation.unresolvedProblems = Unresolved compilation problems: \n
+compilation.request    = [parsing    {2} - #{0}/{1}]
+compilation.loadBinary = [reading    {0}.class]
+compilation.process    = [analyzing  {2} - #{0}/{1}]
+compilation.write      = [writing    {1} - #{0}]
+compilation.done       = [completed  {2} - #{0}/{1}]
+compilation.units      = [{0} units compiled]
+compilation.unit       = [{0} unit compiled]
+compilation.internalError = Internal compiler error
+
+### output
+output.isFile =  The outDir is a file : {0}
+output.isFileNotDirectory = The outDir is a file not a directory.
+output.dirName =  The output dir name is : {0}
+output.notValidAll =  The outDir is not a valid directory name. All the directories cannot be created.
+output.fileName =  file name : {0}
+output.notValid = The outDir is not a valid directory name. The directory cannot be created.
+
+### problem
+problem.noSourceInformation = \n!! no source information available !!
+problem.atLine = (at line {0})
+
+### abort
+abort.invalidAttribute = SANITY CHECK: Invalid attribute for local variable {0}
+abort.missingCode = Missing code implementation in the compiler
+abort.againstSourceModel = Cannot compile against source model {0} issued from {1}
+
+### accept
+accept.cannot = Cannot accept the compilation unit: 
+
+### parser
+parser.incorrectPath = The path for the javadcl.java file is incorrect
+parser.moveFiles = MOVE FILES IN THE Runtime DIRECTORY OF Parser.class
+parser.syntaxRecovery = SYNTAX RECOVERY
+parser.regularParse = REGULAR PARSE
+parser.missingFile = missing file {0}
+parser.corruptedFile = corrupted file {0}
+parser.endOfFile = end of file
+parser.endOfConstructor = end of constructor
+parser.endOfMethod = end of method
+parser.endOfInitializer = end of initializer
+
+### binding
+binding.subclass = anonymous subclass of {0}
+binding.implementation = anonymous implementation of {0}
+
+### ast
+ast.missingCode = Missing code gen implementation
+
+### constant
+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}