--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+/**
+ * An adapter class for interating through the parse tree.
+ */
+
+public class AbstractSyntaxTreeVisitorAdapter implements IAbstractSyntaxTreeVisitor {
+
+ public void acceptProblem(IProblem problem) {}
+ public void endVisit(
+ AllocationExpression allocationExpression,
+ BlockScope scope) {
+ }
+ public void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+ }
+ public void endVisit(
+ AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
+ BlockScope scope) {
+ }
+ public void endVisit(Argument argument, BlockScope scope) {
+ }
+ public void endVisit(
+ ArrayAllocationExpression arrayAllocationExpression,
+ BlockScope scope) {
+ }
+ public void endVisit(ArrayInitializer arrayInitializer, BlockScope scope) {
+ }
+ public void endVisit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ ClassScope scope) {
+ }
+ public void endVisit(ArrayReference arrayReference, BlockScope scope) {
+ }
+ public void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+ }
+ public void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+ }
+ public void endVisit(Assignment assignment, BlockScope scope) {
+ }
+ public void endVisit(AssertStatement assertStatement, BlockScope scope) {
+ }
+ public void endVisit(BinaryExpression binaryExpression, BlockScope scope) {
+ }
+ public void endVisit(Block block, BlockScope scope) {
+ }
+ public void endVisit(Break breakStatement, BlockScope scope) {
+ }
+ public void endVisit(Case caseStatement, BlockScope scope) {
+ }
+ public void endVisit(CastExpression castExpression, BlockScope scope) {
+ }
+ public void endVisit(CharLiteral charLiteral, BlockScope scope) {
+ }
+ public void endVisit(ClassLiteralAccess classLiteral, BlockScope scope) {
+ }
+ public void endVisit(Clinit clinit, ClassScope scope) {
+ }
+ public void endVisit(
+ CompilationUnitDeclaration compilationUnitDeclaration,
+ CompilationUnitScope scope) {
+ }
+ public void endVisit(CompoundAssignment compoundAssignment, BlockScope scope) {
+ }
+ public void endVisit(
+ ConditionalExpression conditionalExpression,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+ }
+ public void endVisit(Continue continueStatement, BlockScope scope) {
+ }
+ public void endVisit(DefaultCase defaultCaseStatement, BlockScope scope) {
+ }
+ public void endVisit(DoStatement doStatement, BlockScope scope) {
+ }
+ public void endVisit(DoubleLiteral doubleLiteral, BlockScope scope) {
+ }
+ public void endVisit(EqualExpression equalExpression, BlockScope scope) {
+ }
+ public void endVisit(
+ ExplicitConstructorCall explicitConstructor,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ ExtendedStringLiteral extendedStringLiteral,
+ BlockScope scope) {
+ }
+ public void endVisit(FalseLiteral falseLiteral, BlockScope scope) {
+ }
+ public void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ }
+ public void endVisit(FieldReference fieldReference, BlockScope scope) {
+ }
+ public void endVisit(FloatLiteral floatLiteral, BlockScope scope) {
+ }
+ public void endVisit(EmptyStatement emptyStatement, BlockScope scope) {
+ }
+ public void endVisit(ForStatement forStatement, BlockScope scope) {
+ }
+ public void endVisit(IfStatement ifStatement, BlockScope scope) {
+ }
+ public void endVisit(ImportReference importRef, CompilationUnitScope scope) {
+ }
+ public void endVisit(Initializer initializer, MethodScope scope) {
+ }
+ public void endVisit(
+ InstanceOfExpression instanceOfExpression,
+ BlockScope scope) {
+ }
+ public void endVisit(IntLiteral intLiteral, BlockScope scope) {
+ }
+ public void endVisit(LabeledStatement labeledStatement, BlockScope scope) {
+ }
+ public void endVisit(LocalDeclaration localDeclaration, BlockScope scope) {
+ }
+ public void endVisit(LongLiteral longLiteral, BlockScope scope) {
+ }
+ public void endVisit(
+ MemberTypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ }
+ public void endVisit(MessageSend messageSend, BlockScope scope) {
+ }
+ public void endVisit(MethodDeclaration methodDeclaration, ClassScope scope) {
+ }
+ public void endVisit(NullLiteral nullLiteral, BlockScope scope) {
+ }
+ public void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+ }
+ public void endVisit(PostfixExpression postfixExpression, BlockScope scope) {
+ }
+ public void endVisit(PrefixExpression prefixExpression, BlockScope scope) {
+ }
+ public void endVisit(
+ QualifiedAllocationExpression qualifiedAllocationExpression,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ QualifiedNameReference qualifiedNameReference,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ QualifiedSuperReference qualifiedSuperReference,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ QualifiedThisReference qualifiedThisReference,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ QualifiedTypeReference qualifiedTypeReference,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ QualifiedTypeReference qualifiedTypeReference,
+ ClassScope scope) {
+ }
+ public void endVisit(ReturnStatement returnStatement, BlockScope scope) {
+ }
+ public void endVisit(
+ SingleNameReference singleNameReference,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ SingleTypeReference singleTypeReference,
+ BlockScope scope) {
+ }
+ public void endVisit(
+ SingleTypeReference singleTypeReference,
+ ClassScope scope) {
+ }
+ public void endVisit(StringLiteral stringLiteral, BlockScope scope) {
+ }
+ public void endVisit(SuperReference superReference, BlockScope scope) {
+ }
+ public void endVisit(SwitchStatement switchStatement, BlockScope scope) {
+ }
+ public void endVisit(
+ SynchronizedStatement synchronizedStatement,
+ BlockScope scope) {
+ }
+ public void endVisit(ThisReference thisReference, BlockScope scope) {
+ }
+ public void endVisit(ThrowStatement throwStatement, BlockScope scope) {
+ }
+ public void endVisit(TrueLiteral trueLiteral, BlockScope scope) {
+ }
+ public void endVisit(TryStatement tryStatement, BlockScope scope) {
+ }
+ public void endVisit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ }
+ public void endVisit(UnaryExpression unaryExpression, BlockScope scope) {
+ }
+ public void endVisit(WhileStatement whileStatement, BlockScope scope) {
+ }
+ public boolean visit(
+ AllocationExpression allocationExpression,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(Argument argument, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ ArrayAllocationExpression arrayAllocationExpression,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ArrayInitializer arrayInitializer, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference,
+ ClassScope scope) {
+ return true;
+ }
+ public boolean visit(ArrayReference arrayReference, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope) {
+ return true;
+ }
+ public boolean visit(Assignment assignment, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(AssertStatement assertStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(BinaryExpression binaryExpression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(Block block, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(Break breakStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(Case caseStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(CastExpression castExpression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(CharLiteral charLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ClassLiteralAccess classLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(Clinit clinit, ClassScope scope) {
+ return true;
+ }
+ public boolean visit(
+ CompilationUnitDeclaration compilationUnitDeclaration,
+ CompilationUnitScope scope) {
+ return true;
+ }
+ public boolean visit(CompoundAssignment compoundAssignment, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ ConditionalExpression conditionalExpression,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ ConstructorDeclaration constructorDeclaration,
+ ClassScope scope) {
+ return true;
+ }
+ public boolean visit(Continue continueStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(DefaultCase defaultCaseStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(DoStatement doStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(DoubleLiteral doubleLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(EqualExpression equalExpression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(EmptyStatement emptyStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ ExplicitConstructorCall explicitConstructor,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ ExtendedStringLiteral extendedStringLiteral,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(FalseLiteral falseLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
+ return true;
+ }
+ public boolean visit(FieldReference fieldReference, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(FloatLiteral floatLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ForStatement forStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(IfStatement ifStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ImportReference importRef, CompilationUnitScope scope) {
+ return true;
+ }
+ public boolean visit(Initializer initializer, MethodScope scope) {
+ return true;
+ }
+ public boolean visit(
+ InstanceOfExpression instanceOfExpression,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(IntLiteral intLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(LocalDeclaration localDeclaration, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(LongLiteral longLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ MemberTypeDeclaration memberTypeDeclaration,
+ ClassScope scope) {
+ return true;
+ }
+ public boolean visit(MessageSend messageSend, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
+ return true;
+ }
+ public boolean visit(NullLiteral nullLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(PostfixExpression postfixExpression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(PrefixExpression prefixExpression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ QualifiedAllocationExpression qualifiedAllocationExpression,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ QualifiedNameReference qualifiedNameReference,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ QualifiedSuperReference qualifiedSuperReference,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ QualifiedThisReference qualifiedThisReference,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ QualifiedTypeReference qualifiedTypeReference,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ QualifiedTypeReference qualifiedTypeReference,
+ ClassScope scope) {
+ return true;
+ }
+ public boolean visit(ReturnStatement returnStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ SingleNameReference singleNameReference,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ SingleTypeReference singleTypeReference,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ SingleTypeReference singleTypeReference,
+ ClassScope scope) {
+ return true;
+ }
+ public boolean visit(StringLiteral stringLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(SuperReference superReference, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(SwitchStatement switchStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ SynchronizedStatement synchronizedStatement,
+ BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ThisReference thisReference, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(ThrowStatement throwStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(TrueLiteral trueLiteral, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(TryStatement tryStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ return true;
+ }
+ public boolean visit(UnaryExpression unaryExpression, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(WhileStatement whileStatement, BlockScope scope) {
+ return true;
+ }
+ public boolean visit(
+ LocalTypeDeclaration localTypeDeclaration,
+ BlockScope scope) {
+ return true;
+ }
+ public void endVisit(
+ LocalTypeDeclaration localTypeDeclaration,
+ BlockScope scope) {
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import java.io.*;
+import java.util.*;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.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 = 1000;
+ public static final int INITIAL_HEADER_SIZE = 1000;
+ public static final int INCREMENT_SIZE = 1000;
+ public static final int INNER_CLASSES_SIZE = 5;
+ protected HashtableOfType nameUsage;
+ public CodeStream codeStream;
+ protected int problemLine; // used to create line number attributes for problem methods
+
+ /**
+ * INTERNAL USE-ONLY
+ * This methods creates a new instance of the receiver.
+ */
+ public ClassFile() {
+ }
+
+ /**
+ * 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;
+ header = new byte[INITIAL_HEADER_SIZE];
+ // generate the magic numbers inside the header
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+ header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+ switch(((SourceTypeBinding) referenceBinding).scope.environment().options.targetJDK) {
+ case CompilerOptions.JDK1_4 :
+ // Compatible with JDK 1.4
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 48;
+ break;
+ case CompilerOptions.JDK1_3 :
+ // Compatible with JDK 1.3
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 47;
+ break;
+ case CompilerOptions.JDK1_2 :
+ // Compatible with JDK 1.2
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 46;
+ break;
+ case CompilerOptions.JDK1_1 :
+ // Compatible with JDK 1.1
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 3;
+ header[headerOffset++] = 0;
+ header[headerOffset++] = 45;
+ }
+ 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)
+ accessFlags |= AccSuper;
+
+ this.enclosingClassFile = enclosingClassFile;
+ // innerclasses get their names computed at code gen time
+ if (aType.isLocalType()) {
+ ((LocalTypeBinding) aType).constantPoolName(
+ computeConstantPoolName((LocalTypeBinding) aType));
+ ReferenceBinding[] memberTypes = aType.memberTypes();
+ for (int i = 0, max = memberTypes.length; i < max; i++) {
+ ((LocalTypeBinding) memberTypes[i]).constantPoolName(
+ computeConstantPoolName((LocalTypeBinding) memberTypes[i]));
+ }
+ }
+ contents = new byte[INITIAL_CONTENTS_SIZE];
+ // now we continue to generate the bytes inside the contents array
+ contents[contentsOffset++] = (byte) (accessFlags >> 8);
+ contents[contentsOffset++] = (byte) accessFlags;
+ int classNameIndex = constantPool.literalIndex(aType);
+ contents[contentsOffset++] = (byte) (classNameIndex >> 8);
+ contents[contentsOffset++] = (byte) classNameIndex;
+ 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;
+ if (superInterfacesBinding != null) {
+ for (int i = 0; i < interfacesCount; i++) {
+ int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+ contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
+ contents[contentsOffset++] = (byte) interfaceIndex;
+ }
+ }
+ produceDebugAttributes =
+ ((SourceTypeBinding) 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;
+ int contentsLength;
+
+ // 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 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ 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 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ 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;
+ if (contentsOffset + (exSize = (8 * numberOfInnerClasses + 8))
+ >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents =
+ new byte[contentsLength
+ + (exSize >= INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]),
+ 0,
+ contentsLength);
+ }
+ // 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
+ contentsLength = contents.length;
+ if (attributeOffset + 2 >= contentsLength) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ 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
+ int contentsLength;
+ if (contentsOffset + 30 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ // 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
+ && fieldBinding.constant.typeID() != T_null) {
+ // 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
+ 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 referenceBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+ */
+ public void addInnerClasses(ReferenceBinding referenceBinding) {
+ // check first if that reference binding is there
+ for (int i = 0; i < numberOfInnerClasses; i++) {
+ if (innerClassesBindings[i] == referenceBinding)
+ return;
+ }
+ int length = innerClassesBindings.length;
+ if (numberOfInnerClasses == length) {
+ System.arraycopy(
+ innerClassesBindings,
+ 0,
+ (innerClassesBindings = new ReferenceBinding[length * 2]),
+ 0,
+ length);
+ }
+ innerClassesBindings[numberOfInnerClasses++] = referenceBinding;
+ }
+
+ /**
+ * INTERNAL USE-ONLY
+ * Generate the byte for a problem clinit method info that correspond to a boggus method.
+ *
+ * @param problem 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, "")
+ int[] exceptionHandler =
+ codeStream.generateCodeAttributeForProblemMethod(
+ referenceBinding
+ .scope
+ .environment()
+ .options
+ .runtimeExceptionNameForCompileError,
+ problemString);
+ attributeNumber++; // code attribute
+ completeCodeAttributeForClinit(
+ codeAttributeOffset,
+ exceptionHandler,
+ 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 problem 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
+ methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
+
+ generateMethodInfoHeader(methodBinding);
+ int methodAttributeOffset = contentsOffset;
+ int attributeNumber = generateMethodInfoAttribute(methodBinding);
+
+ // Code attribute
+ attributeNumber++;
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ final ProblemReporter problemReporter = method.scope.problemReporter();
+ 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, "")
+ int[] exceptionHandler =
+ codeStream.generateCodeAttributeForProblemMethod(
+ problemReporter.options.runtimeExceptionNameForCompileError,
+ problemString);
+ completeCodeAttributeForProblemMethod(
+ method,
+ methodBinding,
+ codeAttributeOffset,
+ exceptionHandler,
+ ((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 problem 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 problem org.eclipse.jdt.internal.compiler.problem.Problem[]
+ */
+ public void addProblemMethod(
+ AbstractMethodDeclaration method,
+ MethodBinding methodBinding,
+ IProblem[] problems) {
+ if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
+ method.abort(AbstractMethodDeclaration.AbortType);
+ }
+ // always clear the strictfp/native/abstract bit for a problem method
+ methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
+
+ generateMethodInfoHeader(methodBinding);
+ int methodAttributeOffset = contentsOffset;
+ int attributeNumber = generateMethodInfoAttribute(methodBinding);
+
+ // Code attribute
+ attributeNumber++;
+
+ int codeAttributeOffset = contentsOffset;
+ generateCodeAttributeHeader();
+ final ProblemReporter problemReporter = method.scope.problemReporter();
+ 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, "")
+ int[] exceptionHandler =
+ codeStream.generateCodeAttributeForProblemMethod(
+ problemReporter.options.runtimeExceptionNameForCompileError,
+ problemString);
+ completeCodeAttributeForProblemMethod(
+ method,
+ methodBinding,
+ codeAttributeOffset,
+ exceptionHandler,
+ ((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 problem 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 private field
+ addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
+ break;
+ case SyntheticAccessMethodBinding.FieldWriteAccess :
+ // generate a method info to emulate an writing access to
+ // a private field
+ addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
+ break;
+ case SyntheticAccessMethodBinding.MethodAccess :
+ // generate a method info to emulate an access to a private method
+ addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
+ break;
+ case SyntheticAccessMethodBinding.ConstructorAccess :
+ // generate a method info to emulate an access to a private method
+ 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
+ methodBinding.modifiers &= ~(AccStrictfp | AccNative | AccAbstract);
+
+ generateMethodInfoHeader(methodBinding);
+ 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();
+
+ final ProblemReporter problemReporter = methodDeclaration.scope.problemReporter();
+ codeStream.init(this);
+ codeStream.preserveUnusedLocals = true;
+ codeStream.initializeMaxLocals(methodBinding);
+
+ // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+ int[] exceptionHandler =
+ codeStream.generateCodeAttributeForProblemMethod(
+ problemReporter.options.runtimeExceptionNameForCompileError,
+ problemString);
+
+ completeCodeAttributeForMissingAbstractProblemMethod(
+ methodBinding,
+ codeAttributeOffset,
+ exceptionHandler,
+ compilationResult.lineSeparatorPositions);
+
+ completeMethodInfo(methodAttributeOffset, attributeNumber);
+ }
+
+ /**
+ *
+ */
+ public void completeCodeAttributeForMissingAbstractProblemMethod(
+ MethodBinding binding,
+ int codeAttributeOffset,
+ int[] exceptionHandler,
+ int[] startLineIndexes) {
+ // reinitialize the localContents with the byte modified by the code stream
+ byte[] localContents = 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;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ int code_length = codeStream.position;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+ // write the exception table
+ int contentsLength;
+ if (localContentsOffset + 50 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ int start = exceptionHandler[0];
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler[1];
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler[2];
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ int nameIndex = constantPool.literalIndexForJavaLangException();
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[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 lineNumberNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 6;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ if (problemLine == 0) {
+ problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+ }
+ // first entry at pc = 0
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (problemLine >> 8);
+ localContents[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
+ >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[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 codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+ public void completeCodeAttribute(int codeAttributeOffset) {
+ // reinitialize the localContents with the byte modified by the code stream
+ byte[] localContents = 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 contentsLength;
+ int code_length = codeStream.position;
+ if (code_length > 65535) {
+ codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+ codeStream.methodDeclaration);
+ }
+ if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ int max_stack = codeStream.stackMax;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+ // write the exception table
+ int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+ ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+ int exSize;
+ if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2))
+ >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents =
+ contents =
+ new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]),
+ 0,
+ contentsLength);
+ }
+ // there is no exception table, so we need to offset by 2 the current offset and move
+ // on the attribute generation
+ localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+ localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+ for (int i = 0; i < exceptionHandlersNumber; i++) {
+ ExceptionLabel exceptionHandler = exceptionHandlers[i];
+ int start = exceptionHandler.start;
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler.end;
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler.position;
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ if (exceptionHandler.exceptionType == null) {
+ // any exception handler
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ } else {
+ int nameIndex;
+ if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+ /* represents ClassNotFoundException, see class literal access*/
+ nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+ } else {
+ nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+ }
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ int pc = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (pc >> 8);
+ localContents[localContentsOffset++] = (byte) pc;
+ int lineNumber = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumber;
+ numberOfEntries++;
+ }
+ // now we change the size of the line number attribute
+ int lineNumberAttr_length = numberOfEntries * 4 + 2;
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+ localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+ localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContentsOffset += 2; // the startPC for this is always 0
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex =
+ constantPool.literalIndex(
+ codeStream.methodDeclaration.binding.declaringClass.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ localContentsOffset += 2; // the resolved position for this is always 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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = (byte) (startPC >> 8);
+ localContents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ localContents[localContentsOffset++] = (byte) (length >> 8);
+ localContents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ int value = numberOfEntries * 10 + 2;
+ localVariableTableOffset += 2;
+ localContents[localVariableTableOffset++] = (byte) (value >> 24);
+ localContents[localVariableTableOffset++] = (byte) (value >> 16);
+ localContents[localVariableTableOffset++] = (byte) (value >> 8);
+ localContents[localVariableTableOffset++] = (byte) value;
+ localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[localVariableTableOffset] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+ // update the number of attributes
+ // ensure first that there is enough space available inside the localContents array
+ if (codeAttributeAttributeOffset + 2
+ >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[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 codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ */
+ public void completeCodeAttributeForClinit(int codeAttributeOffset) {
+ // reinitialize the contents with the byte modified by the code stream
+ byte[] localContents = 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 contentsLength;
+ int code_length = codeStream.position;
+ if (code_length > 65535) {
+ codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+ codeStream.methodDeclaration.scope.referenceType());
+ }
+ if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ int max_stack = codeStream.stackMax;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+ // write the exception table
+ int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+ ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+ int exSize;
+ if (localContentsOffset + (exSize = (exceptionHandlersNumber * 8 + 2))
+ >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents =
+ contents =
+ new byte[contentsLength + (exSize > INCREMENT_SIZE ? exSize : INCREMENT_SIZE)]),
+ 0,
+ contentsLength);
+ }
+ // there is no exception table, so we need to offset by 2 the current offset and move
+ // on the attribute generation
+ localContents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+ localContents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+ for (int i = 0; i < exceptionHandlersNumber; i++) {
+ ExceptionLabel exceptionHandler = exceptionHandlers[i];
+ int start = exceptionHandler.start;
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler.end;
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler.position;
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ if (exceptionHandler.exceptionType == null) {
+ // any exception handler
+ localContentsOffset += 2;
+ } else {
+ int nameIndex;
+ if (exceptionHandler.exceptionType == TypeBinding.NullBinding) {
+ /* represents denote ClassNotFoundException, see class literal access*/
+ nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+ } else {
+ nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+ }
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ int pc = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (pc >> 8);
+ localContents[localContentsOffset++] = (byte) pc;
+ int lineNumber = pcToSourceMapTable[i++];
+ localContents[localContentsOffset++] = (byte) (lineNumber >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumber;
+ numberOfEntries++;
+ }
+ // now we change the size of the line number attribute
+ int lineNumberAttr_length = numberOfEntries * 4 + 2;
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+ localContents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+ localContents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+ localContents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = (byte) (startPC >> 8);
+ localContents[localContentsOffset++] = (byte) startPC;
+ int length = endPC - startPC;
+ localContents[localContentsOffset++] = (byte) (length >> 8);
+ localContents[localContentsOffset++] = (byte) length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ int value = numberOfEntries * 10 + 2;
+ localVariableTableOffset += 2;
+ localContents[localVariableTableOffset++] = (byte) (value >> 24);
+ localContents[localVariableTableOffset++] = (byte) (value >> 16);
+ localContents[localVariableTableOffset++] = (byte) (value >> 8);
+ localContents[localVariableTableOffset++] = (byte) value;
+ localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[localVariableTableOffset] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+ }
+ // update the number of attributes
+ // ensure first that there is enough space available inside the contents array
+ if (codeAttributeAttributeOffset + 2
+ >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[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 codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ * @param exceptionHandler int[]
+ * @param startIndexes int[]
+ */
+ public void completeCodeAttributeForClinit(
+ int codeAttributeOffset,
+ int[] exceptionHandler,
+ int[] startLineIndexes) {
+ // reinitialize the contents with the byte modified by the code stream
+ byte[] localContents = 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 contentsLength;
+ int code_length = codeStream.position;
+ if (code_length > 65535) {
+ codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+ codeStream.methodDeclaration.scope.referenceType());
+ }
+ if (localContentsOffset + 20 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ int max_stack = codeStream.stackMax;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+
+ // write the exception table
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ int start = exceptionHandler[0];
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler[1];
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler[2];
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ int nameIndex = constantPool.literalIndexForJavaLangException();
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[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
+
+ // 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);
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 6;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ // first entry at pc = 0
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (problemLine >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) localVariableNameIndex;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 2;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ attributeNumber++;
+ }
+ // update the number of attributes
+ // ensure first that there is enough space available inside the contents array
+ if (codeAttributeAttributeOffset + 2
+ >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[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 codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param codeAttributeOffset <CODE>int</CODE>
+ * @param exceptionHandler int[]
+ */
+ public void completeCodeAttributeForProblemMethod(
+ AbstractMethodDeclaration method,
+ MethodBinding binding,
+ int codeAttributeOffset,
+ int[] exceptionHandler,
+ int[] startLineIndexes) {
+ // reinitialize the localContents with the byte modified by the code stream
+ byte[] localContents = 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;
+ localContents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+ localContents[codeAttributeOffset + 7] = (byte) max_stack;
+ int max_locals = codeStream.maxLocals;
+ localContents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+ localContents[codeAttributeOffset + 9] = (byte) max_locals;
+ int code_length = codeStream.position;
+ localContents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+ localContents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+ localContents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+ localContents[codeAttributeOffset + 13] = (byte) code_length;
+ // write the exception table
+ int contentsLength;
+ if (localContentsOffset + 50 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ int start = exceptionHandler[0];
+ localContents[localContentsOffset++] = (byte) (start >> 8);
+ localContents[localContentsOffset++] = (byte) start;
+ int end = exceptionHandler[1];
+ localContents[localContentsOffset++] = (byte) (end >> 8);
+ localContents[localContentsOffset++] = (byte) end;
+ int handlerPC = exceptionHandler[2];
+ localContents[localContentsOffset++] = (byte) (handlerPC >> 8);
+ localContents[localContentsOffset++] = (byte) handlerPC;
+ int nameIndex = constantPool.literalIndexForJavaLangException();
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[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 lineNumberNameIndex =
+ constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+ localContents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) lineNumberNameIndex;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 6;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 1;
+ if (problemLine == 0) {
+ problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+ }
+ // first entry at pc = 0
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (problemLine >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex =
+ constantPool.literalIndex(
+ codeStream.methodDeclaration.binding.declaringClass.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ // the resolved position for this is always 0
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ }
+ if (binding.isConstructor()) {
+ ReferenceBinding declaringClass = binding.declaringClass;
+ if (declaringClass.isNestedType()) {
+ NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
+ argSize = methodDeclaringClass.syntheticArgumentsOffset;
+ SyntheticArgumentBinding[] syntheticArguments;
+ if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances())
+ != null) {
+ for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+ LocalVariableBinding localVariable = syntheticArguments[i];
+ if (localContentsOffset + 10 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(localVariable.name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = localVariable.resolvedPosition;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[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 >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ // now we can safely add the local entry
+ numberOfEntries++;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = 0;
+ localContents[localContentsOffset++] = (byte) (code_length >> 8);
+ localContents[localContentsOffset++] = (byte) code_length;
+ nameIndex = constantPool.literalIndex(arguments[i].name);
+ localContents[localContentsOffset++] = (byte) (nameIndex >> 8);
+ localContents[localContentsOffset++] = (byte) nameIndex;
+ descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
+ localContents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+ localContents[localContentsOffset++] = (byte) descriptorIndex;
+ int resolvedPosition = argSize;
+ if ((argumentBinding == TypeBinding.LongBinding)
+ || (argumentBinding == TypeBinding.DoubleBinding))
+ argSize += 2;
+ else
+ argSize++;
+ localContents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+ localContents[localContentsOffset++] = (byte) resolvedPosition;
+ }
+ }
+ }
+ int value = numberOfEntries * 10 + 2;
+ localVariableTableOffset += 2;
+ localContents[localVariableTableOffset++] = (byte) (value >> 24);
+ localContents[localVariableTableOffset++] = (byte) (value >> 16);
+ localContents[localVariableTableOffset++] = (byte) (value >> 8);
+ localContents[localVariableTableOffset++] = (byte) value;
+ localContents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+ localContents[localVariableTableOffset] = (byte) numberOfEntries;
+ attributeNumber++;
+ }
+ // update the number of attributes// ensure first that there is enough space available inside the localContents array
+ if (codeAttributeAttributeOffset + 2
+ >= (contentsLength = localContents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (localContents = contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ localContents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+ localContents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+ // update the attribute length
+ int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+ localContents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+ localContents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+ localContents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+ localContents[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 codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @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
+ 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;
+ int contentsLength;
+ if ((localContentsOffset + 40) >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ // there is no exception table, so we need to offset by 2 the current offset and move
+ // on the attribute generation
+ localContentsOffset += 2;
+ // 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 > (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ 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 > (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ // 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 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ 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
+ * Innerclasses get their name computed as they are generated, since some may not
+ * be actually outputed if sitting inside unreachable code.
+ *
+ * @param localType org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding
+ */
+ 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 (enclosingClassFile != null) {
+ return this.outerMostEnclosingClassFile().computeConstantPoolName(localType);
+ }
+ if (nameUsage == null)
+ nameUsage = new HashtableOfType();
+
+ // 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(
+ referenceBinding.constantPoolName(),
+ String.valueOf(index+1).toCharArray(),
+ '$');
+ } else {
+ candidateName = CharOperation.concat(
+ referenceBinding.constantPoolName(),
+ '$',
+ String.valueOf(index+1).toCharArray(),
+ '$',
+ localType.sourceName);
+ }
+ if (nameUsage.get(candidateName) != null) {
+ index ++;
+ } else {
+ nameUsage.put(candidateName, localType);
+ break;
+ }
+ }
+ return candidateName;
+ }
+
+ /**
+ * 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);
+
+ // 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], false, null, null, 0);
+ }
+ }
+ 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.getProblems();
+ 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 (i.e. Code)
+ * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
+ */
+ public void generateCodeAttributeHeader() {
+ int contentsLength;
+ if (contentsOffset + 20 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ 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 contentsLength;
+ 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;
+ if (contentsOffset + (8 + length * 2) >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents =
+ new byte[contentsLength + Math.max(INCREMENT_SIZE, (8 + length * 2))]),
+ 0,
+ contentsLength);
+ }
+ 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++;
+ }
+ // Deprecated attribute
+ // Check that there is enough space to write the deprecated attribute
+ if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ if (methodBinding.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++;
+ }
+ // Synthetic attribute
+ // Check that there is enough space to write the deprecated attribute
+ if (contentsOffset + 6 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ if (methodBinding.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++;
+ }
+ 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) {
+ // check that there is enough space to write all the bytes for the method info corresponding
+ // to the @methodBinding
+ int contentsLength;
+ methodCount++; // add one more method
+ if (contentsOffset + 10 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ int accessFlags = methodBinding.getAccessFlags();
+ 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.
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ */
+ public void generateMethodInfoHeaderForClinit() {
+ // check that there is enough space to write all the bytes for the method info corresponding
+ // to the @methodBinding
+ int contentsLength;
+ methodCount++; // add one more method
+ if (contentsOffset + 10 >= (contentsLength = contents.length)) {
+ System.arraycopy(
+ contents,
+ 0,
+ (contents = new byte[contentsLength + INCREMENT_SIZE]),
+ 0,
+ contentsLength);
+ }
+ 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());
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * INTERNAL USE-ONLY
+ * Search the line number corresponding to a specific position
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+ 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();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
+
+import java.util.*;
+
+public class CompilationResult {
+
+ public IProblem problems[];
+ public int problemCount;
+ public ICompilationUnit compilationUnit;
+ private Map problemsMap;
+ private Map firstErrorsMap;
+ private HashSet duplicateProblems;
+ 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 = 1000;
+ final int P_OUTSIDE_METHOD = 4000;
+ final int P_FIRST_ERROR = 2000;
+ final int P_ERROR = 10000;
+
+ int priority = 1000 - 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 ClassFile[] getClassFiles() {
+ Enumeration enum = compiledTypes.elements();
+ ClassFile[] classFiles = new ClassFile[compiledTypes.size()];
+ int index = 0;
+ while (enum.hasMoreElements()){
+ classFiles[index++] = (ClassFile)enum.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 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;
+}
+
+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 hasWarnings() {
+ if (problems != null)
+ for (int i = 0; i < problemCount; i++) {
+ if (problems[i].isWarning())
+ return true;
+ }
+ return false;
+}
+
+private static void quicksort(IProblem arr[], int left, int right) {
+ int i, last, pos;
+
+ if (left >= right) {
+ /* do nothing if array contains fewer than two */
+ return;
+ /* two elements */
+ }
+
+ swap(arr, left, (left + right) / 2);
+ last = left;
+ pos = arr[left].getSourceStart();
+
+ for (i = left + 1; i <= right; i++) {
+ if (arr[i].getSourceStart() < pos) {
+ swap(arr, ++last, i);
+ }
+ }
+
+ swap(arr, left, last);
+ quicksort(arr, left, last - 1);
+ quicksort(arr, last + 1, right);
+}
+
+private void quickPrioritize(IProblem arr[], int left, int right) {
+ int i, last, prio;
+
+ if (left >= right) {
+ /* do nothing if array contains fewer than two */
+ return;
+ /* two elements */
+ }
+
+ swap(arr, left, (left + right) / 2);
+ last = left;
+ prio = computePriority(arr[left]);
+
+ for (i = left + 1; i <= right; i++) {
+ if (computePriority(arr[i]) > prio) {
+ swap(arr, ++last, i);
+ }
+ }
+
+ swap(arr, left, last);
+ quickPrioritize(arr, left, last - 1);
+ quickPrioritize(arr, last + 1, 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 (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 static void swap(IProblem arr[], int i, int j) {
+ IProblem tmp;
+ tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+}
+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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+import java.io.*;
+import java.util.*;
+
+public class Compiler implements ITypeRequestor, ProblemSeverities {
+ public Parser parser;
+ ICompilerRequestor requestor;
+ public CompilerOptions options;
+ public ProblemReporter problemReporter;
+
+ // management of unit to be processed
+ //public CompilationUnitResult currentCompilationUnitResult;
+ CompilationUnitDeclaration[] unitsToProcess;
+ 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);
+ this.parser =
+ new Parser(
+ problemReporter,
+ this.options.parseLiteralExpressionsAsConstants,
+ this.options.assertMode);
+ }
+
+ /**
+ * 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);
+ this.parser =
+ new Parser(
+ problemReporter,
+ parseLiteralExpressionsAsConstants,
+ this.options.assertMode);
+ }
+
+ /**
+ * Add an additional binary type
+ */
+ public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
+ lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
+ }
+
+ /**
+ * Add an additional compilation unit into the loop
+ * -> build compilation unit declarations, their bindings and record their results.
+ */
+ public void accept(ICompilationUnit sourceUnit) {
+ // Switch the current policy and compilation result for this unit to the requested one.
+ CompilationResult unitResult =
+ new CompilationResult(sourceUnit, totalUnits, totalUnits, this.options.maxProblemsPerUnit);
+ try {
+ // diet parsing for large collection of unit
+ CompilationUnitDeclaration parsedUnit;
+ if (totalUnits < parseThreshold) {
+ parsedUnit = parser.parse(sourceUnit, unitResult);
+ } else {
+ parsedUnit = parser.dietParse(sourceUnit, unitResult);
+ }
+
+ if (options.verbose) {
+ System.out.println(
+ Util.bind(
+ "compilation.request" , //$NON-NLS-1$
+ new String[] {
+ String.valueOf(totalUnits + 1),
+ String.valueOf(totalUnits + 1),
+ new String(sourceUnit.getFileName())}));
+ }
+
+ // 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 {
+ // diet parsing for large collection of units
+ if (totalUnits < parseThreshold) {
+ parsedUnit = parser.parse(sourceUnits[i], unitResult);
+ } else {
+ parsedUnit = parser.dietParse(sourceUnits[i], unitResult);
+ }
+ 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())}));
+ }
+ // 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();
+ if (options.verbose)
+ System.out.println(Util.bind("compilation.done", //$NON-NLS-1$
+ new String[] {
+ String.valueOf(i + 1),
+ String.valueOf(totalUnits),
+ new String(unitsToProcess[i].getFileName())}));
+ }
+ unitsToProcess[i] = null; // release reference to processed unit declaration
+ requestor.acceptResult(unit.compilationResult.tagAsAccepted());
+ }
+ } 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$
+ }
+ }
+ }
+
+ protected void getMethodBodies(CompilationUnitDeclaration unit, int place) {
+ //fill the methods bodies in order for the code to be generated
+
+ if (unit.ignoreMethodBodies) {
+ unit.ignoreFurtherInvestigation = true;
+ return;
+ // if initial diet parse did not work, no need to dig into method bodies.
+ }
+
+ if (place < parseThreshold)
+ return; //work already done ...
+
+ //real parse of the method....
+ parser.scanner.setSource(
+ unit.compilationResult.compilationUnit.getContents());
+ if (unit.types != null) {
+ for (int i = unit.types.length; --i >= 0;)
+ unit.types[i].parseMethod(parser, unit);
+ }
+ }
+
+ /*
+ * Compiler crash recovery in case of unexpected runtime exceptions
+ */
+ protected void handleInternalException(
+ Throwable internalException,
+ CompilationUnitDeclaration unit,
+ CompilationResult result) {
+
+ /* dump a stack trace to the console */
+ internalException.printStackTrace();
+
+ /* find a compilation result */
+ if ((unit != null)) // basing result upon the current unit if available
+ result = unit.compilationResult; // current unit being processed ?
+ if ((result == null) && (unitsToProcess != null) && (totalUnits > 0))
+ result = unitsToProcess[totalUnits - 1].compilationResult;
+ // last unit in beginToCompile ?
+
+ 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();
+
+ result
+ .record(
+ problemReporter
+ .createProblem(
+ result.getFileName(),
+ IProblem.Unclassified,
+ new String[] {
+ Util.bind("compilation.internalError" ) //$NON-NLS-1$
+ + "\n" //$NON-NLS-1$
+ + buffer.toString()},
+ Error, // severity
+ 0, // source start
+ 0, // source end
+ 0, // line number
+ unit,
+ result),
+ unit);
+
+ /* hand back the compilation result */
+ if (!result.hasBeenAccepted) {
+ requestor.acceptResult(result.tagAsAccepted());
+ }
+ }
+ }
+
+ /*
+ * 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;
+ } else {
+ 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 ?
+ 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.problemId != 0) {
+ result
+ .record(
+ problemReporter
+ .createProblem(
+ result.getFileName(),
+ abortException.problemId,
+ abortException.problemArguments,
+ Error, // severity
+ 0, // source start
+ 0, // source end
+ 0, // line number
+ unit,
+ result),
+ 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 {
+ /*
+ if (abortException.problemId != 0){
+ IProblem problem =
+ problemReporter.createProblem(
+ "???".toCharArray(),
+ abortException.problemId,
+ abortException.problemArguments,
+ Error, // severity
+ 0, // source start
+ 0, // source end
+ 0); // line number
+ System.out.println(problem.getMessage());
+ }
+ */
+ abortException.printStackTrace();
+ }
+ }
+
+ /**
+ * Process a compilation unit already parsed and build.
+ */
+ private void process(CompilationUnitDeclaration unit, int i) {
+
+ getMethodBodies(unit, i);
+
+ // 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 compilation unit minimally for code assist engine
+ */
+ public CompilationUnitDeclaration resolve(ICompilationUnit sourceUnit) {
+ CompilationUnitDeclaration unit = null;
+ try {
+ // build and record parsed units
+ parseThreshold = 0; // will request a full parse
+ beginToCompile(new ICompilationUnit[] { sourceUnit });
+ // process all units (some more could be injected in the loop by the lookup environment)
+ unit = unitsToProcess[0];
+ getMethodBodies(unit, 0);
+ if (unit.scope != null) {
+ // fault in fields & methods
+ unit.scope.faultInTypes();
+ // type checking
+ unit.resolve();
+ }
+ 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();
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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).
+ *
+ * @return int
+ */
+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;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+ }
+ };
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+/*
+ * A document element parser extracts structural information
+ * from a piece of source, providing detailed source positions info.
+ *
+ * also see @IDocumentElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+import net.sourceforge.phpdt.internal.compiler.env.*;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+public class DocumentElementParser extends Parser {
+ IDocumentElementRequestor requestor;
+ private int localIntPtr;
+ private int lastFieldEndPosition;
+ private int lastFieldBodyEndPosition;
+ private int typeStartPosition;
+ private long selectorSourcePositions;
+ private int typeDims;
+ private int extendsDim;
+ private int declarationSourceStart;
+
+ /* int[] stack for storing javadoc positions */
+ int[][] intArrayStack;
+ int intArrayPtr;
+
+ CompilerOptions options;
+
+public DocumentElementParser(
+ final IDocumentElementRequestor requestor,
+ IProblemFactory problemFactory,
+ CompilerOptions options) {
+ super(new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ options,
+ problemFactory) {
+ public void record(IProblem problem, CompilationResult unitResult) {
+ requestor.acceptProblem(problem);
+ }
+ },
+ false,
+ options.assertMode);
+ this.requestor = requestor;
+ intArrayStack = new int[30][];
+ this.options = options;
+}
+
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void adjustInterfaceModifiers() {
+ intStack[intPtr - 2] |= AccInterface;
+}
+/*
+ * Will clear the comment stack when looking
+ * for a potential JavaDoc which might contain @deprecated.
+ *
+ * Additionally, before investigating for @deprecated, retrieve the positions
+ * of the JavaDoc comments so as to notify requestor with them.
+ */
+public void checkAnnotation() {
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+ boolean deprecated = false;
+ int lastAnnotationIndex = -1;
+
+ //since jdk1.2 look only in the last java doc comment...
+ found : {
+ if ((lastAnnotationIndex = scanner.commentPtr) >= 0) { //look for @deprecated
+ scanner.commentPtr = -1;
+ // reset the comment stack, since not necessary after having checked
+ int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
+ // javadoc only (non javadoc comment have negative end positions.)
+ int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1;
+ //stop is one over
+ char[] comment = scanner.source;
+
+ for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
+ if ((comment[i] == '@')
+ && (comment[i + 1] == 'd')
+ && (comment[i + 2] == 'e')
+ && (comment[i + 3] == 'p')
+ && (comment[i + 4] == 'r')
+ && (comment[i + 5] == 'e')
+ && (comment[i + 6] == 'c')
+ && (comment[i + 7] == 'a')
+ && (comment[i + 8] == 't')
+ && (comment[i + 9] == 'e')
+ && (comment[i + 10] == 'd')) {
+ // ensure the tag is properly ended: either followed by a space, line end or asterisk.
+ int nextPos = i + 11;
+ deprecated =
+ (comment[nextPos] == ' ')
+ || (comment[nextPos] == '\n')
+ || (comment[nextPos] == '\r')
+ || (comment[nextPos] == '*');
+ break found;
+ }
+ }
+ }
+ }
+ if (deprecated) {
+ checkAndSetModifiers(AccDeprecated);
+ }
+ // modify the modifier source start to point at the first comment
+ if (lastAnnotationIndex >= 0) {
+ declarationSourceStart = scanner.commentStarts[0];
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassBodyDeclaration() {
+ // ClassBodyDeclaration ::= Diet Block
+ //push an Initializer
+ //optimize the push/pop
+
+ super.consumeClassBodyDeclaration();
+ Initializer initializer = (Initializer) astStack[astPtr];
+ requestor.acceptInitializer(
+ initializer.declarationSourceStart,
+ initializer.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ 0,
+ modifiersSourceStart,
+ initializer.block.sourceStart,
+ initializer.block.sourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassDeclaration() {
+ super.consumeClassDeclaration();
+ // we know that we have a TypeDeclaration on the top of the astStack
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ requestor.exitClass(endStatementPosition, // '}' is the end of the body
+ ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeClassHeader() {
+ //ClassHeader ::= $empty
+ super.consumeClassHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ TypeReference[] superInterfaces = typeDecl.superInterfaces;
+ char[][] interfaceNames = null;
+ int[] interfaceNameStarts = null;
+ int[] interfaceNameEnds = null;
+ if (superInterfaces != null) {
+ int superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ interfaceNameStarts = new int[superInterfacesLength];
+ interfaceNameEnds = new int[superInterfacesLength];
+ for (int i = 0; i < superInterfacesLength; i++) {
+ TypeReference superInterface = superInterfaces[i];
+ interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
+ interfaceNameStarts[i] = superInterface.sourceStart;
+ interfaceNameEnds[i] = superInterface.sourceEnd;
+ }
+ }
+ // flush the comments related to the class header
+ scanner.commentPtr = -1;
+ TypeReference superclass = typeDecl.superclass;
+ if (superclass == null) {
+ requestor.enterClass(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ null,
+ -1,
+ -1,
+ interfaceNames,
+ interfaceNameStarts,
+ interfaceNameEnds,
+ scanner.currentPosition - 1);
+ } else {
+ requestor.enterClass(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ CharOperation.concatWith(superclass.getTypeName(), '.'),
+ superclass.sourceStart,
+ superclass.sourceEnd,
+ interfaceNames,
+ interfaceNameStarts,
+ interfaceNameEnds,
+ scanner.currentPosition - 1);
+
+ }
+}
+protected void consumeClassHeaderName() {
+ // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+ TypeDeclaration typeDecl;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+ markCurrentMethodWithLocalType();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'class' and 'interface' push an int position
+ typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+ intPtr--;
+ int declarationSourceStart = intStack[intPtr--];
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.declarationSourceStart > declarationSourceStart) {
+ typeDecl.declarationSourceStart = declarationSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeCompilationUnit() {
+ // CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt
+ requestor.exitCompilationUnit(scanner.source.length - 1);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorDeclaration() {
+ // ConstructorDeclaration ::= ConstructorHeader ConstructorBody
+ super.consumeConstructorDeclaration();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+ requestor.exitConstructor(endStatementPosition, cd.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeConstructorHeader() {
+ // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
+ super.consumeConstructorHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+ Argument[] arguments = cd.arguments;
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ int[] argumentTypeStarts = null;
+ int[] argumentTypeEnds = null;
+ int[] argumentNameStarts = null;
+ int[] argumentNameEnds = null;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ argumentNameStarts = new int[argumentLength];
+ argumentNameEnds = new int[argumentLength];
+ argumentTypeStarts = new int[argumentLength];
+ argumentTypeEnds = new int[argumentLength];
+ for (int i = 0; i < argumentLength; i++) {
+ Argument argument = arguments[i];
+ TypeReference argumentType = argument.type;
+ argumentTypes[i] = returnTypeName(argumentType);
+ argumentNames[i] = argument.name;
+ argumentNameStarts[i] = argument.sourceStart;
+ argumentNameEnds[i] = argument.sourceEnd;
+ argumentTypeStarts[i] = argumentType.sourceStart;
+ argumentTypeEnds[i] = argumentType.sourceEnd;
+ }
+ }
+ TypeReference[] thrownExceptions = cd.thrownExceptions;
+ char[][] exceptionTypes = null;
+ int[] exceptionTypeStarts = null;
+ int[] exceptionTypeEnds = null;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ exceptionTypes = new char[thrownExceptionLength][];
+ exceptionTypeStarts = new int[thrownExceptionLength];
+ exceptionTypeEnds = new int[thrownExceptionLength];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ TypeReference exception = thrownExceptions[i];
+ exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+ exceptionTypeStarts[i] = exception.sourceStart;
+ exceptionTypeEnds[i] = exception.sourceEnd;
+ }
+ }
+ requestor
+ .enterConstructor(
+ cd.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ cd.modifiers,
+ cd.modifiersSourceStart,
+ cd.selector,
+ cd.sourceStart,
+ (int) (selectorSourcePositions & 0xFFFFFFFFL),
+ // retrieve the source end of the name
+ argumentTypes,
+ argumentTypeStarts,
+ argumentTypeEnds,
+ argumentNames,
+ argumentNameStarts,
+ argumentNameEnds,
+ rParenPos,
+ // right parenthesis
+ exceptionTypes,
+ exceptionTypeStarts,
+ exceptionTypeEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeConstructorHeaderName() {
+ // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
+ ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
+
+ //name -- this is not really revelant but we do .....
+ cd.selector = identifierStack[identifierPtr];
+ selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //modifiers
+ cd.declarationSourceStart = intStack[intPtr--];
+ cd.modifiersSourceStart = intStack[intPtr--];
+ cd.modifiers = intStack[intPtr--];
+
+ //highlight starts at the selector starts
+ cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+ pushOnAstStack(cd);
+
+ cd.sourceEnd = lParenPos;
+ cd.bodyStart = lParenPos + 1;
+}
+protected void consumeDefaultModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(-1);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
+ resetModifiers();
+}
+protected void consumeDiet() {
+ // Diet ::= $empty
+ super.consumeDiet();
+ /* persisting javadoc positions
+ * Will be consume in consumeClassBodyDeclaration
+ */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterCompilationUnit() {
+ // EnterCompilationUnit ::= $empty
+ requestor.enterCompilationUnit();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeEnterVariable() {
+ // EnterVariable ::= $empty
+ boolean isLocalDeclaration = isLocalDeclaration();
+ if (!isLocalDeclaration && (variablesCounter[nestedType] != 0)) {
+ requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+ }
+ char[] name = identifierStack[identifierPtr];
+ long namePosition = identifierPositionStack[identifierPtr--];
+ int extendedTypeDimension = intStack[intPtr--];
+
+ AbstractVariableDeclaration declaration;
+ if (nestedMethod[nestedType] != 0) {
+ // create the local variable declarations
+ declaration =
+ new LocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ } else {
+ // create the field declaration
+ declaration =
+ new FieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ }
+ identifierLengthPtr--;
+ TypeReference type;
+ int variableIndex = variablesCounter[nestedType];
+ int typeDim = 0;
+ if (variableIndex == 0) {
+ // first variable of the declaration (FieldDeclaration or LocalDeclaration)
+ if (nestedMethod[nestedType] != 0) {
+ // local declaration
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiersSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+ pushOnAstStack(type);
+ } else {
+ // field declaration
+ type = getTypeReference(typeDim = intStack[intPtr--]); // type dimension
+ pushOnAstStack(type);
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiersSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ }
+ } else {
+ type = (TypeReference) astStack[astPtr - variableIndex];
+ typeDim = type.dimensions();
+ AbstractVariableDeclaration previousVariable =
+ (AbstractVariableDeclaration) astStack[astPtr];
+ declaration.declarationSourceStart = previousVariable.declarationSourceStart;
+ declaration.modifiers = previousVariable.modifiers;
+ declaration.modifiersSourceStart = previousVariable.modifiersSourceStart;
+ }
+
+ localIntPtr = intPtr;
+
+ if (extendedTypeDimension == 0) {
+ declaration.type = type;
+ } else {
+ int dimension = typeDim + extendedTypeDimension;
+ //on the identifierLengthStack there is the information about the type....
+ int baseType;
+ if ((baseType = identifierLengthStack[identifierLengthPtr + 1]) < 0) {
+ //it was a baseType
+ declaration.type = TypeReference.baseTypeReference(-baseType, dimension);
+ declaration.type.sourceStart = type.sourceStart;
+ declaration.type.sourceEnd = type.sourceEnd;
+ } else {
+ declaration.type = this.copyDims(type, dimension);
+ }
+ }
+ variablesCounter[nestedType]++;
+ nestedMethod[nestedType]++;
+ pushOnAstStack(declaration);
+
+ int[] javadocPositions = intArrayStack[intArrayPtr];
+ if (!isLocalDeclaration) {
+ requestor
+ .enterField(
+ declaration.declarationSourceStart,
+ javadocPositions,
+ declaration.modifiers,
+ declaration.modifiersSourceStart,
+ returnTypeName(declaration.type),
+ type.sourceStart,
+ type.sourceEnd,
+ typeDims,
+ name,
+ (int) (namePosition >>> 32),
+ (int) namePosition,
+ extendedTypeDimension,
+ extendedTypeDimension == 0 ? -1 : endPosition);
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // the scanner is located after the comma or the semi-colon.
+ // we want to include the comma or the semi-colon
+ super.consumeExitVariableWithInitialization();
+ nestedMethod[nestedType]--;
+ lastFieldEndPosition = scanner.currentPosition - 1;
+ lastFieldBodyEndPosition = ((AbstractVariableDeclaration) astStack[astPtr]).initialization.sourceEnd;
+}
+protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+ super.consumeExitVariableWithoutInitialization();
+ nestedMethod[nestedType]--;
+ lastFieldEndPosition = scanner.currentPosition - 1;
+ lastFieldBodyEndPosition = scanner.startPosition - 1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeFieldDeclaration() {
+ // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+ // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+ // the super.consumeFieldDeclaration will reinitialize the variableCounter[nestedType]
+ int variableIndex = variablesCounter[nestedType];
+ super.consumeFieldDeclaration();
+ intArrayPtr--;
+ if (isLocalDeclaration())
+ return;
+ if (variableIndex != 0) {
+ requestor.exitField(lastFieldBodyEndPosition, lastFieldEndPosition);
+ }
+}
+protected void consumeFormalParameter() {
+ // FormalParameter ::= Type VariableDeclaratorId ==> false
+ // FormalParameter ::= Modifiers Type VariableDeclaratorId ==> true
+ /*
+ astStack :
+ identifierStack : type identifier
+ intStack : dim dim
+ ==>
+ astStack : Argument
+ identifierStack :
+ intStack :
+ */
+
+ identifierLengthPtr--;
+ char[] name = identifierStack[identifierPtr];
+ long namePositions = identifierPositionStack[identifierPtr--];
+ TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+ intPtr -= 3;
+ Argument arg =
+ new Argument(
+ name,
+ namePositions,
+ type,
+ intStack[intPtr + 1]); // modifiers
+ pushOnAstStack(arg);
+ intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceDeclaration() {
+ super.consumeInterfaceDeclaration();
+ // we know that we have a TypeDeclaration on the top of the astStack
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ requestor.exitInterface(endStatementPosition, // the '}' is the end of the body
+ ((TypeDeclaration) astStack[astPtr]).declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeInterfaceHeader() {
+ //InterfaceHeader ::= $empty
+ super.consumeInterfaceHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ TypeReference[] superInterfaces = typeDecl.superInterfaces;
+ char[][] interfaceNames = null;
+ int[] interfaceNameStarts = null;
+ int[] interfacenameEnds = null;
+ int superInterfacesLength = 0;
+ if (superInterfaces != null) {
+ superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ interfaceNameStarts = new int[superInterfacesLength];
+ interfacenameEnds = new int[superInterfacesLength];
+ }
+ if (superInterfaces != null) {
+ for (int i = 0; i < superInterfacesLength; i++) {
+ TypeReference superInterface = superInterfaces[i];
+ interfaceNames[i] = CharOperation.concatWith(superInterface.getTypeName(), '.');
+ interfaceNameStarts[i] = superInterface.sourceStart;
+ interfacenameEnds[i] = superInterface.sourceEnd;
+ }
+ }
+ // flush the comments related to the interface header
+ scanner.commentPtr = -1;
+ requestor.enterInterface(
+ typeDecl.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ typeDecl.modifiers,
+ typeDecl.modifiersSourceStart,
+ typeStartPosition,
+ typeDecl.name,
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ interfaceNames,
+ interfaceNameStarts,
+ interfacenameEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeInterfaceHeaderName() {
+ // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
+ TypeDeclaration typeDecl;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+ markCurrentMethodWithLocalType();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //compute the declaration source too
+ // 'class' and 'interface' push an int position
+ typeStartPosition = typeDecl.declarationSourceStart = intStack[intPtr--];
+ intPtr--;
+ int declarationSourceStart = intStack[intPtr--];
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.declarationSourceStart > declarationSourceStart) {
+ typeDecl.declarationSourceStart = declarationSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeLocalVariableDeclaration() {
+ // See consumeLocalVariableDeclarationDefaultModifier() in case of change: duplicated code
+ // FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+
+ super.consumeLocalVariableDeclaration();
+ intArrayPtr--;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodDeclaration(boolean isNotAbstract) {
+ // MethodDeclaration ::= MethodHeader MethodBody
+ // AbstractMethodDeclaration ::= MethodHeader ';'
+ super.consumeMethodDeclaration(isNotAbstract);
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ return;
+ }
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+ requestor.exitMethod(endStatementPosition, md.declarationSourceEnd);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodHeader() {
+ // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+ super.consumeMethodHeader();
+ if (isLocalDeclaration()) {
+ // we ignore the local variable declarations
+ intArrayPtr--;
+ return;
+ }
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+
+ TypeReference returnType = md.returnType;
+ char[] returnTypeName = returnTypeName(returnType);
+ Argument[] arguments = md.arguments;
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ int[] argumentTypeStarts = null;
+ int[] argumentTypeEnds = null;
+ int[] argumentNameStarts = null;
+ int[] argumentNameEnds = null;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ argumentNameStarts = new int[argumentLength];
+ argumentNameEnds = new int[argumentLength];
+ argumentTypeStarts = new int[argumentLength];
+ argumentTypeEnds = new int[argumentLength];
+ for (int i = 0; i < argumentLength; i++) {
+ Argument argument = arguments[i];
+ TypeReference argumentType = argument.type;
+ argumentTypes[i] = returnTypeName(argumentType);
+ argumentNames[i] = argument.name;
+ argumentNameStarts[i] = argument.sourceStart;
+ argumentNameEnds[i] = argument.sourceEnd;
+ argumentTypeStarts[i] = argumentType.sourceStart;
+ argumentTypeEnds[i] = argumentType.sourceEnd;
+ }
+ }
+ TypeReference[] thrownExceptions = md.thrownExceptions;
+ char[][] exceptionTypes = null;
+ int[] exceptionTypeStarts = null;
+ int[] exceptionTypeEnds = null;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ exceptionTypeStarts = new int[thrownExceptionLength];
+ exceptionTypeEnds = new int[thrownExceptionLength];
+ exceptionTypes = new char[thrownExceptionLength][];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ TypeReference exception = thrownExceptions[i];
+ exceptionTypes[i] = CharOperation.concatWith(exception.getTypeName(), '.');
+ exceptionTypeStarts[i] = exception.sourceStart;
+ exceptionTypeEnds[i] = exception.sourceEnd;
+ }
+ }
+ requestor
+ .enterMethod(
+ md.declarationSourceStart,
+ intArrayStack[intArrayPtr--],
+ md.modifiers,
+ md.modifiersSourceStart,
+ returnTypeName,
+ returnType.sourceStart,
+ returnType.sourceEnd,
+ typeDims,
+ md.selector,
+ md.sourceStart,
+ (int) (selectorSourcePositions & 0xFFFFFFFFL),
+ argumentTypes,
+ argumentTypeStarts,
+ argumentTypeEnds,
+ argumentNames,
+ argumentNameStarts,
+ argumentNameEnds,
+ rParenPos,
+ extendsDim,
+ extendsDim == 0 ? -1 : endPosition,
+ exceptionTypes,
+ exceptionTypeStarts,
+ exceptionTypeEnds,
+ scanner.currentPosition - 1);
+}
+protected void consumeMethodHeaderExtendedDims() {
+ // MethodHeaderExtendedDims ::= Dimsopt
+ // now we update the returnType of the method
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+ int extendedDims = intStack[intPtr--];
+ extendsDim = extendedDims;
+ if (extendedDims != 0) {
+ TypeReference returnType = md.returnType;
+ md.sourceEnd = endPosition;
+ int dims = returnType.dimensions() + extendedDims;
+ int baseType;
+ if ((baseType = identifierLengthStack[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 (currentToken == TokenNameLBRACE) {
+ md.bodyStart = endPosition + 1;
+ }
+ }
+}
+protected void consumeMethodHeaderName() {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(typeDims = intStack[intPtr--]);
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiersSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSourcePositions >>> 32);
+ pushOnAstStack(md);
+ md.bodyStart = scanner.currentPosition-1;
+}
+protected void consumeModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumePackageDeclarationName() {
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumePackageDeclarationName();
+ ImportReference importReference = compilationUnit.currentPackage;
+
+ requestor.acceptPackage(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart);
+}
+protected void consumePushModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ if (modifiersSourceStart < 0) {
+ pushOnIntStack(-1);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : scanner.startPosition);
+ } else {
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ }
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeSingleTypeImportDeclarationName() {
+ // SingleTypeImportDeclarationName ::= 'import' Name
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumeSingleTypeImportDeclarationName();
+ ImportReference importReference = (ImportReference) astStack[astPtr];
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart,
+ false);
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeStaticInitializer() {
+ // StaticInitializer ::= StaticOnly Block
+ //push an Initializer
+ //optimize the push/pop
+ super.consumeStaticInitializer();
+ Initializer initializer = (Initializer) astStack[astPtr];
+ requestor.acceptInitializer(
+ initializer.declarationSourceStart,
+ initializer.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ AccStatic,
+ intStack[intPtr--],
+ initializer.block.sourceStart,
+ initializer.declarationSourceEnd);
+}
+protected void consumeStaticOnly() {
+ // StaticOnly ::= 'static'
+ checkAnnotation(); // might update declaration source start
+ pushOnIntStack(modifiersSourceStart);
+ pushOnIntStack(
+ declarationSourceStart >= 0 ? declarationSourceStart : modifiersSourceStart);
+ jumpOverMethodBody();
+ nestedMethod[nestedType]++;
+ resetModifiers();
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeTypeImportOnDemandDeclarationName() {
+ // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+
+ /* persisting javadoc positions */
+ pushOnIntArrayStack(this.getJavaDocPositions());
+
+ super.consumeTypeImportOnDemandDeclarationName();
+ ImportReference importReference = (ImportReference) astStack[astPtr];
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ intArrayStack[intArrayPtr--],
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.sourceStart,
+ true);
+}
+public CompilationUnitDeclaration endParse(int act) {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+ }
+ return super.endParse(act);
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+ return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+}
+protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
+This variable is a type reference and dim will be its dimensions*/
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[identifierPtr],
+ dim,
+ identifierPositionStack[identifierPtr--]);
+ ref.sourceEnd = endPosition;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[intPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[intPtr--];
+ } else {
+ intPtr--;
+ ref.sourceEnd = endPosition;
+ }
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ ref = new QualifiedTypeReference(tokens, positions);
+ } else {
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ ref.sourceEnd = endPosition;
+ }
+ }
+ };
+ return ref;
+}
+public void initialize() {
+ //positionning the parser for a new compilation unit
+ //avoiding stack reallocation and all that....
+ super.initialize();
+ intArrayPtr = -1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+private boolean isLocalDeclaration() {
+ int nestedDepth = nestedType;
+ while (nestedDepth >= 0) {
+ if (nestedMethod[nestedDepth] != 0) {
+ return true;
+ }
+ nestedDepth--;
+ }
+ return false;
+}
+/*
+ * Investigate one entire unit.
+ */
+public void parseCompilationUnit(ICompilationUnit unit) {
+ char[] regionSource = unit.getContents();
+ try {
+ initialize();
+ goForCompilationUnit();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+}
+/*
+ * Investigate one constructor declaration.
+ */
+public void parseConstructor(char[] regionSource) {
+ try {
+ initialize();
+ goForClassBodyDeclarations();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+}
+/*
+ * Investigate one field declaration statement (might have multiple declarations in it).
+ */
+public void parseField(char[] regionSource) {
+ try {
+ initialize();
+ goForFieldDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one import statement declaration.
+ */
+public void parseImport(char[] regionSource) {
+ try {
+ initialize();
+ goForImportDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one initializer declaration.
+ * regionSource need to content exactly an initializer declaration.
+ * e.g: static { i = 4; }
+ * { name = "test"; }
+ */
+public void parseInitializer(char[] regionSource) {
+ try {
+ initialize();
+ goForInitializer();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one method declaration.
+ */
+public void parseMethod(char[] regionSource) {
+ try {
+ initialize();
+ goForGenericMethodDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one package statement declaration.
+ */
+public void parsePackage(char[] regionSource) {
+ try {
+ initialize();
+ goForPackageDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/*
+ * Investigate one type declaration, its fields, methods and member types.
+ */
+public void parseType(char[] regionSource) {
+ try {
+ initialize();
+ goForTypeDeclaration();
+ referenceContext =
+ compilationUnit =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter(),
+ new CompilationResult(regionSource, 0, 0, this.options.maxProblemsPerUnit),
+ regionSource.length);
+ scanner.resetTo(0, regionSource.length);
+ scanner.setSource(regionSource);
+ parse();
+ } catch (AbortCompilation ex) {
+ }
+
+}
+/**
+ * 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.
+ */
+public ProblemReporter problemReporter() {
+ problemReporter.referenceContext = referenceContext;
+ return problemReporter;
+}
+protected void pushOnIntArrayStack(int[] positions) {
+
+ try {
+ intArrayStack[++intArrayPtr] = positions;
+ } catch (IndexOutOfBoundsException e) {
+ //intPtr is correct
+ int oldStackLength = intArrayStack.length;
+ int oldStack[][] = intArrayStack;
+ intArrayStack = new int[oldStackLength + StackIncrement][];
+ System.arraycopy(oldStack, 0, intArrayStack, 0, oldStackLength);
+ intArrayStack[intArrayPtr] = positions;
+ }
+}
+protected void resetModifiers() {
+ super.resetModifiers();
+ declarationSourceStart = -1;
+}
+/*
+ * Syntax error was detected. Will attempt to perform some recovery action in order
+ * to resume to the regular parse loop.
+ */
+protected boolean resumeOnSyntaxError() {
+ return false;
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+ int dimension = type.dimensions();
+ if (dimension != 0) {
+ char[] dimensionsArray = new char[dimension * 2];
+ for (int i = 0; i < dimension; i++) {
+ dimensionsArray[i*2] = '[';
+ dimensionsArray[(i*2) + 1] = ']';
+ }
+ return CharOperation.concat(
+ CharOperation.concatWith(type.getTypeName(), '.'),
+ dimensionsArray);
+ }
+ return CharOperation.concatWith(type.getTypeName(), '.');
+}
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("intArrayPtr = " + intArrayPtr + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
+ buffer.append(super.toString());
+ return buffer.toString();
+}
+/**
+ * INTERNAL USE ONLY
+ */
+protected TypeReference typeReference(
+ int dim,
+ int localIdentifierPtr,
+ int localIdentifierLengthPtr) {
+ /* build a Reference on a variable that may be qualified or not
+ * This variable is a type reference and dim will be its dimensions.
+ * We don't have any side effect on the stacks' pointers.
+ */
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[localIdentifierPtr],
+ identifierPositionStack[localIdentifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[localIdentifierPtr],
+ dim,
+ identifierPositionStack[localIdentifierPtr--]);
+ ref.sourceEnd = endPosition;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[localIntPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[localIntPtr--];
+ } else {
+ localIntPtr--;
+ ref.sourceEnd = endPosition;
+ }
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ localIdentifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ localIdentifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0)
+ ref = new QualifiedTypeReference(tokens, positions);
+ else
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ }
+ };
+ return ref;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+/**
+ * A visitor interface for interating through the parse tree.
+ */
+public interface IAbstractSyntaxTreeVisitor {
+ void acceptProblem(IProblem problem);
+ void endVisit(AllocationExpression allocationExpression, BlockScope scope);
+ void endVisit(AND_AND_Expression and_and_Expression, BlockScope scope);
+ void endVisit(AnonymousLocalTypeDeclaration anonymousTypeDeclaration, BlockScope scope);
+ void endVisit(Argument argument, BlockScope scope);
+ void endVisit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope);
+ void endVisit(ArrayInitializer arrayInitializer, BlockScope scope);
+ void endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope);
+ void endVisit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope);
+ void endVisit(ArrayReference arrayReference, BlockScope scope);
+ void endVisit(ArrayTypeReference arrayTypeReference, BlockScope scope);
+ void endVisit(ArrayTypeReference arrayTypeReference, ClassScope scope);
+ void endVisit(AssertStatement assertStatement, BlockScope scope);
+ void endVisit(Assignment assignment, BlockScope scope);
+ void endVisit(BinaryExpression binaryExpression, BlockScope scope);
+ void endVisit(Block block, BlockScope scope);
+ void endVisit(Break breakStatement, BlockScope scope);
+ void endVisit(Case caseStatement, BlockScope scope);
+ void endVisit(CastExpression castExpression, BlockScope scope);
+ void endVisit(CharLiteral charLiteral, BlockScope scope);
+ void endVisit(ClassLiteralAccess classLiteral, BlockScope scope);
+ void endVisit(Clinit clinit, ClassScope scope);
+ void endVisit(CompilationUnitDeclaration compilationUnitDeclaration, CompilationUnitScope scope);
+ void endVisit(CompoundAssignment compoundAssignment, BlockScope scope);
+ void endVisit(ConditionalExpression conditionalExpression, BlockScope scope);
+ void endVisit(ConstructorDeclaration constructorDeclaration, ClassScope scope);
+ void endVisit(Continue continueStatement, BlockScope scope);
+ void endVisit(DefaultCase defaultCaseStatement, BlockScope scope);
+ void endVisit(DoStatement doStatement, BlockScope scope);
+ void endVisit(DoubleLiteral doubleLiteral, BlockScope scope);
+ void endVisit(EqualExpression equalExpression, BlockScope scope);
+ void endVisit(EmptyStatement statement, BlockScope scope);
+ void endVisit(ExplicitConstructorCall explicitConstructor, BlockScope scope);
+ void endVisit(ExtendedStringLiteral extendedStringLiteral, BlockScope scope);
+ void endVisit(FalseLiteral falseLiteral, BlockScope scope);
+ void endVisit(FieldDeclaration fieldDeclaration, MethodScope scope);
+ void endVisit(FieldReference fieldReference, BlockScope scope);
+ void endVisit(FloatLiteral floatLiteral, BlockScope scope);
+ void endVisit(ForStatement forStatement, BlockScope scope);
+ void endVisit(IfStatement ifStatement, BlockScope scope);
+ void endVisit(ImportReference importRef, CompilationUnitScope scope);
+ void endVisit(Initializer initializer, MethodScope scope);
+ void endVisit(InstanceOfExpression instanceOfExpression, BlockScope scope);
+ void endVisit(IntLiteral intLiteral, BlockScope scope);
+ void endVisit(LabeledStatement labeledStatement, BlockScope scope);
+ void endVisit(LocalDeclaration localDeclaration, BlockScope scope);
+ void endVisit(LocalTypeDeclaration localTypeDeclaration, BlockScope scope);
+ void endVisit(LongLiteral longLiteral, BlockScope scope);
+ void endVisit(MemberTypeDeclaration memberTypeDeclaration, ClassScope scope);
+ void endVisit(MessageSend messageSend, BlockScope scope);
+ void endVisit(MethodDeclaration methodDeclaration, ClassScope scope);
+ void endVisit(NullLiteral nullLiteral, BlockScope scope);
+ void endVisit(OR_OR_Expression or_or_Expression, BlockScope scope);
+ void endVisit(PostfixExpression postfixExpression, BlockScope scope);
+ void endVisit(PrefixExpression prefixExpression, BlockScope scope);
+ void endVisit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope);
+ void endVisit(QualifiedNameReference qualifiedNameReference, BlockScope scope);
+ void endVisit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope);
+ void endVisit(QualifiedThisReference qualifiedThisReference, BlockScope scope);
+ void endVisit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope);
+ void endVisit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope);
+ void endVisit(ReturnStatement returnStatement, BlockScope scope);
+ void endVisit(SingleNameReference singleNameReference, BlockScope scope);
+ void endVisit(SingleTypeReference singleTypeReference, BlockScope scope);
+ void endVisit(SingleTypeReference singleTypeReference, ClassScope scope);
+ void endVisit(StringLiteral stringLiteral, BlockScope scope);
+ void endVisit(SuperReference superReference, BlockScope scope);
+ void endVisit(SwitchStatement switchStatement, BlockScope scope);
+ void endVisit(SynchronizedStatement synchronizedStatement, BlockScope scope);
+ void endVisit(ThisReference thisReference, BlockScope scope);
+ void endVisit(ThrowStatement throwStatement, BlockScope scope);
+ void endVisit(TrueLiteral trueLiteral, BlockScope scope);
+ void endVisit(TryStatement tryStatement, BlockScope scope);
+ void endVisit(TypeDeclaration typeDeclaration, CompilationUnitScope scope);
+ void endVisit(UnaryExpression unaryExpression, BlockScope scope);
+ void endVisit(WhileStatement whileStatement, BlockScope scope);
+ boolean visit(AllocationExpression allocationExpression, BlockScope scope);
+ boolean visit(AND_AND_Expression and_and_Expression, BlockScope scope);
+ boolean visit(AnonymousLocalTypeDeclaration anonymousTypeDeclaration, BlockScope scope);
+ boolean visit(Argument argument, BlockScope scope);
+ boolean visit(ArrayAllocationExpression arrayAllocationExpression, BlockScope scope);
+ boolean visit(ArrayInitializer arrayInitializer, BlockScope scope);
+ boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, BlockScope scope);
+ boolean visit(ArrayQualifiedTypeReference arrayQualifiedTypeReference, ClassScope scope);
+ boolean visit(ArrayReference arrayReference, BlockScope scope);
+ boolean visit(ArrayTypeReference arrayTypeReference, BlockScope scope);
+ boolean visit(ArrayTypeReference arrayTypeReference, ClassScope scope);
+ boolean visit(AssertStatement assertStatement, BlockScope scope);
+ boolean visit(Assignment assignment, BlockScope scope);
+ boolean visit(BinaryExpression binaryExpression, BlockScope scope);
+ boolean visit(Block block, BlockScope scope);
+ boolean visit(Break breakStatement, BlockScope scope);
+ boolean visit(Case caseStatement, BlockScope scope);
+ boolean visit(CastExpression castExpression, BlockScope scope);
+ boolean visit(CharLiteral charLiteral, BlockScope scope);
+ boolean visit(ClassLiteralAccess classLiteral, BlockScope scope);
+ boolean visit(Clinit clinit, ClassScope scope);
+ boolean visit(CompilationUnitDeclaration compilationUnitDeclaration, CompilationUnitScope scope);
+ boolean visit(CompoundAssignment compoundAssignment, BlockScope scope);
+ boolean visit(ConditionalExpression conditionalExpression, BlockScope scope);
+ boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope);
+ boolean visit(Continue continueStatement, BlockScope scope);
+ boolean visit(DefaultCase defaultCaseStatement, BlockScope scope);
+ boolean visit(DoStatement doStatement, BlockScope scope);
+ boolean visit(DoubleLiteral doubleLiteral, BlockScope scope);
+ boolean visit(EqualExpression equalExpression, BlockScope scope);
+ boolean visit(EmptyStatement statement, BlockScope scope);
+ boolean visit(ExplicitConstructorCall explicitConstructor, BlockScope scope);
+ boolean visit(ExtendedStringLiteral extendedStringLiteral, BlockScope scope);
+ boolean visit(FalseLiteral falseLiteral, BlockScope scope);
+ boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope);
+ boolean visit(FieldReference fieldReference, BlockScope scope);
+ boolean visit(FloatLiteral floatLiteral, BlockScope scope);
+ boolean visit(ForStatement forStatement, BlockScope scope);
+ boolean visit(IfStatement ifStatement, BlockScope scope);
+ boolean visit(ImportReference importRef, CompilationUnitScope scope);
+ boolean visit(Initializer initializer, MethodScope scope);
+ boolean visit(InstanceOfExpression instanceOfExpression, BlockScope scope);
+ boolean visit(IntLiteral intLiteral, BlockScope scope);
+ boolean visit(LabeledStatement labeledStatement, BlockScope scope);
+ boolean visit(LocalDeclaration localDeclaration, BlockScope scope);
+ boolean visit(LocalTypeDeclaration localTypeDeclaration, BlockScope scope);
+ boolean visit(LongLiteral longLiteral, BlockScope scope);
+ boolean visit(MemberTypeDeclaration memberTypeDeclaration, ClassScope scope);
+ boolean visit(MessageSend messageSend, BlockScope scope);
+ boolean visit(MethodDeclaration methodDeclaration, ClassScope scope);
+ boolean visit(NullLiteral nullLiteral, BlockScope scope);
+ boolean visit(OR_OR_Expression or_or_Expression, BlockScope scope);
+ boolean visit(PostfixExpression postfixExpression, BlockScope scope);
+ boolean visit(PrefixExpression prefixExpression, BlockScope scope);
+ boolean visit(QualifiedAllocationExpression qualifiedAllocationExpression, BlockScope scope);
+ boolean visit(QualifiedNameReference qualifiedNameReference, BlockScope scope);
+ boolean visit(QualifiedSuperReference qualifiedSuperReference, BlockScope scope);
+ boolean visit(QualifiedThisReference qualifiedThisReference, BlockScope scope);
+ boolean visit(QualifiedTypeReference qualifiedTypeReference, BlockScope scope);
+ boolean visit(QualifiedTypeReference qualifiedTypeReference, ClassScope scope);
+ boolean visit(ReturnStatement returnStatement, BlockScope scope);
+ boolean visit(SingleNameReference singleNameReference, BlockScope scope);
+ boolean visit(SingleTypeReference singleTypeReference, BlockScope scope);
+ boolean visit(SingleTypeReference singleTypeReference, ClassScope scope);
+ boolean visit(StringLiteral stringLiteral, BlockScope scope);
+ boolean visit(SuperReference superReference, BlockScope scope);
+ boolean visit(SwitchStatement switchStatement, BlockScope scope);
+ boolean visit(SynchronizedStatement synchronizedStatement, BlockScope scope);
+ boolean visit(ThisReference thisReference, BlockScope scope);
+ boolean visit(ThrowStatement throwStatement, BlockScope scope);
+ boolean visit(TrueLiteral trueLiteral, BlockScope scope);
+ boolean visit(TryStatement tryStatement, BlockScope scope);
+ boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope);
+ boolean visit(UnaryExpression unaryExpression, BlockScope scope);
+ boolean visit(WhileStatement whileStatement, BlockScope scope);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+/**
+ * A callback interface for receiving compilation results.
+ */
+public interface ICompilerRequestor {
+
+ /**
+ * Accept a compilation result.
+ */
+ public void acceptResult(CompilationResult result);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
+
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+/**
+ * Part of the source element parser responsible for building the output.
+ * It gets notified of structural information as they are detected, relying
+ * on the requestor to assemble them together, based on the notifications it got.
+ *
+ * The structural investigation includes:
+ * - package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ *
+ * All positions are relative to the exact source fed to the parser.
+ *
+ * Elements which are complex are notified in two steps:
+ * - enter<Element> : once the element header has been identified
+ * - exit<Element> : once the element has been fully consumed
+ *
+ * other simpler elements (package, import) are read all at once:
+ * - accept<Element>
+ */
+
+public interface IDocumentElementRequestor {
+/**
+ * @param declarationStart - a source position corresponding to the start of the package
+ * declaration
+ * @param declarationEnd - a source position corresponding to the end of the package
+ * declaration
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param name - the name of the package
+ * @param nameStartPosition - a source position corresponding to the first character of the
+ * name
+ * @param onDemand - a boolean equals to true if the import is an import on demand
+ */
+void acceptImport(
+ int declarationStart,
+ int declarationEnd,
+ int[] javaDocPositions,
+ char[] name,
+ int nameStartPosition,
+ boolean onDemand);
+/**
+ * @param declarationStart - a source position corresponding to the start of the package
+ * declaration
+ * @param declarationEnd - a source position corresponding to the end of the package
+ * declaration
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param modifiers - the modifiers for this initializer
+ * @param modifiersStart - a source position corresponding to the start
+ * of the textual modifiers, is < 0 if there are no textual modifiers
+ * @param bodyStart - the position of the '{'
+ * @param bodyEnd - the position of the '}'
+ */
+void acceptInitializer(
+ int declarationStart,
+ int declarationEnd,
+ int[] javaDocPositions,
+ int modifiers,
+ int modifiersStart,
+ int bodyStart,
+ int bodyEnd);
+/*
+ * Table of line separator position. This table is passed once at the end
+ * of the parse action, so as to allow computation of normalized ranges.
+ *
+ * A line separator might corresponds to several characters in the source,
+ *
+ */
+void acceptLineSeparatorPositions(int[] positions);
+/**
+ * @param declarationStart - a source position corresponding to the start of the package
+ * declaration
+ * @param declarationEnd - a source position corresponding to the end of the package
+ * declaration
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param name - the name of the package
+ * @param nameStartPosition - a source position corresponding to the first character of the
+ * name
+ */
+void acceptPackage(
+ int declarationStart,
+ int declarationEnd,
+ int[] javaDocPositions,
+ char[] name,
+ int nameStartPosition);
+/**
+ * @param problem - Used to report a problem while running the JDOM
+ */
+void acceptProblem(IProblem problem);
+/**
+ * @param declarationStart - a source position corresponding to the start
+ * of this class.
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param modifiers - the modifiers for this class
+ * @param modifiersStart - a source position corresponding to the start
+ * of the textual modifiers, is < 0 if there are no textual modifiers
+ * @param classStart - a source position corresponding to the start
+ * of the keyword 'class'
+ * @param name - the name of the class
+ * @param nameStart - a source position corresponding to the start of the name
+ * @param nameEnd - a source position corresponding to the end of the name
+ * @param superclass - the name of the superclass
+ * @param superclassStart - a source position corresponding to the start
+ * of the superclass name
+ * @param superclassEnd - a source position corresponding to the end of the
+ * superclass name
+ * @param superinterfaces - the name of the superinterfaces
+ * @param superinterfaceStarts - an array of source positions corresponding
+ * to the start of their respective superinterface names
+ * @param superinterfaceEnds - an array of source positions corresponding
+ * to the end of their respective superinterface names
+ * @param bodyStart - a source position corresponding to the open bracket
+ * of the class body
+ */
+void enterClass(
+ int declarationStart,
+ int[] javaDocPositions,
+ int modifiers,
+ int modifiersStart,
+ int classStart,
+ char[] name,
+ int nameStart,
+ int nameEnd,
+ char[] superclass,
+ int superclassStart,
+ int superclassEnd,
+ char[][] superinterfaces,
+ int[] superinterfaceStarts,
+ int[] superinterfaceEnds,
+ int bodyStart);
+void enterCompilationUnit();
+/**
+ * @param declarationStart - a source position corresponding to the first character
+ * of this constructor declaration
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param modifiers - the modifiers for this constructor converted to a flag
+ * @param modifiersStart - a source position corresponding to the first character of the
+ * textual modifiers
+ * @param name - the name of this constructor
+ * @param nameStart - a source position corresponding to the first character of the name
+ * @param nameEnd - a source position corresponding to the last character of the name
+ * @param parameterTypes - a list of parameter type names
+ * @param parameterTypeStarts - a list of source positions corresponding to the
+ * first character of each parameter type name
+ * @param parameterTypeEnds - a list of source positions corresponding to the
+ * last character of each parameter type name
+ * @param parameterNames - a list of the names of the parameters
+ * @param parametersEnd - a source position corresponding to the last character of the
+ * parameter list
+ * @param exceptionTypes - a list of the exception types
+ * @param exceptionTypeStarts - a list of source positions corresponding to the first
+ * character of the respective exception types
+ * @param exceptionTypeEnds - a list of source positions corresponding to the last
+ * character of the respective exception types
+ * @param bodyStart - a source position corresponding to the start of this
+ * constructor's body
+ */
+void enterConstructor(
+ int declarationStart,
+ int[] javaDocPositions,
+ int modifiers,
+ int modifiersStart,
+ char[] name,
+ int nameStart,
+ int nameEnd,
+ char[][] parameterTypes,
+ int [] parameterTypeStarts,
+ int [] parameterTypeEnds,
+ char[][] parameterNames,
+ int [] parameterNameStarts,
+ int [] parameterNameEnds,
+ int parametersEnd,
+ char[][] exceptionTypes,
+ int [] exceptionTypeStarts,
+ int [] exceptionTypeEnds,
+ int bodyStart);
+/**
+ * @param declarationStart - a source position corresponding to the first character
+ * of this field
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param modifiers - the modifiers for this field converted to a flag
+ * @param modifiersStart - a source position corresponding to the first character of the
+ * textual modifiers
+ * @param type - the name of the field type
+ * @param typeStart - a source position corresponding to the start of the fields type
+ * @param typeEnd - a source position corresponding to the end of the fields type
+ * @param typeDimensionCount - the array dimension indicated on the type, i.e. int[] v
+ * @param name - the name of this constructor
+ * @param nameStart - a source position corresponding to the first character of the name
+ * @param nameEnd - a source position corresponding to the last character of the name
+ * @param extendedTypeDimensionCount - the array dimension indicated on the variable,
+ * i.e. int v[]
+ * @param extendedTypeDimnesionEnd - a source position corresponding to the end of
+ * the extened type dimension. This position should be -1 in case there is no extended
+ * dimension for the type.
+ */
+void enterField(
+ int declarationStart,
+ int[] javaDocPositions,
+ int modifiers,
+ int modifiersStart,
+ char[] type,
+ int typeStart,
+ int typeEnd,
+ int typeDimensionCount,
+ char[] name,
+ int nameStart,
+ int nameEnd,
+ int extendedTypeDimensionCount,
+ int extendedTypeDimensionEnd);
+/**
+ * @param declarationStart - a source position corresponding to the start
+ * of this class.
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param modifiers - the modifiers for this class
+ * @param modifiersStart - a source position corresponding to the start
+ * of the textual modifiers, is < 0 if there are no textual modifiers
+ * @param interfaceStart - a source position corresponding to the start
+ * of the keyword 'interface'
+ * @param name - the name of the class
+ * @param nameStart - a source position corresponding to the start of the name
+ * @param nameEnd - a source position corresponding to the end of the name
+ * @param superinterfaces - the name of the superinterfaces
+ * @param superinterfaceStarts - an array of source positions corresponding
+ * to the start of their respective superinterface names
+ * @param superinterfaceEnds - an array of source positions corresponding
+ * to the end of their respective superinterface names
+ * @param bodyStart - a source position corresponding to the open bracket
+ * of the class body
+ */
+void enterInterface(
+ int declarationStart,
+ int[] javaDocPositions,
+ int modifiers,
+ int modifiersStart,
+ int interfaceStart,
+ char[] name,
+ int nameStart,
+ int nameEnd,
+ char[][] superinterfaces,
+ int[] superinterfaceStarts,
+ int[] superinterfaceEnds,
+ int bodyStart);
+/**
+ * @param declarationStart - a source position corresponding to the first character
+ * of this constructor declaration
+ * @param javaDocPositions - 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
+ * The array is equals to null if there are no javadoc comments
+ * @param modifiers - the modifiers for this constructor converted to a flag
+ * @param modifiersStart - a source position corresponding to the first character of the
+ * textual modifiers
+ * @param returnType - the name of the return type
+ * @param returnTypeStart - a source position corresponding to the first character
+ * of the return type
+ * @param returnTypeEnd - a source position corresponding to the last character
+ * of the return type
+ * @param returnTypeDimensionCount - the array dimension count as supplied on the
+ * return type, i.e. public int[] foo() {}
+ * @param name - the name of this constructor
+ * @param nameStart - a source position corresponding to the first character of the name
+ * @param nameEnd - a source position corresponding to the last character of the name
+ * @param parameterTypes - a list of parameter type names
+ * @param parameterTypeStarts - a list of source positions corresponding to the
+ * first character of each parameter type name
+ * @param parameterTypeEnds - a list of source positions corresponding to the
+ * last character of each parameter type name
+ * @param parameterNames - a list of the names of the parameters
+ * @param parametersEnd - a source position corresponding to the last character of the
+ * parameter list
+ * @param extendedReturnTypeDimensionCount - the array dimension count as supplied on the
+ * end of the parameter list, i.e. public int foo()[] {}
+ * @param extendedReturnTypeDimensionEnd - a source position corresponding to the last character
+ * of the extended return type dimension. This position should be -1 in case there is no extended
+ * dimension for the type.
+ * @param exceptionTypes - a list of the exception types
+ * @param exceptionTypeStarts - a list of source positions corresponding to the first
+ * character of the respective exception types
+ * @param exceptionTypeEnds - a list of source positions corresponding to the last
+ * character of the respective exception types
+ * @param bodyStart - a source position corresponding to the start of this
+ * method's body
+ */
+void enterMethod(
+ int declarationStart,
+ int[] javaDocPositions,
+ int modifiers,
+ int modifiersStart,
+ char[] returnType,
+ int returnTypeStart,
+ int returnTypeEnd,
+ int returnTypeDimensionCount,
+ char[] name,
+ int nameStart,
+ int nameEnd,
+ char[][] parameterTypes,
+ int [] parameterTypeStarts,
+ int [] parameterTypeEnds,
+ char[][] parameterNames,
+ int [] parameterNameStarts,
+ int [] parameterNameEnds,
+ int parametersEnd,
+ int extendedReturnTypeDimensionCount,
+ int extendedReturnTypeDimensionEnd,
+ char[][] exceptionTypes,
+ int [] exceptionTypeStarts,
+ int [] exceptionTypeEnds,
+ int bodyStart);
+/**
+ * @param bodyEnd - a source position corresponding to the closing bracket of the class
+ * @param declarationEnd - a source position corresponding to the end of the class
+ * declaration. This can include whitespace and comments following the closing bracket.
+ */
+void exitClass(
+ int bodyEnd,
+ int declarationEnd);
+/**
+ * @param declarationEnd - a source position corresponding to the end of the compilation unit
+ */
+void exitCompilationUnit(
+ int declarationEnd);
+/**
+ * @param bodyEnd - a source position corresponding to the closing bracket of the method
+ * @param declarationEnd - a source position corresponding to the end of the method
+ * declaration. This can include whitespace and comments following the closing bracket.
+ */
+void exitConstructor(
+ int bodyEnd,
+ int declarationEnd);
+/**
+ * @param bodyEnd - a source position corresponding to the end of the field.
+ * @param declarationEnd - a source position corresponding to the end of the field.
+ * This can include whitespace and comments following the semi-colon.
+ */
+void exitField(
+ int bodyEnd,
+ int declarationEnd);
+/**
+ * @param bodyEnd - a source position corresponding to the closing bracket of the interface
+ * @param declarationEnd - a source position corresponding to the end of the interface
+ * declaration. This can include whitespace and comments following the closing bracket.
+ */
+void exitInterface(
+ int bodyEnd,
+ int declarationEnd);
+/**
+ * @param bodyEnd - a source position corresponding to the closing bracket of the method
+ * @param declarationEnd - a source position corresponding to the end of the method
+ * declaration. This can include whitespace and comments following the closing bracket.
+ */
+void exitMethod(
+ int bodyEnd,
+ int declarationEnd);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 (i.e. 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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import java.util.Locale;
+
+import net.sourceforge.phpdt.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[] arguments,
+ int severity,
+ int startPosition,
+ int endPosition,
+ int lineNumber);
+
+ Locale getLocale();
+
+ String getLocalizedMessage(int problemId, String[] problemArguments);
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+/*
+ * Part of the source element parser responsible for building the output.
+ * It gets notified of structural information as they are detected, relying
+ * on the requestor to assemble them together, based on the notifications it got.
+ *
+ * The structural investigation includes:
+ * - package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ *
+ * All positions are relative to the exact source fed to the parser.
+ *
+ * Elements which are complex are notified in two steps:
+ * - enter<Element> : once the element header has been identified
+ * - exit<Element> : once the element has been fully consumed
+ *
+ * other simpler elements (package, import) are read all at once:
+ * - accept<Element>
+ */
+
+public interface ISourceElementRequestor {
+void acceptConstructorReference(char[] typeName, int argCount, int sourcePosition);
+void acceptFieldReference(char[] fieldName, int sourcePosition);
+/**
+ * @param declarationStart This is the position of the first character of the
+ * import keyword.
+ * @param declarationEnd This is the position of the ';' ending the import statement
+ * or the end of the comment following the import.
+ * @param name This is the name of the import like specified in the source including the dots. The '.*'
+ * is never included in the name.
+ * @param onDemand set to true if the import is an import on demand (e.g. import java.io.*). False otherwise.
+ */
+void acceptImport(
+ int declarationStart,
+ int declarationEnd,
+ char[] name,
+ boolean onDemand);
+/*
+ * Table of line separator position. This table is passed once at the end
+ * of the parse action, so as to allow computation of normalized ranges.
+ *
+ * A line separator might corresponds to several characters in the source,
+ *
+ */
+void acceptLineSeparatorPositions(int[] positions);
+void acceptMethodReference(char[] methodName, int argCount, int sourcePosition);
+void acceptPackage(
+ int declarationStart,
+ int declarationEnd,
+ char[] name);
+void acceptProblem(IProblem problem);
+void acceptTypeReference(char[][] typeName, int sourceStart, int sourceEnd);
+void acceptTypeReference(char[] typeName, int sourcePosition);
+void acceptUnknownReference(char[][] name, int sourceStart, int sourceEnd);
+void acceptUnknownReference(char[] name, int sourcePosition);
+void enterClass(
+ int declarationStart,
+ int modifiers,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[] superclass,
+ char[][] superinterfaces);
+void enterCompilationUnit();
+void enterConstructor(
+ int declarationStart,
+ int modifiers,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ char[][] exceptionTypes);
+void enterField(
+ int declarationStart,
+ int modifiers,
+ char[] type,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd);
+void enterInitializer(
+ int declarationStart,
+ int modifiers);
+void enterInterface(
+ int declarationStart,
+ int modifiers,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[][] superinterfaces);
+void enterMethod(
+ int declarationStart,
+ int modifiers,
+ char[] returnType,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ char[][] exceptionTypes);
+void exitClass(int declarationEnd);
+void exitCompilationUnit(int declarationEnd);
+void exitConstructor(int declarationEnd);
+/*
+ * - No initialization source for now -
+ * initializationSource denotes the source of the expression used for initializing
+ * the field if any (if no source, then it is null).
+ *
+ * Note: the initializationSource will be used in case we do need to type check
+ * against source models, and thus the only interesting use for it is field
+ * constant propagation. Therefore, the initializationSource will only be non
+ * null for final fields (so as to minimize char[] allocations).
+ */
+void exitField(/*char[] initializationSource, */int declarationEnd);
+void exitInitializer(int declarationEnd);
+void exitInterface(int declarationEnd);
+void exitMethod(int declarationEnd);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+/**
+ * A source element parser extracts structural and reference information
+ * from a piece of source.
+ *
+ * also see @ISourceElementRequestor
+ *
+ * The structural investigation includes:
+ * - the package statement
+ * - import statements
+ * - top-level types: package member, member types (member types of member types...)
+ * - fields
+ * - methods
+ *
+ * If reference information is requested, then all source constructs are
+ * investigated and type, field & method references are provided as well.
+ *
+ * Any (parsing) problem encountered is also provided.
+ */
+
+import net.sourceforge.phpdt.internal.compiler.env.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+public class SourceElementParser extends Parser {
+
+ ISourceElementRequestor requestor;
+ private int fieldCount;
+ private int localIntPtr;
+ private int lastFieldEndPosition;
+ private ISourceType sourceType;
+ private boolean reportReferenceInfo;
+ private char[][] typeNames;
+ private char[][] superTypeNames;
+ private int nestedTypeIndex;
+ private static final char[] JAVA_LANG_OBJECT = "java.lang.Object".toCharArray(); //$NON-NLS-1$
+ private NameReference[] unknownRefs;
+ private int unknownRefsCounter;
+ private LocalDeclarationVisitor localDeclarationVisitor = null;
+ private CompilerOptions options;
+
+/**
+ * An ast visitor that visits local type declarations.
+ */
+public class LocalDeclarationVisitor extends AbstractSyntaxTreeVisitorAdapter {
+ public boolean visit(
+ AnonymousLocalTypeDeclaration anonymousTypeDeclaration,
+ BlockScope scope) {
+ notifySourceElementRequestor(anonymousTypeDeclaration, sourceType == null);
+ return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+ }
+ public boolean visit(LocalTypeDeclaration typeDeclaration, BlockScope scope) {
+ notifySourceElementRequestor(typeDeclaration, sourceType == null);
+ return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+ }
+ public boolean visit(MemberTypeDeclaration typeDeclaration, ClassScope scope) {
+ notifySourceElementRequestor(typeDeclaration, sourceType == null);
+ return false; // don't visit members as this was done during notifySourceElementRequestor(...)
+ }
+
+}
+
+public SourceElementParser(
+ final ISourceElementRequestor requestor,
+ IProblemFactory problemFactory,
+ CompilerOptions options) {
+ // we want to notify all syntax error with the acceptProblem API
+ // To do so, we define the record method of the ProblemReporter
+ super(new ProblemReporter(
+ DefaultErrorHandlingPolicies.exitAfterAllProblems(),
+ options,
+ problemFactory) {
+ public void record(IProblem problem, CompilationResult unitResult, ReferenceContext referenceContext) {
+ unitResult.record(problem, referenceContext);
+ requestor.acceptProblem(problem);
+ }
+ },
+ true,
+ options.assertMode);
+ this.requestor = requestor;
+ typeNames = new char[4][];
+ superTypeNames = new char[4][];
+ nestedTypeIndex = 0;
+ this.options = options;
+}
+
+/** @deprecated use SourceElementParser(ISourceElementRequestor, IProblemFactory, CompilerOptions) */
+public SourceElementParser(
+ final ISourceElementRequestor requestor,
+ IProblemFactory problemFactory) {
+ this(requestor, problemFactory, new CompilerOptions());
+}
+
+public SourceElementParser(
+ final ISourceElementRequestor requestor,
+ IProblemFactory problemFactory,
+ CompilerOptions options,
+ boolean reportLocalDeclarations) {
+ this(requestor, problemFactory, options);
+ if (reportLocalDeclarations) {
+ this.localDeclarationVisitor = new LocalDeclarationVisitor();
+ }
+}
+
+public void checkAnnotation() {
+ int firstCommentIndex = scanner.commentPtr;
+
+ super.checkAnnotation();
+
+ // modify the modifier source start to point at the first comment
+ if (firstCommentIndex >= 0) {
+ modifiersSourceStart = scanner.commentStarts[0];
+ }
+}
+
+protected void classInstanceCreation(boolean alwaysQualified) {
+
+ boolean previousFlag = reportReferenceInfo;
+ reportReferenceInfo = false; // not to see the type reference reported in super call to getTypeReference(...)
+ super.classInstanceCreation(alwaysQualified);
+ reportReferenceInfo = previousFlag;
+ if (reportReferenceInfo){
+ AllocationExpression alloc = (AllocationExpression)expressionStack[expressionPtr];
+ TypeReference typeRef = alloc.type;
+ requestor.acceptConstructorReference(
+ typeRef instanceof SingleTypeReference
+ ? ((SingleTypeReference) typeRef).token
+ : CharOperation.concatWith(alloc.type.getTypeName(), '.'),
+ alloc.arguments == null ? 0 : alloc.arguments.length,
+ alloc.sourceStart);
+ }
+}
+protected void consumeConstructorHeaderName() {
+ // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
+
+ /* recovering - might be an empty message send */
+ if (currentElement != null){
+ if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
+ lastCheckPoint = scanner.startPosition; // force to restart at this exact position
+ restartRecovery = true;
+ return;
+ }
+ }
+ SourceConstructorDeclaration cd = new SourceConstructorDeclaration(this.compilationUnit.compilationResult);
+
+ //name -- this is not really revelant but we do .....
+ cd.selector = identifierStack[identifierPtr];
+ long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //modifiers
+ cd.declarationSourceStart = intStack[intPtr--];
+ cd.modifiers = intStack[intPtr--];
+
+ //highlight starts at the selector starts
+ cd.sourceStart = (int) (selectorSourcePositions >>> 32);
+ cd.selectorSourceEnd = (int) selectorSourcePositions;
+ pushOnAstStack(cd);
+
+ cd.sourceEnd = lParenPos;
+ cd.bodyStart = lParenPos+1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = cd.bodyStart;
+ if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
+ || cd.modifiers != 0){
+ currentElement = currentElement.add(cd, 0);
+ lastIgnoredToken = -1;
+ }
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // the scanner is located after the comma or the semi-colon.
+ // we want to include the comma or the semi-colon
+ super.consumeExitVariableWithInitialization();
+ if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+ return;
+ ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+}
+protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+ if (isLocalDeclaration() || ((currentToken != TokenNameCOMMA) && (currentToken != TokenNameSEMICOLON)))
+ return;
+ ((SourceFieldDeclaration) astStack[astPtr]).fieldEndPosition = scanner.currentPosition - 1;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeFieldAccess(boolean isSuperAccess) {
+ // FieldAccess ::= Primary '.' 'Identifier'
+ // FieldAccess ::= 'super' '.' 'Identifier'
+ super.consumeFieldAccess(isSuperAccess);
+ FieldReference fr = (FieldReference) expressionStack[expressionPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptFieldReference(fr.token, fr.sourceStart);
+ }
+}
+protected void consumeMethodHeaderName() {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ SourceMethodDeclaration md = new SourceMethodDeclaration(this.compilationUnit.compilationResult);
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ long selectorSourcePositions = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(intStack[intPtr--]);
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSourcePositions >>> 32);
+ md.selectorSourceEnd = (int) selectorSourcePositions;
+ pushOnAstStack(md);
+ md.sourceEnd = lParenPos;
+ md.bodyStart = lParenPos+1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ // recovery
+ if (currentElement != null){
+ if (currentElement instanceof RecoveredType
+ //|| md.modifiers != 0
+ || (scanner.getLineNumber(md.returnType.sourceStart)
+ == scanner.getLineNumber(md.sourceStart))){
+ lastCheckPoint = md.bodyStart;
+ currentElement = currentElement.add(md, 0);
+ lastIgnoredToken = -1;
+ } else {
+ lastCheckPoint = md.sourceStart;
+ restartRecovery = true;
+ }
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationName() {
+ // MethodInvocation ::= Name '(' ArgumentListopt ')'
+
+ // when the name is only an identifier...we have a message send to "this" (implicit)
+ super.consumeMethodInvocationName();
+ MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+ Expression[] args = messageSend.arguments;
+ if (reportReferenceInfo) {
+ requestor.acceptMethodReference(
+ messageSend.selector,
+ args == null ? 0 : args.length,
+ (int)(messageSend.nameSourcePosition >>> 32));
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationPrimary() {
+ super.consumeMethodInvocationPrimary();
+ MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+ Expression[] args = messageSend.arguments;
+ if (reportReferenceInfo) {
+ requestor.acceptMethodReference(
+ messageSend.selector,
+ args == null ? 0 : args.length,
+ (int)(messageSend.nameSourcePosition >>> 32));
+ }
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void consumeMethodInvocationSuper() {
+ // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
+ super.consumeMethodInvocationSuper();
+ MessageSend messageSend = (MessageSend) expressionStack[expressionPtr];
+ Expression[] args = messageSend.arguments;
+ if (reportReferenceInfo) {
+ requestor.acceptMethodReference(
+ messageSend.selector,
+ args == null ? 0 : args.length,
+ (int)(messageSend.nameSourcePosition >>> 32));
+ }
+}
+protected void consumeSingleTypeImportDeclarationName() {
+ // SingleTypeImportDeclarationName ::= 'import' Name
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ super.consumeSingleTypeImportDeclarationName();
+ ImportReference impt = (ImportReference)astStack[astPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
+ }
+}
+protected void consumeTypeImportOnDemandDeclarationName() {
+ // TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ super.consumeTypeImportOnDemandDeclarationName();
+ ImportReference impt = (ImportReference)astStack[astPtr];
+ if (reportReferenceInfo) {
+ requestor.acceptUnknownReference(impt.tokens, impt.sourceStart, impt.sourceEnd);
+ }
+}
+protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+ return new SourceFieldDeclaration(null, name, sourceStart, sourceEnd);
+}
+protected CompilationUnitDeclaration endParse(int act) {
+ if (sourceType != null) {
+ if (sourceType.isInterface()) {
+ consumeInterfaceDeclaration();
+ } else {
+ consumeClassDeclaration();
+ }
+ }
+ if (compilationUnit != null) {
+ CompilationUnitDeclaration result = super.endParse(act);
+ return result;
+ } else {
+ return null;
+ }
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+ return lastFieldEndPosition = super.flushAnnotationsDefinedPriorTo(position);
+}
+public TypeReference getTypeReference(int dim) {
+ /* build a Reference on a variable that may be qualified or not
+ * This variable is a type reference and dim will be its dimensions
+ */
+ int length;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ SingleTypeReference ref =
+ new SingleTypeReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.token, ref.sourceStart);
+ }
+ return ref;
+ } else {
+ ArrayTypeReference ref =
+ new ArrayTypeReference(
+ identifierStack[identifierPtr],
+ dim,
+ identifierPositionStack[identifierPtr--]);
+ ref.sourceEnd = endPosition;
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.token, ref.sourceStart);
+ }
+ return ref;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ TypeReference ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[intPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[intPtr--];
+ } else {
+ intPtr--; // no need to use this position as it is an array
+ ref.sourceEnd = endPosition;
+ }
+ if (reportReferenceInfo){
+ requestor.acceptTypeReference(ref.getTypeName(), ref.sourceStart, ref.sourceEnd);
+ }
+ return ref;
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
+ }
+ return ref;
+ } else {
+ ArrayQualifiedTypeReference ref =
+ new ArrayQualifiedTypeReference(tokens, dim, positions);
+ ref.sourceEnd = endPosition;
+ if (reportReferenceInfo) {
+ requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
+ }
+ return ref;
+ }
+ }
+ }
+}
+public NameReference getUnspecifiedReference() {
+ /* build a (unspecified) NameReference which may be qualified*/
+
+ int length;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ SingleNameReference ref =
+ new SingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ return ref;
+ } else {
+ //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ QualifiedNameReference ref =
+ new QualifiedNameReference(
+ tokens,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
+ (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ return ref;
+ }
+}
+public 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;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ SingleNameReference ref =
+ new SingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ ref.bits &= ~AstNode.RestrictiveFlagMASK;
+ ref.bits |= LOCAL | FIELD;
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ 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][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ QualifiedNameReference ref =
+ new QualifiedNameReference(
+ tokens,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32),
+ // sourceStart
+ (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+ ref.bits &= ~AstNode.RestrictiveFlagMASK;
+ ref.bits |= LOCAL | FIELD;
+ if (reportReferenceInfo) {
+ this.addUnknownRef(ref);
+ }
+ return ref;
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+private boolean isLocalDeclaration() {
+ int nestedDepth = nestedType;
+ while (nestedDepth >= 0) {
+ if (nestedMethod[nestedDepth] != 0) {
+ return true;
+ }
+ nestedDepth--;
+ }
+ return false;
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor(CompilationUnitDeclaration parsedUnit) {
+ if (parsedUnit == null) {
+ // when we parse a single type member declaration the compilation unit is null, but we still
+ // want to be able to notify the requestor on the created ast node
+ if (astStack[0] instanceof AbstractMethodDeclaration) {
+ notifySourceElementRequestor((AbstractMethodDeclaration) astStack[0]);
+ return;
+ }
+ return;
+ }
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= parsedUnit.sourceStart
+ && scanner.eofPosition >= parsedUnit.sourceEnd;
+
+ if (reportReferenceInfo) {
+ notifyAllUnknownReferences();
+ }
+ // collect the top level ast nodes
+ int length = 0;
+ AstNode[] nodes = null;
+ if (sourceType == null){
+ if (isInRange) {
+ requestor.enterCompilationUnit();
+ }
+ ImportReference currentPackage = parsedUnit.currentPackage;
+ ImportReference[] imports = parsedUnit.imports;
+ TypeDeclaration[] types = parsedUnit.types;
+ length =
+ (currentPackage == null ? 0 : 1)
+ + (imports == null ? 0 : imports.length)
+ + (types == null ? 0 : types.length);
+ nodes = new AstNode[length];
+ int index = 0;
+ if (currentPackage != null) {
+ nodes[index++] = currentPackage;
+ }
+ if (imports != null) {
+ for (int i = 0, max = imports.length; i < max; i++) {
+ nodes[index++] = imports[i];
+ }
+ }
+ if (types != null) {
+ for (int i = 0, max = types.length; i < max; i++) {
+ nodes[index++] = types[i];
+ }
+ }
+ } else {
+ TypeDeclaration[] types = parsedUnit.types;
+ if (types != null) {
+ length = types.length;
+ nodes = new AstNode[length];
+ for (int i = 0, max = types.length; i < max; i++) {
+ nodes[i] = types[i];
+ }
+ }
+ }
+
+ // notify the nodes in the syntactical order
+ if (nodes != null && length > 0) {
+ quickSort(nodes, 0, length-1);
+ for (int i=0;i<length;i++) {
+ AstNode node = nodes[i];
+ if (node instanceof ImportReference) {
+ ImportReference importRef = (ImportReference)node;
+ if (node == parsedUnit.currentPackage) {
+ notifySourceElementRequestor(importRef, true);
+ } else {
+ notifySourceElementRequestor(importRef, false);
+ }
+ } else { // instanceof TypeDeclaration
+ notifySourceElementRequestor((TypeDeclaration)node, sourceType == null);
+ }
+ }
+ }
+
+ if (sourceType == null){
+ if (isInRange) {
+ requestor.exitCompilationUnit(parsedUnit.sourceEnd);
+ }
+ }
+}
+
+private void notifyAllUnknownReferences() {
+ for (int i = 0, max = this.unknownRefsCounter; i < max; i++) {
+ NameReference nameRef = this.unknownRefs[i];
+ if ((nameRef.bits & BindingIds.VARIABLE) != 0) {
+ if ((nameRef.bits & BindingIds.TYPE) == 0) {
+ // variable but not type
+ if (nameRef instanceof SingleNameReference) {
+ // local var or field
+ requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+ } else {
+ // QualifiedNameReference
+ // The last token is a field reference and the previous tokens are a type/variable references
+ char[][] tokens = ((QualifiedNameReference) nameRef).tokens;
+ int tokensLength = tokens.length;
+ requestor.acceptFieldReference(tokens[tokensLength - 1], nameRef.sourceEnd - tokens[tokensLength - 1].length + 1);
+ char[][] typeRef = new char[tokensLength - 1][];
+ System.arraycopy(tokens, 0, typeRef, 0, tokensLength - 1);
+ requestor.acceptUnknownReference(typeRef, nameRef.sourceStart, nameRef.sourceEnd - tokens[tokensLength - 1].length);
+ }
+ } else {
+ // variable or type
+ if (nameRef instanceof SingleNameReference) {
+ requestor.acceptUnknownReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+ } else {
+ //QualifiedNameReference
+ requestor.acceptUnknownReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
+ }
+ }
+ } else if ((nameRef.bits & BindingIds.TYPE) != 0) {
+ if (nameRef instanceof SingleNameReference) {
+ requestor.acceptTypeReference(((SingleNameReference) nameRef).token, nameRef.sourceStart);
+ } else {
+ // it is a QualifiedNameReference
+ requestor.acceptTypeReference(((QualifiedNameReference) nameRef).tokens, nameRef.sourceStart, nameRef.sourceEnd);
+ }
+ }
+ }
+}
+/*
+ * Update the bodyStart of the corresponding parse node
+ */
+public void notifySourceElementRequestor(AbstractMethodDeclaration methodDeclaration) {
+
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= methodDeclaration.declarationSourceStart
+ && scanner.eofPosition >= methodDeclaration.declarationSourceEnd;
+
+ if (methodDeclaration.isClinit()) {
+ this.visitIfNeeded(methodDeclaration);
+ return;
+ }
+
+ if (methodDeclaration.isDefaultConstructor()) {
+ if (reportReferenceInfo) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+ ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+ if (constructorCall != null) {
+ switch(constructorCall.accessMode) {
+ case ExplicitConstructorCall.This :
+ requestor.acceptConstructorReference(
+ typeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ case ExplicitConstructorCall.Super :
+ case ExplicitConstructorCall.ImplicitSuper :
+ requestor.acceptConstructorReference(
+ superTypeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ }
+ }
+ }
+ return;
+ }
+ char[][] argumentTypes = null;
+ char[][] argumentNames = null;
+ Argument[] arguments = methodDeclaration.arguments;
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ argumentTypes = new char[argumentLength][];
+ argumentNames = new char[argumentLength][];
+ for (int i = 0; i < argumentLength; i++) {
+ argumentTypes[i] = returnTypeName(arguments[i].type);
+ argumentNames[i] = arguments[i].name;
+ }
+ }
+ char[][] thrownExceptionTypes = null;
+ TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
+ if (thrownExceptions != null) {
+ int thrownExceptionLength = thrownExceptions.length;
+ thrownExceptionTypes = new char[thrownExceptionLength][];
+ for (int i = 0; i < thrownExceptionLength; i++) {
+ thrownExceptionTypes[i] =
+ CharOperation.concatWith(thrownExceptions[i].getTypeName(), '.');
+ }
+ }
+ // by default no selector end position
+ int selectorSourceEnd = -1;
+ if (methodDeclaration.isConstructor()) {
+ if (methodDeclaration instanceof SourceConstructorDeclaration) {
+ selectorSourceEnd =
+ ((SourceConstructorDeclaration) methodDeclaration).selectorSourceEnd;
+ }
+ if (isInRange){
+ requestor.enterConstructor(
+ methodDeclaration.declarationSourceStart,
+ methodDeclaration.modifiers,
+ methodDeclaration.selector,
+ methodDeclaration.sourceStart,
+ selectorSourceEnd,
+ argumentTypes,
+ argumentNames,
+ thrownExceptionTypes);
+ }
+ if (reportReferenceInfo) {
+ ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) methodDeclaration;
+ ExplicitConstructorCall constructorCall = constructorDeclaration.constructorCall;
+ if (constructorCall != null) {
+ switch(constructorCall.accessMode) {
+ case ExplicitConstructorCall.This :
+ requestor.acceptConstructorReference(
+ typeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ case ExplicitConstructorCall.Super :
+ case ExplicitConstructorCall.ImplicitSuper :
+ requestor.acceptConstructorReference(
+ superTypeNames[nestedTypeIndex-1],
+ constructorCall.arguments == null ? 0 : constructorCall.arguments.length,
+ constructorCall.sourceStart);
+ break;
+ }
+ }
+ }
+ this.visitIfNeeded(methodDeclaration);
+ if (isInRange){
+ requestor.exitConstructor(methodDeclaration.declarationSourceEnd);
+ }
+ return;
+ }
+ if (methodDeclaration instanceof SourceMethodDeclaration) {
+ selectorSourceEnd =
+ ((SourceMethodDeclaration) methodDeclaration).selectorSourceEnd;
+ }
+ if (isInRange){
+ requestor.enterMethod(
+ methodDeclaration.declarationSourceStart,
+ methodDeclaration.modifiers & AccJustFlag,
+ returnTypeName(((MethodDeclaration) methodDeclaration).returnType),
+ methodDeclaration.selector,
+ methodDeclaration.sourceStart,
+ selectorSourceEnd,
+ argumentTypes,
+ argumentNames,
+ thrownExceptionTypes);
+ }
+ this.visitIfNeeded(methodDeclaration);
+
+ if (isInRange){
+ requestor.exitMethod(methodDeclaration.declarationSourceEnd);
+ }
+}
+/*
+* Update the bodyStart of the corresponding parse node
+*/
+public void notifySourceElementRequestor(FieldDeclaration fieldDeclaration) {
+
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= fieldDeclaration.declarationSourceStart
+ && scanner.eofPosition >= fieldDeclaration.declarationSourceEnd;
+
+ if (fieldDeclaration.isField()) {
+ int fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+ if (fieldDeclaration instanceof SourceFieldDeclaration) {
+ fieldEndPosition = ((SourceFieldDeclaration) fieldDeclaration).fieldEndPosition;
+ if (fieldEndPosition == 0) {
+ // use the declaration source end by default
+ fieldEndPosition = fieldDeclaration.declarationSourceEnd;
+ }
+ }
+ if (isInRange) {
+ requestor.enterField(
+ fieldDeclaration.declarationSourceStart,
+ fieldDeclaration.modifiers & AccJustFlag,
+ returnTypeName(fieldDeclaration.type),
+ fieldDeclaration.name,
+ fieldDeclaration.sourceStart,
+ fieldDeclaration.sourceEnd);
+ }
+ this.visitIfNeeded(fieldDeclaration);
+ if (isInRange){
+ requestor.exitField(fieldEndPosition);
+ }
+
+ } else {
+ if (isInRange){
+ requestor.enterInitializer(
+ fieldDeclaration.declarationSourceStart,
+ fieldDeclaration.modifiers);
+ }
+ this.visitIfNeeded((Initializer)fieldDeclaration);
+ if (isInRange){
+ requestor.exitInitializer(fieldDeclaration.declarationSourceEnd);
+ }
+ }
+}
+public void notifySourceElementRequestor(
+ ImportReference importReference,
+ boolean isPackage) {
+ if (isPackage) {
+ requestor.acceptPackage(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ CharOperation.concatWith(importReference.getImportName(), '.'));
+ } else {
+ requestor.acceptImport(
+ importReference.declarationSourceStart,
+ importReference.declarationSourceEnd,
+ CharOperation.concatWith(importReference.getImportName(), '.'),
+ importReference.onDemand);
+ }
+}
+public void notifySourceElementRequestor(TypeDeclaration typeDeclaration, boolean notifyTypePresence) {
+
+ // range check
+ boolean isInRange =
+ scanner.initialPosition <= typeDeclaration.declarationSourceStart
+ && scanner.eofPosition >= typeDeclaration.declarationSourceEnd;
+
+ FieldDeclaration[] fields = typeDeclaration.fields;
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+ MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
+ int fieldCount = fields == null ? 0 : fields.length;
+ int methodCount = methods == null ? 0 : methods.length;
+ int memberTypeCount = memberTypes == null ? 0 : memberTypes.length;
+ int fieldIndex = 0;
+ int methodIndex = 0;
+ int memberTypeIndex = 0;
+ boolean isInterface = typeDeclaration.isInterface();
+
+ if (notifyTypePresence){
+ char[][] interfaceNames = null;
+ int superInterfacesLength = 0;
+ TypeReference[] superInterfaces = typeDeclaration.superInterfaces;
+ if (superInterfaces != null) {
+ superInterfacesLength = superInterfaces.length;
+ interfaceNames = new char[superInterfacesLength][];
+ } else {
+ if (typeDeclaration instanceof AnonymousLocalTypeDeclaration) {
+ // see PR 3442
+ QualifiedAllocationExpression alloc = ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation;
+ if (alloc != null && alloc.type != null) {
+ superInterfaces = new TypeReference[] { ((AnonymousLocalTypeDeclaration)typeDeclaration).allocation.type};
+ superInterfacesLength = 1;
+ interfaceNames = new char[1][];
+ }
+ }
+ }
+ if (superInterfaces != null) {
+ for (int i = 0; i < superInterfacesLength; i++) {
+ interfaceNames[i] =
+ CharOperation.concatWith(superInterfaces[i].getTypeName(), '.');
+ }
+ }
+ if (isInterface) {
+ if (isInRange){
+ requestor.enterInterface(
+ typeDeclaration.declarationSourceStart,
+ typeDeclaration.modifiers & AccJustFlag,
+ typeDeclaration.name,
+ typeDeclaration.sourceStart,
+ typeDeclaration.sourceEnd,
+ interfaceNames);
+ }
+ if (nestedTypeIndex == typeNames.length) {
+ // need a resize
+ System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ }
+ typeNames[nestedTypeIndex] = typeDeclaration.name;
+ superTypeNames[nestedTypeIndex++] = JAVA_LANG_OBJECT;
+ } else {
+ TypeReference superclass = typeDeclaration.superclass;
+ if (superclass == null) {
+ if (isInRange){
+ requestor.enterClass(
+ typeDeclaration.declarationSourceStart,
+ typeDeclaration.modifiers,
+ typeDeclaration.name,
+ typeDeclaration.sourceStart,
+ typeDeclaration.sourceEnd,
+ null,
+ interfaceNames);
+ }
+ } else {
+ if (isInRange){
+ requestor.enterClass(
+ typeDeclaration.declarationSourceStart,
+ typeDeclaration.modifiers,
+ typeDeclaration.name,
+ typeDeclaration.sourceStart,
+ typeDeclaration.sourceEnd,
+ CharOperation.concatWith(superclass.getTypeName(), '.'),
+ interfaceNames);
+ }
+ }
+ if (nestedTypeIndex == typeNames.length) {
+ // need a resize
+ System.arraycopy(typeNames, 0, (typeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ System.arraycopy(superTypeNames, 0, (superTypeNames = new char[nestedTypeIndex * 2][]), 0, nestedTypeIndex);
+ }
+ typeNames[nestedTypeIndex] = typeDeclaration.name;
+ superTypeNames[nestedTypeIndex++] = superclass == null ? JAVA_LANG_OBJECT : CharOperation.concatWith(superclass.getTypeName(), '.');
+ }
+ }
+ while ((fieldIndex < fieldCount)
+ || (memberTypeIndex < memberTypeCount)
+ || (methodIndex < methodCount)) {
+ FieldDeclaration nextFieldDeclaration = null;
+ AbstractMethodDeclaration nextMethodDeclaration = null;
+ TypeDeclaration nextMemberDeclaration = null;
+
+ int position = Integer.MAX_VALUE;
+ int nextDeclarationType = -1;
+ if (fieldIndex < fieldCount) {
+ nextFieldDeclaration = fields[fieldIndex];
+ if (nextFieldDeclaration.declarationSourceStart < position) {
+ position = nextFieldDeclaration.declarationSourceStart;
+ nextDeclarationType = 0; // FIELD
+ }
+ }
+ if (methodIndex < methodCount) {
+ nextMethodDeclaration = methods[methodIndex];
+ if (nextMethodDeclaration.declarationSourceStart < position) {
+ position = nextMethodDeclaration.declarationSourceStart;
+ nextDeclarationType = 1; // METHOD
+ }
+ }
+ if (memberTypeIndex < memberTypeCount) {
+ nextMemberDeclaration = memberTypes[memberTypeIndex];
+ if (nextMemberDeclaration.declarationSourceStart < position) {
+ position = nextMemberDeclaration.declarationSourceStart;
+ nextDeclarationType = 2; // MEMBER
+ }
+ }
+ switch (nextDeclarationType) {
+ case 0 :
+ fieldIndex++;
+ notifySourceElementRequestor(nextFieldDeclaration);
+ break;
+ case 1 :
+ methodIndex++;
+ notifySourceElementRequestor(nextMethodDeclaration);
+ break;
+ case 2 :
+ memberTypeIndex++;
+ notifySourceElementRequestor(nextMemberDeclaration, true);
+ }
+ }
+ if (notifyTypePresence){
+ if (isInRange){
+ if (isInterface) {
+ requestor.exitInterface(typeDeclaration.declarationSourceEnd);
+ } else {
+ requestor.exitClass(typeDeclaration.declarationSourceEnd);
+ }
+ }
+ nestedTypeIndex--;
+ }
+}
+public void parseCompilationUnit(
+ ICompilationUnit unit,
+ int start,
+ int end,
+ boolean needReferenceInfo) {
+
+ reportReferenceInfo = needReferenceInfo;
+ boolean old = diet;
+ if (needReferenceInfo) {
+ unknownRefs = new NameReference[10];
+ unknownRefsCounter = 0;
+ }
+ try {
+ diet = true;
+ CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
+ CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult, start, end);
+ if (needReferenceInfo){
+ diet = false;
+ this.getMethodBodies(parsedUnit);
+ }
+ this.scanner.resetTo(start, end);
+ notifySourceElementRequestor(parsedUnit);
+ } catch (AbortCompilation e) {
+ } finally {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+ }
+ diet = old;
+ }
+}
+public void parseCompilationUnit(
+ ICompilationUnit unit,
+ boolean needReferenceInfo) {
+ boolean old = diet;
+ if (needReferenceInfo) {
+ unknownRefs = new NameReference[10];
+ unknownRefsCounter = 0;
+ }
+
+ try {
+/* diet = !needReferenceInfo;
+ reportReferenceInfo = needReferenceInfo;
+ CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0);
+ parse(unit, compilationUnitResult);
+*/ diet = true;
+ reportReferenceInfo = needReferenceInfo;
+ CompilationResult compilationUnitResult = new CompilationResult(unit, 0, 0, this.options.maxProblemsPerUnit);
+ CompilationUnitDeclaration parsedUnit = parse(unit, compilationUnitResult);
+ int initialStart = this.scanner.initialPosition;
+ int initialEnd = this.scanner.eofPosition;
+ if (needReferenceInfo){
+ diet = false;
+ this.getMethodBodies(parsedUnit);
+ }
+ this.scanner.resetTo(initialStart, initialEnd);
+ notifySourceElementRequestor(parsedUnit);
+ } catch (AbortCompilation e) {
+ } finally {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+ }
+ diet = old;
+ }
+}
+public void parseTypeMemberDeclarations(
+ ISourceType sourceType,
+ ICompilationUnit sourceUnit,
+ int start,
+ int end,
+ boolean needReferenceInfo) {
+ boolean old = diet;
+ if (needReferenceInfo) {
+ unknownRefs = new NameReference[10];
+ unknownRefsCounter = 0;
+ }
+
+ try {
+ diet = !needReferenceInfo;
+ reportReferenceInfo = needReferenceInfo;
+ CompilationResult compilationUnitResult =
+ new CompilationResult(sourceUnit, 0, 0, this.options.maxProblemsPerUnit);
+ CompilationUnitDeclaration unit =
+ SourceTypeConverter.buildCompilationUnit(
+ new ISourceType[]{sourceType},
+ false,
+ false,
+ problemReporter(),
+ compilationUnitResult);
+ if ((unit == null) || (unit.types == null) || (unit.types.length != 1))
+ return;
+ this.sourceType = sourceType;
+ try {
+ /* automaton initialization */
+ initialize();
+ goForClassBodyDeclarations();
+ /* scanner initialization */
+ scanner.setSource(sourceUnit.getContents());
+ scanner.resetTo(start, end);
+ /* unit creation */
+ referenceContext = compilationUnit = unit;
+ /* initialize the astStacl */
+ // the compilationUnitDeclaration should contain exactly one type
+ pushOnAstStack(unit.types[0]);
+ /* run automaton */
+ parse();
+ notifySourceElementRequestor(unit);
+ } finally {
+ unit = compilationUnit;
+ compilationUnit = null; // reset parser
+ }
+ } catch (AbortCompilation e) {
+ } finally {
+ if (scanner.recordLineSeparator) {
+ requestor.acceptLineSeparatorPositions(scanner.getLineEnds());
+ }
+ diet = old;
+ }
+}
+
+public void parseTypeMemberDeclarations(
+ char[] contents,
+ int start,
+ int end) {
+
+ boolean old = diet;
+
+ try {
+ diet = true;
+
+ /* automaton initialization */
+ initialize();
+ goForClassBodyDeclarations();
+ /* scanner initialization */
+ scanner.setSource(contents);
+ scanner.recordLineSeparator = false;
+ scanner.resetTo(start, end);
+
+ /* unit creation */
+ referenceContext = null;
+
+ /* initialize the astStacl */
+ // the compilationUnitDeclaration should contain exactly one type
+ /* run automaton */
+ parse();
+ notifySourceElementRequestor((CompilationUnitDeclaration)null);
+ } catch (AbortCompilation e) {
+ } finally {
+ diet = old;
+ }
+}
+/**
+ * Sort the given ast nodes by their positions.
+ */
+private static void quickSort(AstNode[] sortedCollection, int left, int right) {
+ int original_left = left;
+ int original_right = right;
+ AstNode mid = sortedCollection[ (left + right) / 2];
+ do {
+ while (sortedCollection[left].sourceStart < mid.sourceStart) {
+ left++;
+ }
+ while (mid.sourceStart < sortedCollection[right].sourceStart) {
+ right--;
+ }
+ if (left <= right) {
+ AstNode tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right);
+ }
+}
+/*
+ * Answer a char array representation of the type name formatted like:
+ * - type name + dimensions
+ * Example:
+ * "A[][]".toCharArray()
+ * "java.lang.String".toCharArray()
+ */
+private char[] returnTypeName(TypeReference type) {
+ if (type == null)
+ return null;
+ int dimension = type.dimensions();
+ if (dimension != 0) {
+ char[] dimensionsArray = new char[dimension * 2];
+ for (int i = 0; i < dimension; i++) {
+ dimensionsArray[i * 2] = '[';
+ dimensionsArray[(i * 2) + 1] = ']';
+ }
+ return CharOperation.concat(
+ CharOperation.concatWith(type.getTypeName(), '.'),
+ dimensionsArray);
+ }
+ return CharOperation.concatWith(type.getTypeName(), '.');
+}
+
+public void addUnknownRef(NameReference nameRef) {
+ if (this.unknownRefs.length == this.unknownRefsCounter) {
+ // resize
+ System.arraycopy(
+ this.unknownRefs,
+ 0,
+ (this.unknownRefs = new NameReference[this.unknownRefsCounter * 2]),
+ 0,
+ this.unknownRefsCounter);
+ }
+ this.unknownRefs[this.unknownRefsCounter++] = nameRef;
+}
+private TypeReference typeReference(
+ int dim,
+ int localIdentifierPtr,
+ int localIdentifierLengthPtr) {
+ /* build a Reference on a variable that may be qualified or not
+ * This variable is a type reference and dim will be its dimensions.
+ * We don't have any side effect on the stacks' pointers.
+ */
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[localIdentifierLengthPtr]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[localIdentifierPtr],
+ identifierPositionStack[localIdentifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[localIdentifierPtr],
+ dim,
+ identifierPositionStack[localIdentifierPtr--]);
+ ref.sourceEnd = endPosition;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[localIntPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[localIntPtr--];
+ } else {
+ localIntPtr--;
+ ref.sourceEnd = endPosition;
+ }
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ localIdentifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, localIdentifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ localIdentifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ ref = new QualifiedTypeReference(tokens, positions);
+ } else {
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ ref.sourceEnd = endPosition;
+ }
+ }
+ };
+ return ref;
+}
+
+private void visitIfNeeded(AbstractMethodDeclaration method) {
+ if (this.localDeclarationVisitor != null
+ && (method.bits & AstNode.HasLocalTypeMASK) != 0) {
+ if (method.statements != null) {
+ int statementsLength = method.statements.length;
+ for (int i = 0; i < statementsLength; i++)
+ method.statements[i].traverse(this.localDeclarationVisitor, method.scope);
+ }
+ }
+}
+
+private void visitIfNeeded(FieldDeclaration field) {
+ if (this.localDeclarationVisitor != null
+ && (field.bits & AstNode.HasLocalTypeMASK) != 0) {
+ if (field.initialization != null) {
+ field.initialization.traverse(this.localDeclarationVisitor, null);
+ }
+ }
+}
+
+private void visitIfNeeded(Initializer initializer) {
+ if (this.localDeclarationVisitor != null
+ && (initializer.bits & AstNode.HasLocalTypeMASK) != 0) {
+ if (initializer.block != null) {
+ initializer.block.traverse(this.localDeclarationVisitor, null);
+ }
+ }
+}
+
+protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
+ if (compilationUnit == null) return;
+ super.reportSyntaxError(act, currentKind,stateStackTop);
+}
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+
+public class SourceElementRequestorAdapter implements ISourceElementRequestor {
+
+ /*
+ * @see ISourceElementRequestor#acceptConstructorReference(char[], int, int)
+ */
+ public void acceptConstructorReference(
+ char[] typeName,
+ int argCount,
+ int sourcePosition) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptFieldReference(char[], int)
+ */
+ public void acceptFieldReference(char[] fieldName, int sourcePosition) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptImport(int, int, char[], boolean)
+ */
+ public void acceptImport(
+ int declarationStart,
+ int declarationEnd,
+ char[] name,
+ boolean onDemand) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptLineSeparatorPositions(int[])
+ */
+ public void acceptLineSeparatorPositions(int[] positions) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptMethodReference(char[], int, int)
+ */
+ public void acceptMethodReference(
+ char[] methodName,
+ int argCount,
+ int sourcePosition) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptPackage(int, int, char[])
+ */
+ public void acceptPackage(
+ int declarationStart,
+ int declarationEnd,
+ char[] name) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptProblem(IProblem)
+ */
+ public void acceptProblem(IProblem problem) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptTypeReference(char[][], int, int)
+ */
+ public void acceptTypeReference(
+ char[][] typeName,
+ int sourceStart,
+ int sourceEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptTypeReference(char[], int)
+ */
+ public void acceptTypeReference(char[] typeName, int sourcePosition) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptUnknownReference(char[][], int, int)
+ */
+ public void acceptUnknownReference(
+ char[][] name,
+ int sourceStart,
+ int sourceEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#acceptUnknownReference(char[], int)
+ */
+ public void acceptUnknownReference(char[] name, int sourcePosition) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#enterClass(int, int, char[], int, int, char[], char[][])
+ */
+ public void enterClass(
+ int declarationStart,
+ int modifiers,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[] superclass,
+ char[][] superinterfaces) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#enterCompilationUnit()
+ */
+ public void enterCompilationUnit() {
+ }
+
+ /*
+ * @see ISourceElementRequestor#enterConstructor(int, int, char[], int, int, char[][], char[][], char[][])
+ */
+ public void enterConstructor(
+ int declarationStart,
+ int modifiers,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ char[][] exceptionTypes) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#enterField(int, int, char[], char[], int, int)
+ */
+ public void enterField(
+ int declarationStart,
+ int modifiers,
+ char[] type,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#enterInitializer(int, int)
+ */
+ public void enterInitializer(int declarationStart, int modifiers) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#enterInterface(int, int, char[], int, int, char[][])
+ */
+ public void enterInterface(
+ int declarationStart,
+ int modifiers,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[][] superinterfaces) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#enterMethod(int, int, char[], char[], int, int, char[][], char[][], char[][])
+ */
+ public void enterMethod(
+ int declarationStart,
+ int modifiers,
+ char[] returnType,
+ char[] name,
+ int nameSourceStart,
+ int nameSourceEnd,
+ char[][] parameterTypes,
+ char[][] parameterNames,
+ char[][] exceptionTypes) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#exitClass(int)
+ */
+ public void exitClass(int declarationEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#exitCompilationUnit(int)
+ */
+ public void exitCompilationUnit(int declarationEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#exitConstructor(int)
+ */
+ public void exitConstructor(int declarationEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#exitField(int)
+ */
+ public void exitField(int declarationEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#exitInitializer(int)
+ */
+ public void exitInitializer(int declarationEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#exitInterface(int)
+ */
+ public void exitInterface(int declarationEnd) {
+ }
+
+ /*
+ * @see ISourceElementRequestor#exitMethod(int)
+ */
+ public void exitMethod(int declarationEnd) {
+ }
+
+}
+
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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 opConstant = left.conditionalConstant();
+ if (opConstant != NotAConstant) {
+ if (opConstant.booleanValue() == true) {
+ // 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();
+ if (opConstant != NotAConstant && opConstant.booleanValue() == false) rightInfo.markAsFakeReachable(true);
+
+ rightInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(rightInfo);
+ rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
+ FlowInfo mergedInfo =
+ FlowInfo.conditional(
+ rightInfo.initsWhenTrue().copy(),
+ 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;
+ Label falseLabel, endLabel;
+ if (constant != Constant.NotAConstant) {
+ // inlined value
+ if (valueRequired)
+ codeStream.generateConstant(constant, implicitConversion);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ bits |= OnlyValueRequiredMASK;
+ generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ (falseLabel = new Label(codeStream)),
+ valueRequired);
+ /* improving code gen for such a case: boolean b = i < 0 && 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();
+ }
+ }
+ 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;
+ }
+ int pc = codeStream.position;
+ Constant condConst;
+ if ((condConst = left.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // <something equivalent to true> && x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ right.generateCode(currentScope, codeStream, valueRequired);
+ } else {
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ } else {
+ // <something equivalent to false> && x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_0();
+ } else {
+ if (falseLabel != null) {
+ // implicit falling through the TRUE case
+ codeStream.goto_(falseLabel);
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ return;
+ }
+ if ((condConst = right.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // x && <something equivalent to true>
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ left.generateCode(currentScope, codeStream, valueRequired);
+ } else {
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ } else {
+ // x && <something equivalent to false>
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ 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);
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ return;
+ }
+ // default case
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ Label internalFalseLabel = new Label(codeStream);
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ internalFalseLabel,
+ true);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ null,
+ valueRequired);
+ internalFalseLabel.place();
+ }
+ } else {
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ falseLabel,
+ valueRequired);
+ } else {
+ // no implicit fall through TRUE/FALSE --> should never occur
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ }
+
+ public boolean isCompactableOperation() {
+ return false;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor 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
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.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 int bodyStart;
+ public int bodyEnd = -1;
+ public CompilationResult compilationResult;
+
+ AbstractMethodDeclaration(CompilationResult compilationResult){
+ this.compilationResult = compilationResult;
+ }
+
+ /*
+ * We cause the compilation task to abort to a given extent.
+ */
+ public void abort(int abortLevel) {
+
+ if (scope == null) {
+ throw new AbortCompilation(); // cannot do better
+ }
+
+ CompilationResult compilationResult =
+ scope.referenceCompilationUnit().compilationResult;
+
+ switch (abortLevel) {
+ case AbortCompilation :
+ throw new AbortCompilation(compilationResult);
+ case AbortCompilationUnit :
+ throw new AbortCompilationUnit(compilationResult);
+ case AbortType :
+ throw new AbortType(compilationResult);
+ default :
+ throw new AbortMethod(compilationResult);
+ }
+ }
+
+ public void analyseCode(
+ ClassScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ // starting of the code analysis for methods
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ if (binding == null)
+ return;
+ // may be in a non necessary <clinit> for innerclass with static final constant fields
+ if (binding.isAbstract() || binding.isNative())
+ return;
+
+ ExceptionHandlingFlowContext methodContext =
+ new ExceptionHandlingFlowContext(
+ flowContext,
+ this,
+ binding.thrownExceptions,
+ scope,
+ FlowInfo.DeadEnd);
+
+ // propagate to statements
+ if (statements != null) {
+ for (int i = 0, count = statements.length; i < count; i++) {
+ Statement stat;
+ if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
+ flowInfo = stat.analyseCode(scope, methodContext, flowInfo);
+ }
+ }
+ }
+ // check for missing returning path
+ TypeBinding returnType = binding.returnType;
+ if ((returnType == VoidBinding) || isAbstract()) {
+ needFreeReturn =
+ !((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable());
+ } else {
+ if (flowInfo != FlowInfo.DeadEnd) {
+ // special test for empty methods that should return something
+ if ((statements == null) && (returnType != VoidBinding)) {
+ scope.problemReporter().shouldReturn(returnType, this);
+ } else {
+ scope.problemReporter().shouldReturn(
+ returnType,
+ statements[statements.length - 1]);
+ }
+ }
+ }
+ } catch (AbortMethod e) {
+ this.ignoreFurtherInvestigation = true;
+ }
+ }
+
+ /**
+ * Bind and add argument's binding into the scope of the method
+ */
+ public void bindArguments() {
+
+ if (arguments != null) {
+ // by default arguments in abstract/native methods are considered to be used (no complaint is expected)
+ boolean used = binding == null || binding.isAbstract() || binding.isNative();
+
+ int length = arguments.length;
+ for (int i = 0; i < length; i++) {
+ TypeBinding argType = binding == null ? null : binding.parameters[i];
+ arguments[i].bind(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 length = this.binding.thrownExceptions.length;
+ for (int i = 0; i < length; i++) {
+ this.thrownExceptions[i].binding = this.binding.thrownExceptions[i];
+ }
+ }
+ }
+
+ public CompilationResult compilationResult() {
+
+ return this.compilationResult;
+ }
+
+ /**
+ * Bytecode generation for a method
+ */
+ public void generateCode(ClassScope classScope, ClassFile classFile) {
+
+ int problemResetPC = 0;
+ classFile.codeStream.wideMode = false; // reset wideMode to false
+ if (ignoreFurtherInvestigation) {
+ // method is known to have errors, dump a problem method
+ if (this.binding == null)
+ return; // handle methods with invalid signature or duplicates
+ int problemsLength;
+ IProblem[] problems =
+ scope.referenceCompilationUnit().compilationResult.getProblems();
+ IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+ System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+ classFile.addProblemMethod(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 {
+ this.traverse(new ResetStateForCodeGenerationVisitor(), classScope);
+ 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 =
+ scope.referenceCompilationUnit().compilationResult.getProblems();
+ IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+ System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+ classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC);
+ }
+ } else {
+ // produce a problem method accounting for this fatal error
+ int problemsLength;
+ IProblem[] problems =
+ scope.referenceCompilationUnit().compilationResult.getProblems();
+ IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+ System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+ classFile.addProblemMethod(this, binding, problemsCopy, problemResetPC);
+ }
+ }
+ }
+
+ private void generateCode(ClassFile classFile) {
+
+ classFile.generateMethodInfoHeader(binding);
+ int methodAttributeOffset = classFile.contentsOffset;
+ int attributeNumber = classFile.generateMethodInfoAttribute(binding);
+ if ((!binding.isNative()) && (!binding.isAbstract())) {
+ int codeAttributeOffset = classFile.contentsOffset;
+ classFile.generateCodeAttributeHeader();
+ CodeStream codeStream = classFile.codeStream;
+ codeStream.reset(this, classFile);
+ // initialize local positions
+ scope.computeLocalVariablePositions(binding.isStatic() ? 0 : 1, codeStream);
+
+ // arguments initialization for local variable debug attributes
+ if (arguments != null) {
+ for (int i = 0, max = arguments.length; i < max; i++) {
+ LocalVariableBinding argBinding;
+ codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding);
+ argBinding.recordInitializationStartPC(0);
+ }
+ }
+ if (statements != null) {
+ for (int i = 0, max = statements.length; i < max; i++)
+ statements[i].generateCode(scope, codeStream);
+ }
+ if (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);
+ }
+ }
+
+ public boolean hasErrors() {
+ return this.ignoreFurtherInvestigation;
+ }
+
+ public boolean isAbstract() {
+
+ if (binding != null)
+ return binding.isAbstract();
+ return (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 (binding != null)
+ return binding.isNative();
+ return (modifiers & AccNative) != 0;
+ }
+
+ public boolean isStatic() {
+
+ if (binding != null)
+ return binding.isStatic();
+ return (modifiers & AccStatic) != 0;
+ }
+
+ /**
+ * Fill up the method body with statement
+ */
+ public abstract void parseStatements(
+ Parser parser,
+ CompilationUnitDeclaration unit);
+
+ public void resolve(ClassScope upperScope) {
+
+ if (binding == null) {
+ ignoreFurtherInvestigation = true;
+ }
+
+ try {
+ bindArguments();
+ bindThrownExceptions();
+ resolveStatements(upperScope);
+ } catch (AbortMethod e) { // ========= abort on fatal error =============
+ this.ignoreFurtherInvestigation = true;
+ }
+ }
+
+ public void resolveStatements(ClassScope upperScope) {
+
+ if (statements != null) {
+ int i = 0, length = statements.length;
+ while (i < length)
+ statements[i++].resolve(scope);
+ }
+ }
+
+ public String returnTypeToString(int tab) {
+
+ return ""; //$NON-NLS-1$
+ }
+
+ public void tagAsHavingErrors() {
+
+ ignoreFurtherInvestigation = true;
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ if (modifiers != AccDefault) {
+ s += modifiersString(modifiers);
+ }
+
+ s += returnTypeToString(0);
+ s += new String(selector) + "("; //$NON-NLS-1$
+ if (arguments != null) {
+ for (int i = 0; i < arguments.length; i++) {
+ s += arguments[i].toString(0);
+ if (i != (arguments.length - 1))
+ s = s + ", "; //$NON-NLS-1$
+ };
+ };
+ s += ")"; //$NON-NLS-1$
+ if (thrownExceptions != null) {
+ s += " throws "; //$NON-NLS-1$
+ for (int i = 0; i < thrownExceptions.length; i++) {
+ s += thrownExceptions[i].toString(0);
+ if (i != (thrownExceptions.length - 1))
+ s = s + ", "; //$NON-NLS-1$
+ };
+ };
+
+ s += toStringStatements(tab + 1);
+ return s;
+ }
+
+ public String toStringStatements(int tab) {
+
+ if (isAbstract() || (this.modifiers & AccSemicolonBody) != 0)
+ return ";"; //$NON-NLS-1$
+
+ String s = " {"; //$NON-NLS-1$
+ if (statements != null) {
+ for (int i = 0; i < statements.length; i++) {
+ s = s + "\n" + statements[i].toString(tab); //$NON-NLS-1$
+ if (!(statements[i] instanceof Block)) {
+ s += ";"; //$NON-NLS-1$
+ }
+ }
+ }
+ s += "\n" + tabString(tab == 0 ? 0 : tab - 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ ClassScope classScope) {
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+public abstract class AbstractVariableDeclaration extends Statement {
+ public int modifiers;
+
+ public TypeReference type;
+ public Expression initialization;
+
+ public char[] name;
+ public int declarationEnd;
+ public int declarationSourceStart;
+ public int declarationSourceEnd;
+ public int modifiersSourceStart;
+ public AbstractVariableDeclaration() {
+ }
+ public abstract String name();
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ if (modifiers != AccDefault) {
+ s += modifiersString(modifiers);
+ }
+ s += type.toString(0) + " " + new String(name()); //$NON-NLS-1$
+ if (initialization != null)
+ s += " = " + initialization.toStringExpression(tab); //$NON-NLS-1$
+ return s;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class AllocationExpression
+ extends Expression
+ implements InvocationSite {
+
+ public TypeReference type;
+ public Expression[] arguments;
+ public MethodBinding binding;
+
+ MethodBinding syntheticAccessor;
+
+ public AllocationExpression() {
+ super();
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ // must verify that exceptions potentially thrown by this expression are caught in the method
+
+ // 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 = binding.thrownExceptions).length) != 0) {
+ // check exception handling
+ flowContext.checkExceptionHandlers(
+ thrownExceptions,
+ this,
+ flowInfo,
+ currentScope);
+ }
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ manageSyntheticAccessIfNecessary(currentScope);
+ return flowInfo;
+ }
+
+ 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
+ if (allocatedType.isNestedType()) {
+ codeStream.generateSyntheticArgumentValues(
+ 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);
+ }
+ }
+ // 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) {
+
+ 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,
+ false);
+ // request cascade of accesses
+ } else {
+ // locally propagate, since we already now the desired shape for sure
+ currentScope.propagateInnerEmulation(allocatedType, false, false);
+ // request cascade of accesses
+ }
+ }
+ }
+
+ public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+
+ 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);
+ currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ }
+ }
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ // Propagate the type checking to the arguments, and check if the constructor is defined.
+ constant = NotAConstant;
+ TypeBinding typeBinding = type.resolveType(scope);
+ // will check for null after args are resolved
+
+ // buffering the arguments' types
+ TypeBinding[] argumentTypes = NoParameters;
+ if (arguments != null) {
+ boolean argHasError = false;
+ int length = arguments.length;
+ argumentTypes = new TypeBinding[length];
+ for (int i = 0; i < length; i++)
+ if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+ argHasError = true;
+ if (argHasError)
+ return typeBinding;
+ }
+ if (typeBinding == null)
+ return null;
+
+ if (!typeBinding.canBeInstantiated()) {
+ scope.problemReporter().cannotInstantiate(type, typeBinding);
+ return typeBinding;
+ }
+ ReferenceBinding allocatedType = (ReferenceBinding) typeBinding;
+ if (!(binding = scope.getConstructor(allocatedType, argumentTypes, this))
+ .isValidBinding()) {
+ if (binding.declaringClass == null)
+ binding.declaringClass = allocatedType;
+ scope.problemReporter().invalidConstructor(this, binding);
+ return typeBinding;
+ }
+ 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]);
+ return allocatedType;
+ }
+
+ public void setActualReceiverType(ReferenceBinding receiverType) {
+ // ignored
+ }
+
+ public void setDepth(int i) {
+ // ignored
+ }
+
+ public void setFieldIndex(int i) {
+ // ignored
+ }
+
+ public String toStringExpression() {
+
+ String s = "new " + type.toString(0); //$NON-NLS-1$
+ if (arguments == null)
+ s = s + "()"; //$NON-NLS-1$
+ else {
+ s = s + "("; //$NON-NLS-1$
+ for (int i = 0; i < arguments.length; i++) {
+ s = s + arguments[i].toStringExpression();
+ if (i == (arguments.length - 1))
+ s = s + ")"; //$NON-NLS-1$
+ else
+ s = s + ", "; //$NON-NLS-1$
+ }
+ }
+ return s;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+
+public class AnonymousLocalTypeDeclaration extends LocalTypeDeclaration {
+
+ public static final char[] ANONYMOUS_EMPTY_NAME = new char[] {};
+ public QualifiedAllocationExpression allocation;
+
+ public AnonymousLocalTypeDeclaration(CompilationResult compilationResult) {
+ super(compilationResult);
+ modifiers = AccDefault;
+ name = ANONYMOUS_EMPTY_NAME;
+ }
+
+ // use a default name in order to th name lookup
+ // to operate juat like a regular type (which has a name)
+ //without checking systematically if the naem is null ....
+ public MethodBinding createsInternalConstructorWithBinding(MethodBinding inheritedConstructorBinding) {
+
+ //Add to method'set, the default constuctor that just recall the
+ //super constructor with the same arguments
+ String baseName = "$anonymous"; //$NON-NLS-1$
+ TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
+ int argumentsLength = argumentTypes.length;
+ //the constructor
+ ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationResult);
+ cd.selector = new char[] { 'x' }; //no maining
+ cd.sourceStart = sourceStart;
+ cd.sourceEnd = sourceEnd;
+ cd.modifiers = modifiers & AccVisibilityMASK;
+ cd.isDefaultConstructor = true;
+
+ if (argumentsLength > 0) {
+ Argument[] arguments = (cd.arguments = new Argument[argumentsLength]);
+ for (int i = argumentsLength; --i >= 0;) {
+ arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, AccDefault);
+ }
+ }
+
+ //the super call inside the constructor
+ cd.constructorCall =
+ new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+ 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, this, true);
+ cd.bindArguments();
+ cd.constructorCall.resolve(cd.scope);
+
+ if (binding.methods == null) {
+ binding.methods = new MethodBinding[] { cd.binding };
+ } else {
+ MethodBinding[] newMethods;
+ System.arraycopy(
+ binding.methods,
+ 0,
+ newMethods = new MethodBinding[binding.methods.length + 1],
+ 1,
+ binding.methods.length);
+ newMethods[0] = cd.binding;
+ binding.methods = newMethods;
+ }
+ //===================================================
+
+ return cd.binding;
+
+ }
+ public void resolve(BlockScope scope) {
+
+ // scope and binding are provided in updateBindingSuperclass
+ resolve();
+ updateMaxFieldCount();
+ }
+
+ public String toString(int tab) {
+
+ return toStringBody(tab);
+ }
+
+ /**
+ * Iteration for a local anonymous innertype
+ *
+ */
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ if (visitor.visit(this, blockScope)) {
+
+ int fieldsLength;
+ int methodsLength;
+ int memberTypesLength;
+
+ // <superclass> is bound to the actual type from the allocation expression
+ // therefore it has already been iterated at this point.
+
+ if (memberTypes != null) {
+ memberTypesLength = memberTypes.length;
+ for (int i = 0; i < memberTypesLength; i++)
+ memberTypes[i].traverse(visitor, scope);
+ }
+ if (fields != null) {
+ fieldsLength = fields.length;
+ for (int i = 0; i < fieldsLength; i++) {
+ FieldDeclaration field;
+ if ((field = fields[i]).isStatic()) {
+ // local type cannot have static fields
+ } else {
+ field.traverse(visitor, initializerScope);
+ }
+ }
+ }
+ if (methods != null) {
+ methodsLength = methods.length;
+ for (int i = 0; i < methodsLength; i++)
+ methods[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, blockScope);
+ } catch (AbortType e) {
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class Argument extends LocalDeclaration {
+
+ public Argument(char[] name, long posNom, TypeReference tr, int modifiers) {
+
+ super(null, name, (int) (posNom >>> 32), (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.binding = typeBinding;
+ // record the resolved type into the type reference
+ int modifierFlag = this.modifiers;
+ if ((this.binding = scope.duplicateName(this.name)) != null) {
+ //the name already exist....may carry on with the first binding ....
+ scope.problemReporter().redefineArgument(this);
+ } else {
+ scope.addLocalVariable(
+ this.binding =
+ new LocalVariableBinding(this, typeBinding, modifierFlag, true));
+ //true stand for argument instead of just local
+ if (typeBinding != null && isTypeUseDeprecated(typeBinding, scope))
+ scope.problemReporter().deprecatedType(typeBinding, this.type);
+ this.binding.declaration = this;
+ this.binding.used = used;
+ }
+ }
+
+ 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;
+ if ((binding = scope.duplicateName(name)) != null) {
+ // the name already exists....may carry on with the first binding ....
+ scope.problemReporter().redefineArgument(this);
+ return null;
+ }
+ binding = new LocalVariableBinding(this, tb, modifiers, false); // argument decl, but local var (i.e. isArgument = false)
+ scope.addLocalVariable(binding);
+ binding.constant = NotAConstant;
+ return tb;
+ }
+
+ public String toString(int tab) {
+
+ String s = ""; //$NON-NLS-1$
+ if (modifiers != AccDefault) {
+ s += modifiersString(modifiers);
+ }
+ if (type == null) {
+ s += "<no type> "; //$NON-NLS-1$
+ } else {
+ s += type.toString(tab) + " "; //$NON-NLS-1$
+ }
+ s += new String(name);
+ return s;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ if (type != null)
+ type.traverse(visitor, scope);
+ if (initialization != null)
+ initialization.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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;
+
+ public ArrayBinding arrayTb;
+
+ /**
+ * 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);
+ } else {
+ return flowInfo;
+ }
+ }
+
+ /**
+ * Code generation for a array allocation expression
+ */
+ public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
+
+ int pc = codeStream.position;
+ ArrayBinding arrayBinding;
+
+ 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 ((arrayTb.isArrayType())
+ && ((arrayBinding = (ArrayBinding) arrayTb).dimensions == 1)) {
+ // Mono-dimensional array
+ codeStream.newArray(currentScope, arrayBinding);
+ } else {
+ // Multi-dimensional array
+ codeStream.multianewarray(arrayTb, nonNullDimensionsLength);
+ }
+
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ } else {
+ codeStream.pop();
+ }
+
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ 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 referenceTb = type.resolveType(scope);
+ // will check for null after dimensions are checked
+ constant = Constant.NotAConstant;
+ if (referenceTb == VoidBinding) {
+ scope.problemReporter().cannotAllocateVoidArray(this);
+ referenceTb = null; // will return below
+ }
+
+ // check the validity of the dimension syntax (and test for all null dimensions)
+ int lengthDim = -1;
+ for (int i = dimensions.length; --i >= 0;) {
+ if (dimensions[i] != null) {
+ if (lengthDim == -1)
+ lengthDim = i;
+ } else if (
+ lengthDim != -1) {
+ // should not have an empty dimension before an non-empty one
+ scope.problemReporter().incorrectLocationForEmptyDimension(this, i);
+ return null;
+ }
+ }
+ if (referenceTb == null)
+ return null;
+
+ // lengthDim == -1 says if all dimensions are nulled
+ // when an initializer is given, no dimension must be specified
+ if (initializer == null) {
+ if (lengthDim == -1) {
+ scope.problemReporter().mustDefineDimensionsOrInitializer(this);
+ return null;
+ }
+ } else if (lengthDim != -1) {
+ scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
+ return null;
+ }
+
+ // dimensions resolution
+ for (int i = 0; i <= lengthDim; i++) {
+ TypeBinding dimTb = dimensions[i].resolveTypeExpecting(scope, IntBinding);
+ if (dimTb == null)
+ return null;
+ dimensions[i].implicitWidening(IntBinding, dimTb);
+ }
+
+ // building the array binding
+ arrayTb = scope.createArray(referenceTb, dimensions.length);
+
+ // check the initializer
+ if (initializer != null)
+ if ((initializer.resolveTypeExpecting(scope, arrayTb)) != null)
+ initializer.binding = arrayTb;
+ return arrayTb;
+ }
+
+ public String toStringExpression() {
+
+ String s = "new " + type.toString(0); //$NON-NLS-1$
+ for (int i = 0; i < dimensions.length; i++) {
+ if (dimensions[i] == null)
+ s = s + "[]"; //$NON-NLS-1$
+ else
+ s = s + "[" + dimensions[i].toStringExpression() + "]"; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ if (initializer != null)
+ s = s + initializer.toStringExpression();
+ return s;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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_float :
+ case T_long :
+ case T_double :
+ if (expr.constant.doubleValue() != 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.constant != NullConstant.Default) {
+ codeStream.dup();
+ codeStream.generateInlinedValue(i);
+ expr.generateCode(currentScope, codeStream, true);
+ codeStream.arrayAtPut(elementsTypeID, false);
+ }
+ }
+ } else {
+ codeStream.dup();
+ codeStream.generateInlinedValue(i);
+ expr.generateCode(currentScope, codeStream, true);
+ codeStream.arrayAtPut(elementsTypeID, false);
+ }
+ }
+ }
+ if (!valueRequired) {
+ codeStream.pop();
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public TypeBinding resolveTypeExpecting(BlockScope scope, TypeBinding expectedTb) {
+ // Array initializers can only occur on the right hand side of an assignment
+ // expression, therefore the expected type contains the valid information
+ // concerning the type that must be enforced by the elements of the array initializer.
+
+ // this method is recursive... (the test on isArrayType is the stop case)
+
+ 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 String toStringExpression() {
+
+ String s = "{" ; //$NON-NLS-1$
+ if (expressions != null)
+ { int j = 20 ;
+ for (int i = 0 ; i < expressions.length ; i++)
+ { s = s + expressions[i].toStringExpression() + "," ; //$NON-NLS-1$
+ j -- ;
+ if (j == 0)
+ { s = s + "\n "; j = 20;}}}; //$NON-NLS-1$
+ s = s + "}"; //$NON-NLS-1$
+ return s;}
+
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (expressions != null) {
+ int expressionsLength = expressions.length;
+ for (int i = 0; i < expressionsLength; i++)
+ expressions[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.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 (binding != null)
+ return binding;
+ return scope.createArray(scope.getType(tokens), dimensions);
+}
+public String toStringExpression(int tab){
+ /* slow speed */
+
+ String s = super.toStringExpression(tab) ;
+ if (dimensions == 1 ) return s + "[]" ; //$NON-NLS-1$
+ for (int i=1 ; i <= dimensions ; i++)
+ s = s + "[]" ; //$NON-NLS-1$
+ return s ;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class ArrayReference extends Reference {
+
+ public Expression receiver;
+ public Expression position;
+
+ public TypeBinding arrayElementBinding;
+
+ 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();
+ } else {
+ 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);
+ position.generateCode(currentScope, codeStream, true);
+ assignment.expression.generateCode(currentScope, codeStream, true);
+ codeStream.arrayAtPut(arrayElementBinding.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);
+ position.generateCode(currentScope, codeStream, true);
+ codeStream.arrayAt(arrayElementBinding.id);
+ // Generating code for the potential runtime type checking
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ } else {
+ if (arrayElementBinding == LongBinding
+ || arrayElementBinding == 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);
+ position.generateCode(currentScope, codeStream, true);
+ codeStream.dup2();
+ codeStream.arrayAt(arrayElementBinding.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(arrayElementBinding.id, valueRequired);
+ }
+
+ public void generatePostIncrement(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ CompoundAssignment postIncrement,
+ boolean valueRequired) {
+
+ receiver.generateCode(currentScope, codeStream, true);
+ position.generateCode(currentScope, codeStream, true);
+ codeStream.dup2();
+ codeStream.arrayAt(arrayElementBinding.id);
+ if (valueRequired) {
+ if ((arrayElementBinding == LongBinding)
+ || (arrayElementBinding == DoubleBinding)) {
+ codeStream.dup2_x2();
+ } else {
+ codeStream.dup_x2();
+ }
+ }
+ codeStream.generateConstant(
+ postIncrement.expression.constant,
+ implicitConversion);
+ codeStream.sendOperator(postIncrement.operator, arrayElementBinding.id);
+ codeStream.generateImplicitConversion(
+ postIncrement.assignmentImplicitConversion);
+ codeStream.arrayAtPut(arrayElementBinding.id, false);
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ constant = Constant.NotAConstant;
+ TypeBinding arrayTb = receiver.resolveType(scope);
+ if (arrayTb == null)
+ return null;
+ if (!arrayTb.isArrayType()) {
+ scope.problemReporter().referenceMustBeArrayTypeAt(arrayTb, this);
+ return null;
+ }
+ TypeBinding positionTb = position.resolveTypeExpecting(scope, IntBinding);
+ if (positionTb == null)
+ return null;
+ position.implicitWidening(IntBinding, positionTb);
+ return arrayElementBinding = ((ArrayBinding) arrayTb).elementsType(scope);
+ }
+
+ public String toStringExpression() {
+
+ return receiver.toStringExpression() + "[" //$NON-NLS-1$
+ +position.toStringExpression() + "]"; //$NON-NLS-1$
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ receiver.traverse(visitor, scope);
+ position.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class ArrayTypeReference extends SingleTypeReference {
+ public int dimensions;
+/**
+ * ArrayTypeReference constructor comment.
+ * @param source char[]
+ * @param dim int
+ * @param pos int
+ */
+public ArrayTypeReference(char[] source, int dim, long pos) {
+ super(source, pos);
+ dimensions = dim ;
+}
+public ArrayTypeReference(char[] source, TypeBinding tb, int dim, long pos) {
+ super(source, tb, pos);
+ dimensions = dim ;}
+public int dimensions() {
+ return dimensions;
+}
+public TypeBinding getTypeBinding(Scope scope) {
+ if (binding != null)
+ return binding;
+ return scope.createArray(scope.getType(token), dimensions);
+}
+public String toStringExpression(int tab){
+ /* slow speed */
+
+ String s = super.toStringExpression(tab) ;
+ if (dimensions == 1 ) return s + "[]" ; //$NON-NLS-1$
+ for (int i=1 ; i <= dimensions ; i++)
+ s = s + "[]" ; //$NON-NLS-1$
+ return s ;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+
+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) {
+
+ Constant constant = assertExpression.constant;
+ if (constant != NotAConstant && constant.booleanValue() == true) {
+ return flowInfo;
+ }
+
+ preAssertInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
+ FlowInfo assertInfo = flowInfo.copy();
+
+ if (exceptionArgument != null) {
+ assertInfo = exceptionArgument.analyseCode(
+ currentScope,
+ flowContext,
+ assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits())
+ .unconditionalInits();
+ } else {
+ assertInfo = assertExpression.analyseCode(currentScope, flowContext, assertInfo).unconditionalInits();
+ }
+
+ // assertion might throw AssertionError (unchecked), which can have consequences in term of
+ // definitely assigned variables (depending on caught exception in the context)
+ // DISABLED - AssertionError is unchecked, try statements are already protected against these.
+ //flowContext.checkExceptionHandlers(currentScope.getJavaLangAssertionError(), this, assertInfo, currentScope);
+
+ // only retain potential initializations
+ flowInfo.addPotentialInitializationsFrom(assertInfo.unconditionalInits());
+
+ // add the assert support in the clinit
+ manageSyntheticAccessIfNecessary(currentScope);
+
+ return flowInfo;
+ }
+
+ 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);
+ 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){
+ if (exceptionArgumentType.id == T_void){
+ scope.problemReporter().illegalVoidExpression(exceptionArgument);
+ }
+ exceptionArgument.implicitConversion = (exceptionArgumentType.id << 4) + exceptionArgumentType.id;
+ }
+ }
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor 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) {
+
+ // need assertion flag: $assertionsDisabled on outer most source type
+ ClassScope outerMostClassScope = currentScope.outerMostClassScope();
+ SourceTypeBinding sourceTypeBinding = outerMostClassScope.enclosingSourceType();
+ this.assertionSyntheticFieldBinding = sourceTypeBinding.addSyntheticField(this, currentScope);
+
+ // find <clinit> and enable assertion support
+ TypeDeclaration typeDeclaration = outerMostClassScope.referenceType();
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+ for (int i = 0, max = methods.length; i < max; i++) {
+ AbstractMethodDeclaration method = methods[i];
+ if (method.isClinit()) {
+ ((Clinit) method).addSupportForAssertion(assertionSyntheticFieldBinding);
+ break;
+ }
+ }
+ }
+
+ public String toString(int tab) {
+
+ StringBuffer buffer = new StringBuffer(tabString(tab));
+ buffer.append("assert"); //$NON-NLS-1$
+ buffer.append(this.assertExpression);
+ if (this.exceptionArgument != null) {
+ buffer.append(":"); //$NON-NLS-1$
+ buffer.append(this.exceptionArgument);
+ buffer.append(";"); //$NON-NLS-1$
+ }
+ return buffer.toString();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class Assignment extends Expression {
+
+ public Reference lhs;
+ public Expression expression;
+ public TypeBinding lhsType;
+
+ 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 = (Reference) lhs;
+ 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 lhs
+ .analyseAssignment(currentScope, flowContext, flowInfo, this, false)
+ .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;
+ 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);
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ // due to syntax lhs may be only a NameReference, a FieldReference or an ArrayReference
+ constant = NotAConstant;
+ this.lhsType = lhs.resolveType(scope);
+ TypeBinding expressionTb = expression.resolveType(scope);
+ if (this.lhsType == null || expressionTb == null)
+ return null;
+
+ // 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(expressionTb, this.lhsType)
+ || (this.lhsType.isBaseType() && BaseTypeBinding.isWidening(this.lhsType.id, expressionTb.id)))
+ || (scope.areTypesCompatible(expressionTb, this.lhsType))) {
+ expression.implicitWidening(this.lhsType, expressionTb);
+ return this.lhsType;
+ }
+ scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+ expression,
+ expressionTb,
+ this.lhsType);
+ return null;
+ }
+
+ public String toString(int tab) {
+
+ //no () when used as a statement
+ return tabString(tab) + toStringExpressionNoParenthesis();
+ }
+
+ public String toStringExpression() {
+
+ //subclass redefine toStringExpressionNoParenthesis()
+ return "(" + toStringExpressionNoParenthesis() + ")"; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ public String toStringExpressionNoParenthesis() {
+
+ return lhs.toStringExpression() + " " //$NON-NLS-1$
+ + "=" //$NON-NLS-1$
+ + ((expression.constant != null) && (expression.constant != NotAConstant)
+ ? " /*cst:" + expression.constant.toString() + "*/ " //$NON-NLS-1$ //$NON-NLS-2$
+ : " ") //$NON-NLS-1$
+ + expression.toStringExpression();
+ }
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ lhs.traverse(visitor, scope);
+ expression.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+
+public abstract class AstNode implements BaseTypes, CompilerModifiers, TypeConstants, TypeIds {
+
+ public int sourceStart, sourceEnd;
+
+ //some global provision for the hierarchy
+ public final static Constant NotAConstant = Constant.NotAConstant;
+
+ // storage for internal flags (32 bits)
+ public int bits = IsReachableMASK; // reachable by default
+
+ // for operators only
+ // Reach . . . . . . . . . . . . . . . . . O O O O O O V VrR R R R
+ public static final int ReturnTypeIDMASK = 15; // 4 lower bits for operators
+ public static final int ValueForReturnMASK = 16; // for binary expressions
+ public static final int OnlyValueRequiredMASK = 32; // for binary expressions
+ public static final int OperatorSHIFT = 6;
+ public static final int OperatorMASK = 63 << OperatorSHIFT;
+
+ // for name references only
+ // Reach . . . . . . . . . . . . . . . . D D D D D D D D VrF R R R
+ public static final int RestrictiveFlagMASK = 7;
+ // 3 lower bits for name references
+ public static final int FirstAssignmentToLocalMASK = 8;
+ // for single name references
+ public static final int DepthSHIFT = 5;
+ public static final int DepthMASK = 0xFF << DepthSHIFT;
+ // 8 bits for actual depth value (max. 255)
+
+ // for statements only
+ public static final int IsReachableMASK = 0x80000000; // highest bit
+ public static final int IsLocalDeclarationReachableMASK = 0x40000000; // below highest bit
+
+ // for type declaration only
+ public static final int AddAssertionMASK = 1; // lowest bit
+
+ // for type, method and field declarations only
+ public static final int HasLocalTypeMASK = 2;
+ // cannot conflict with AddAssertionMASK
+
+ /*
+ public final static int BitMask1= 0x1; // decimal 1
+ public final static int BitMask2= 0x2; // decimal 2
+ public final static int BitMask3= 0x4; // decimal 4
+ public final static int BitMask4= 0x8; // decimal 8
+ public final static int BitMask5= 0x10; // decimal 16
+ public final static int BitMask6= 0x20; // decimal 32
+ public final static int BitMask7= 0x40; // decimal 64
+ public final static int BitMask8= 0x80; // decimal 128
+ public final static int BitMask9= 0x100; // decimal 256
+ public final static int BitMask10= 0x200; // decimal 512
+ public final static int BitMask11= 0x400; // decimal 1024
+ public final static int BitMask12= 0x800; // decimal 2048
+ public final static int BitMask13= 0x1000; // decimal 4096
+ public final static int BitMask14= 0x2000; // decimal 8192
+ public final static int BitMask15= 0x4000; // decimal 16384
+ public final static int BitMask16= 0x8000; // decimal 32768
+ public final static int BitMask17= 0x10000; // decimal 65536
+ public final static int BitMask18= 0x20000; // decimal 131072
+ public final static int BitMask19= 0x40000; // decimal 262144
+ public final static int BitMask20= 0x80000; // decimal 524288
+ public final static int BitMask21= 0x100000; // decimal 1048576
+ public final static int BitMask22= 0x200000; // decimal 2097152
+ public final static int BitMask23= 0x400000; // decimal 4194304
+ public final static int BitMask24= 0x800000; // decimal 8388608
+ public final static int BitMask25= 0x1000000; // decimal 16777216
+ public final static int BitMask26= 0x2000000; // decimal 33554432
+ public final static int BitMask27= 0x4000000; // decimal 67108864
+ public final static int BitMask28= 0x8000000; // decimal 134217728
+ public final static int BitMask29= 0x10000000; // decimal 268435456
+ public final static int BitMask30= 0x20000000; // decimal 536870912
+ public final static int BitMask31= 0x40000000; // decimal 1073741824
+ public final static int BitMask32= 0x80000000; // decimal 2147483648
+ */
+
+ /**
+ * AstNode constructor comment.
+ */
+ public AstNode() {
+
+ super();
+ }
+
+ public boolean cannotReturn() {
+ return false;
+ }
+
+ public AstNode concreteStatement() {
+ return this;
+ }
+
+ /* Answer true if the field use is considered deprecated.
+ * An access in the same compilation unit is allowed.
+ */
+ public final boolean isFieldUseDeprecated(FieldBinding field, Scope scope) {
+
+ return field.isViewedAsDeprecated()
+ && !scope.isDefinedInSameUnit(field.declaringClass);
+ }
+
+ /* 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) {
+ return method.isViewedAsDeprecated()
+ && !scope.isDefinedInSameUnit(method.declaringClass);
+ }
+
+ 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;
+ return refType.isViewedAsDeprecated() && !scope.isDefinedInSameUnit(refType);
+ }
+
+ public static String modifiersString(int modifiers) {
+
+ String s = ""; //$NON-NLS-1$
+ if ((modifiers & AccPublic) != 0)
+ s = s + "public "; //$NON-NLS-1$
+ if ((modifiers & AccPrivate) != 0)
+ s = s + "private "; //$NON-NLS-1$
+ if ((modifiers & AccProtected) != 0)
+ s = s + "protected "; //$NON-NLS-1$
+ if ((modifiers & AccStatic) != 0)
+ s = s + "static "; //$NON-NLS-1$
+ if ((modifiers & AccFinal) != 0)
+ s = s + "final "; //$NON-NLS-1$
+ if ((modifiers & AccSynchronized) != 0)
+ s = s + "synchronized "; //$NON-NLS-1$
+ if ((modifiers & AccVolatile) != 0)
+ s = s + "volatile "; //$NON-NLS-1$
+ if ((modifiers & AccTransient) != 0)
+ s = s + "transient "; //$NON-NLS-1$
+ if ((modifiers & AccNative) != 0)
+ s = s + "native "; //$NON-NLS-1$
+ if ((modifiers & AccAbstract) != 0)
+ s = s + "abstract "; //$NON-NLS-1$
+ return s;
+ }
+
+ /**
+ * @deprecated - use field instead
+ */
+ public int sourceEnd() {
+ return sourceEnd;
+ }
+
+ /**
+ * @deprecated - use field instead
+ */
+ public int sourceStart() {
+ return sourceStart;
+ }
+
+ public static String tabString(int tab) {
+
+ String s = ""; //$NON-NLS-1$
+ for (int i = tab; i > 0; i--)
+ s = s + " "; //$NON-NLS-1$
+ return s;
+ }
+
+ public String toString() {
+
+ return toString(0);
+ }
+
+ public String toString(int tab) {
+
+ return "****" + super.toString() + "****"; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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 ((left.constant != Constant.NotAConstant)
+ && (right.constant != Constant.NotAConstant)) {
+ try {
+ constant =
+ Constant.computeConstantOperation(
+ left.constant,
+ leftId,
+ (bits & OperatorMASK) >> OperatorSHIFT,
+ right.constant,
+ rightId);
+ } catch (ArithmeticException e) {
+ constant = Constant.NotAConstant;
+ // 1.2 no longer throws an exception at compile-time
+ //scope.problemReporter().compileTimeConstantThrowsArithmeticException(this);
+ }
+ } else {
+ constant = Constant.NotAConstant;
+ //add some work for the boolean operators & |
+ optimizedBooleanConstant(
+ leftId,
+ (bits & OperatorMASK) >> OperatorSHIFT,
+ rightId);
+ }
+ }
+
+ public Constant conditionalConstant() {
+
+ return optimizedBooleanConstant == null ? constant : 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 pc = codeStream.position;
+ 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
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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 pc = codeStream.position;
+ 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
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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 pc = codeStream.position;
+ 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.recordPositionsFrom(pc, this.sourceStart);
+ 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.recordPositionsFrom(pc, this.sourceStart);
+ 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.recordPositionsFrom(pc, this.sourceStart);
+ 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.recordPositionsFrom(pc, this.sourceStart);
+ 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 pc = codeStream.position;
+ 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
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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) {
+
+ int pc = codeStream.position;
+ Constant condConst;
+ if ((left.implicitConversion & 0xF) == T_boolean) {
+ if ((condConst = left.conditionalConstant()) != 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);
+ 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);
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ if ((condConst = right.conditionalConstant()) != 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>
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ 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);
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ /**
+ * Boolean generation for |
+ */
+ public void generateOptimizedLogicalOr(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ Label trueLabel,
+ Label falseLabel,
+ boolean valueRequired) {
+
+ int pc = codeStream.position;
+ Constant condConst;
+ if ((left.implicitConversion & 0xF) == T_boolean) {
+ if ((condConst = left.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // <something equivalent to true> | x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_1();
+ } else {
+ if (trueLabel != null) {
+ codeStream.goto_(trueLabel);
+ }
+ }
+ }
+ } 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);
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ if ((condConst = right.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // x | <something equivalent to true>
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_1();
+ } else {
+ if (trueLabel != null) {
+ codeStream.goto_(trueLabel);
+ }
+ }
+ }
+ } 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ /**
+ * Boolean generation for ^
+ */
+ public void generateOptimizedLogicalXor(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ Label trueLabel,
+ Label falseLabel,
+ boolean valueRequired) {
+
+ int pc = codeStream.position;
+ Constant condConst;
+ if ((left.implicitConversion & 0xF) == T_boolean) {
+ if ((condConst = left.conditionalConstant()) != 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);
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ if ((condConst = right.conditionalConstant()) != 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);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ 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.conditionalConstant()) != NotAConstant) {
+ if (cst.booleanValue() == false) { // left is equivalent to false
+ optimizedBooleanConstant = cst; // constant(false)
+ return;
+ } else { //left is equivalent to true
+ if ((cst = right.conditionalConstant()) != NotAConstant) {
+ optimizedBooleanConstant = cst;
+ // the conditional result is equivalent to the right conditional value
+ }
+ return;
+ }
+ }
+ if ((cst = right.conditionalConstant()) != 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.conditionalConstant()) != NotAConstant) {
+ if (cst.booleanValue() == true) { // left is equivalent to true
+ optimizedBooleanConstant = cst; // constant(true)
+ return;
+ } else { //left is equivalent to false
+ if ((cst = right.conditionalConstant()) != NotAConstant) {
+ optimizedBooleanConstant = cst;
+ }
+ return;
+ }
+ }
+ if ((cst = right.conditionalConstant()) != NotAConstant) {
+ if (cst.booleanValue() == true) { // right is equivalent to true
+ optimizedBooleanConstant = cst; // constant(true)
+ }
+ }
+ }
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ // use the id of the type to navigate into the table
+ TypeBinding leftTb = left.resolveType(scope);
+ TypeBinding rightTb = right.resolveType(scope);
+ if (leftTb == null || rightTb == null) {
+ constant = Constant.NotAConstant;
+ return null;
+ }
+ int leftId = leftTb.id;
+ int rightId = rightTb.id;
+ if (leftId > 15
+ || rightId > 15) { // must convert String + Object || Object + String
+ if (leftId == T_String) {
+ rightId = T_Object;
+ } else if (rightId == T_String) {
+ leftId = T_Object;
+ } else {
+ constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftTb, rightTb);
+ return null;
+ }
+ }
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == PLUS) {
+ if (leftId == T_String
+ && rightTb.isArrayType()
+ && ((ArrayBinding) rightTb).elementsType(scope) == CharBinding)
+ scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
+ right);
+ else if (
+ rightId == T_String
+ && leftTb.isArrayType()
+ && ((ArrayBinding) leftTb).elementsType(scope) == CharBinding)
+ scope.problemReporter().signalNoImplicitStringConversionForCharArrayExpression(
+ left);
+ }
+
+ // the code is an int
+ // (cast) left Op (cast) rigth --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+
+ // Don't test for result = 0. If it is zero, some more work is done.
+ // On the one hand when it is not zero (correct code) we avoid doing the test
+ int result =
+ ResolveTypeTables[(bits & OperatorMASK) >> OperatorSHIFT][(leftId << 4)
+ + rightId];
+ left.implicitConversion = result >>> 12;
+ right.implicitConversion = (result >>> 4) & 0x000FF;
+
+ bits |= result & 0xF;
+ switch (result & 0xF) { // record the current ReturnTypeID
+ // only switch on possible result type.....
+ case T_boolean :
+ this.typeBinding = BooleanBinding;
+ break;
+ case T_byte :
+ this.typeBinding = ByteBinding;
+ break;
+ case T_char :
+ this.typeBinding = CharBinding;
+ break;
+ case T_double :
+ this.typeBinding = DoubleBinding;
+ break;
+ case T_float :
+ this.typeBinding = FloatBinding;
+ break;
+ case T_int :
+ this.typeBinding = IntBinding;
+ break;
+ case T_long :
+ this.typeBinding = LongBinding;
+ break;
+ case T_String :
+ this.typeBinding = scope.getJavaLangString();
+ break;
+ default : //error........
+ constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftTb, rightTb);
+ return null;
+ }
+
+ // compute the constant when valid
+ computeConstant(scope, leftId, rightId);
+ return this.typeBinding;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+
+ return left.toStringExpression() + " " + //$NON-NLS-1$
+ operatorToString() + " " + //$NON-NLS-1$
+ right.toStringExpression();
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor 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
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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 static final Block None = new Block(0);
+
+ public Block(int explicitDeclarations) {
+ this.explicitDeclarations = explicitDeclarations;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ // empty block
+ if (statements == null)
+ return flowInfo;
+ for (int i = 0, max = statements.length; i < max; i++) {
+ Statement stat;
+ if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
+ flowInfo = stat.analyseCode(scope, flowContext, flowInfo);
+ }
+ }
+ return flowInfo;
+ }
+
+ public static final Block EmptyWith(int sourceStart, int sourceEnd) {
+
+ //return an empty block which position is s and e
+ Block bk = new Block(0);
+ bk.sourceStart = sourceStart;
+ bk.sourceEnd = sourceEnd;
+ return bk;
+ }
+
+ /**
+ * Code generation for a block
+ */
+ 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 void resolve(BlockScope upperScope) {
+
+ if (statements != null) {
+ scope =
+ explicitDeclarations == 0
+ ? upperScope
+ : new BlockScope(upperScope, explicitDeclarations);
+ int i = 0, length = statements.length;
+ while (i < length)
+ statements[i++].resolve(scope);
+ }
+ }
+
+ public void resolveUsing(BlockScope givenScope) {
+
+ // this optimized resolve(...) is sent only on none empty blocks
+ scope = givenScope;
+ if (statements != null) {
+ int i = 0, length = statements.length;
+ while (i < length)
+ statements[i++].resolve(scope);
+ }
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ if (this.statements == null) {
+ s += "{\n"; //$NON-NLS-1$
+ s += tabString(tab);
+ s += "}"; //$NON-NLS-1$
+ return s;
+ }
+ s += "{\n"; //$NON-NLS-1$
+ s += this.toStringStatements(tab);
+ s += tabString(tab);
+ s += "}"; //$NON-NLS-1$
+ return s;
+ }
+
+ public String toStringStatements(int tab) {
+
+ if (this.statements == null)
+ return ""; //$NON-NLS-1$
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < statements.length; i++) {
+ buffer.append(statements[i].toString(tab + 1));
+ if (statements[i] instanceof Block) {
+ buffer.append("\n"); //$NON-NLS-1$
+ } else {
+ buffer.append(";\n"); //$NON-NLS-1$
+ }
+ };
+ return buffer.toString();
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ if (statements != null) {
+ int statementLength = statements.length;
+ for (int i = 0; i < statementLength; 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);
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public abstract class BranchStatement extends Statement {
+ public char[] label;
+ public Label targetLabel;
+ public AstNode[] 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++){
+ AstNode sub;
+ if ((sub = subroutines[i]) instanceof SynchronizedStatement){
+ codeStream.load(((SynchronizedStatement)sub).synchroVariable);
+ codeStream.monitorexit();
+ } else {
+ TryStatement trySub = (TryStatement) sub;
+ if (trySub.subRoutineCannotReturn) {
+ codeStream.goto_(trySub.subRoutineStartLabel);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ } else {
+ codeStream.jsr(trySub.subRoutineStartLabel);
+ }
+ }
+ }
+ }
+ codeStream.goto_(targetLabel);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public void resetStateForCodeGeneration() {
+ this.targetLabel.resetStateForCodeGeneration();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class Break extends BranchStatement {
+
+ public Break(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;
+ if (label == null) {
+ targetContext = flowContext.getTargetContextForDefaultBreak();
+ } else {
+ targetContext = flowContext.getTargetContextForBreakLabel(label);
+ }
+ if (targetContext == null) {
+ if (label == null) {
+ currentScope.problemReporter().invalidBreak(this);
+ } else {
+ currentScope.problemReporter().undefinedLabel(this); // need to improve
+ }
+ } else {
+ targetLabel = targetContext.breakLabel();
+ targetContext.recordBreakFrom(flowInfo);
+ FlowContext traversedContext = flowContext;
+ int subIndex = 0, maxSub = 5;
+ subroutines = new AstNode[maxSub];
+ while (true) {
+ AstNode sub;
+ if ((sub = traversedContext.subRoutine()) != null) {
+ if (subIndex == maxSub) {
+ System.arraycopy(
+ subroutines,
+ 0,
+ (subroutines = new AstNode[maxSub *= 2]),
+ 0,
+ subIndex);
+ // grow
+ }
+ subroutines[subIndex++] = sub;
+ if (sub.cannotReturn()) {
+ break;
+ }
+ }
+ // remember the initialization at this
+ // point for dealing with blank final variables.
+ traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+
+ if (traversedContext == targetContext) {
+ break;
+ } else {
+ traversedContext = traversedContext.parent;
+ }
+ }
+ // resize subroutines
+ if (subIndex != maxSub) {
+ System.arraycopy(
+ subroutines,
+ 0,
+ (subroutines = new AstNode[subIndex]),
+ 0,
+ subIndex);
+ }
+ }
+ return FlowInfo.DeadEnd;
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ s = s + "break "; //$NON-NLS-1$
+ if (label != null)
+ s = s + new String(label);
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockscope) {
+
+ visitor.visit(this, blockscope);
+ visitor.endVisit(this, blockscope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class Case extends Statement {
+
+ public Expression constantExpression;
+ public CaseLabel targetLabel;
+ public Case(int sourceStart, Expression constantExpression) {
+ this.constantExpression = constantExpression;
+ this.sourceEnd = constantExpression.sourceEnd;
+ this.sourceStart = sourceStart;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ if (constantExpression.constant == NotAConstant)
+ currentScope.problemReporter().caseExpressionMustBeConstant(constantExpression);
+
+ this.constantExpression.analyseCode(currentScope, flowContext, flowInfo);
+ return flowInfo;
+ }
+
+ /**
+ * 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);
+ }
+
+ public void resolve(BlockScope scope) {
+
+ // error....use resolveCase....
+ throw new NullPointerException();
+ }
+
+ public Constant resolveCase(
+ BlockScope scope,
+ TypeBinding testTb,
+ SwitchStatement switchStatement) {
+
+ // add into the collection of cases of the associated switch statement
+ switchStatement.cases[switchStatement.caseCount++] = this;
+ TypeBinding caseTb = constantExpression.resolveType(scope);
+ if (caseTb == null || testTb == null)
+ return null;
+ if (constantExpression.isConstantValueOfTypeAssignableToType(caseTb, testTb))
+ return constantExpression.constant;
+ if (scope.areTypesCompatible(caseTb, testTb))
+ return constantExpression.constant;
+ scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+ constantExpression,
+ caseTb,
+ testTb);
+ return null;
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ s = s + "case " + constantExpression.toStringExpression() + " : "; //$NON-NLS-1$ //$NON-NLS-2$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ constantExpression.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CastExpression extends Expression {
+
+ public Expression expression;
+ public Expression type;
+ public boolean needRuntimeCheckcast;
+ public TypeBinding castTb;
+
+ //expression.implicitConversion holds the cast for baseType casting
+ public CastExpression(Expression e, Expression t) {
+ expression = e;
+ type = t;
+
+ //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();
+ }
+
+ public final void areTypesCastCompatible(
+ BlockScope scope,
+ TypeBinding castTb,
+ TypeBinding expressionTb) {
+
+ // see specifications p.68
+ // handle errors and process constant when needed
+
+ // if either one of the type is null ==>
+ // some error has been already reported some where ==>
+ // we then do not report an obvious-cascade-error.
+
+ needRuntimeCheckcast = false;
+ if (castTb == null || expressionTb == null)
+ return;
+ if (castTb.isBaseType()) {
+ if (expressionTb.isBaseType()) {
+ if (expressionTb == castTb) {
+ constant = expression.constant; //use the same constant
+ return;
+ }
+ if (scope.areTypesCompatible(expressionTb, castTb)
+ || BaseTypeBinding.isNarrowing(castTb.id, expressionTb.id)) {
+ expression.implicitConversion = (castTb.id << 4) + expressionTb.id;
+ if (expression.constant != Constant.NotAConstant)
+ constant = expression.constant.castTo(expression.implicitConversion);
+ return;
+ }
+ }
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+ //-----------cast to something which is NOT a base type--------------------------
+ if (expressionTb == NullBinding)
+ return; //null is compatible with every thing
+
+ if (expressionTb.isBaseType()) {
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+ if (expressionTb.isArrayType()) {
+ if (castTb.isArrayType()) {
+ //------- (castTb.isArray) expressionTb.isArray -----------
+ TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope);
+ if (expressionEltTb.isBaseType()) {
+ // <---stop the recursion-------
+ if (((ArrayBinding) castTb).elementsType(scope) == expressionEltTb)
+ needRuntimeCheckcast = true;
+ else
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+ // recursively on the elements...
+ areTypesCastCompatible(
+ scope,
+ ((ArrayBinding) castTb).elementsType(scope),
+ expressionEltTb);
+ return;
+ } else if (
+ castTb.isClass()) {
+ //------(castTb.isClass) expressionTb.isArray ---------------
+ if (scope.isJavaLangObject(castTb))
+ return;
+ } else { //------- (castTb.isInterface) expressionTb.isArray -----------
+ if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) {
+ needRuntimeCheckcast = true;
+ return;
+ }
+ }
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+ if (expressionTb.isClass()) {
+ if (castTb.isArrayType()) {
+ // ---- (castTb.isArray) expressionTb.isClass -------
+ if (scope.isJavaLangObject(expressionTb)) { // potential runtime error
+ needRuntimeCheckcast = true;
+ return;
+ }
+ } else if (
+ castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
+ if (scope.areTypesCompatible(expressionTb, castTb)) // no runtime error
+ return;
+ if (scope.areTypesCompatible(castTb, expressionTb)) {
+ // potential runtime error
+ needRuntimeCheckcast = true;
+ return;
+ }
+ } else { // ----- (castTb.isInterface) expressionTb.isClass -------
+ if (((ReferenceBinding) expressionTb).isFinal()) {
+ // no subclass for expressionTb, thus compile-time check is valid
+ if (scope.areTypesCompatible(expressionTb, castTb))
+ return;
+ } else { // a subclass may implement the interface ==> no check at compile time
+ needRuntimeCheckcast = true;
+ return;
+ }
+ }
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+
+ // if (expressionTb.isInterface()) { cannot be anything else
+ if (castTb.isArrayType()) {
+ // ----- (castTb.isArray) expressionTb.isInterface ------
+ if (scope.isJavaLangCloneable(expressionTb)
+ || scope.isJavaIoSerializable(expressionTb)) // potential runtime error
+ needRuntimeCheckcast = true;
+ else
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ } else if (
+ castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
+ if (scope.isJavaLangObject(castTb)) // no runtime error
+ return;
+ if (((ReferenceBinding) castTb).isFinal()) {
+ // no subclass for castTb, thus compile-time check is valid
+ if (!scope.areTypesCompatible(castTb, expressionTb)) {
+ // potential runtime error
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ return;
+ }
+ }
+ } else { // ----- (castTb.isInterface) expressionTb.isInterface -------
+ if (castTb != expressionTb
+ && (Scope.compareTypes(castTb, expressionTb) == NotRelated)) {
+ MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods();
+ MethodBinding[] expressionTbMethods =
+ ((ReferenceBinding) expressionTb).methods();
+ int exprMethodsLength = expressionTbMethods.length;
+ for (int i = 0, castMethodsLength = castTbMethods.length;
+ i < castMethodsLength;
+ i++)
+ for (int j = 0; j < exprMethodsLength; j++)
+ if (castTbMethods[i].returnType != expressionTbMethods[j].returnType)
+ if (castTbMethods[i].selector == expressionTbMethods[j].selector)
+ if (castTbMethods[i].areParametersEqual(expressionTbMethods[j]))
+ scope.problemReporter().typeCastError(this, castTb, expressionTb);
+ }
+ }
+ needRuntimeCheckcast = true;
+ return;
+ }
+
+ /**
+ * 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;
+ if (constant != NotAConstant) {
+ if (valueRequired
+ || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
+ codeStream.generateConstant(constant, implicitConversion);
+ if (needRuntimeCheckcast) {
+ codeStream.checkcast(castTb);
+ if (!valueRequired)
+ codeStream.pop();
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ expression.generateCode(
+ currentScope,
+ codeStream,
+ valueRequired || needRuntimeCheckcast);
+ if (needRuntimeCheckcast) {
+ codeStream.checkcast(castTb);
+ if (!valueRequired)
+ codeStream.pop();
+ } else {
+ if (valueRequired)
+ codeStream.generateImplicitConversion(implicitConversion);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ 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;
+ TypeBinding expressionTb = expression.resolveType(scope);
+ if (expressionTb == null)
+ return null;
+
+ if ((type instanceof TypeReference) || (type instanceof NameReference)) {
+ if ((castTb = type.resolveType(scope)) == null)
+ return null;
+ areTypesCastCompatible(scope, castTb, expressionTb);
+ return castTb;
+ } else { // expression as a cast !!!!!!!!
+ scope.problemReporter().invalidTypeReference(type);
+ return null;
+ }
+ }
+
+ public String toStringExpression() {
+
+ return "(" + type.toString(0) + ") " + //$NON-NLS-2$ //$NON-NLS-1$
+ expression.toStringExpression();
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ type.traverse(visitor, blockScope);
+ expression.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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 (welled formed, i.e. 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(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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.binding, syntheticField);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ 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 scope.getJavaLangClass();
+ }
+
+ public String toStringExpression() {
+
+ String s = ""; //$NON-NLS-1$
+ s = s + type.toString(0) + ".class"; //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ type.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.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.DeadEnd);
+
+ // check for missing returning path
+ needFreeReturn =
+ !((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable());
+
+ // 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 {
+ if (statements != null) {
+ for (int i = 0, max = statements.length; i < max; i++)
+ statements[i].resetStateForCodeGeneration();
+ }
+ 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.
+ scope.computeLocalVariablePositions(0, codeStream); // should not be necessary
+ MethodScope staticInitializerScope = declaringType.staticInitializerScope;
+ staticInitializerScope.computeLocalVariablePositions(0, codeStream);
+ // offset by the argument size
+
+ // 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 (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 void resolve(ClassScope scope) {
+
+ this.scope = new MethodScope(scope, scope.referenceContext, true);
+ }
+
+ public String toString(int tab) {
+
+ String s = ""; //$NON-NLS-1$
+ s = s + tabString(tab);
+ s = s + "<clinit>()"; //$NON-NLS-1$
+ s = s + toStringStatements(tab + 1);
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ ClassScope classScope) {
+
+ visitor.visit(this, classScope);
+ visitor.endVisit(this, classScope);
+ }
+
+ // 1.4 feature
+ public void addSupportForAssertion(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);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+public class CompilationUnitDeclaration
+ extends AstNode
+ implements ProblemSeverities, ReferenceContext {
+
+ public ImportReference currentPackage;
+ public ImportReference[] imports;
+ public TypeDeclaration[] types;
+ //public char[][] name;
+
+ public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
+ public boolean ignoreMethodBodies = false;
+ public CompilationUnitScope scope;
+ public ProblemReporter problemReporter;
+ public CompilationResult compilationResult;
+
+ private LocalTypeBinding[] allLocalTypes;
+ 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) {
+
+ switch (abortLevel) {
+ case AbortType :
+ throw new AbortType(compilationResult);
+ case AbortMethod :
+ throw new AbortMethod(compilationResult);
+ default :
+ throw new AbortCompilationUnit(compilationResult);
+ }
+ }
+
+ /*
+ * 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() {
+
+ 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 type's scope backpointers
+ ((SourceTypeBinding) classFile.referenceBinding).scope = null;
+ // null out the classfile backpointer to a type binding
+ classFile.referenceBinding = null;
+ classFile.codeStream = null; // codeStream holds onto ast and scopes
+ classFile.innerClassesBindings = 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) {
+ }
+ }
+
+ 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;
+ }
+
+ /*
+ * Force inner local types to update their innerclass emulation
+ */
+ public void propagateInnerEmulationForAllLocalTypes() {
+
+ isPropagatingInnerClassEmulation = true;
+ if (allLocalTypes != null) {
+ for (int i = 0, max = allLocalTypes.length; i < max; i++) {
+ allLocalTypes[i].updateInnerEmulationDependents();
+ }
+ }
+ }
+
+ /*
+ * Keep track of all local types, so as to update their innerclass
+ * emulation later on.
+ */
+ public void record(LocalTypeBinding localType) {
+
+ if (allLocalTypes == null) {
+ allLocalTypes = new LocalTypeBinding[] { localType };
+ } else {
+ int length = allLocalTypes.length;
+ System.arraycopy(
+ allLocalTypes,
+ 0,
+ (allLocalTypes = new LocalTypeBinding[length + 1]),
+ 0,
+ length);
+ allLocalTypes[length] = localType;
+ }
+ }
+
+ public void resolve() {
+
+ try {
+ if (types != null) {
+ for (int i = 0, count = types.length; i < count; i++) {
+ types[i].resolve(scope);
+ }
+ }
+ checkUnusedImports();
+ } catch (AbortCompilationUnit e) {
+ this.ignoreFurtherInvestigation = true;
+ return;
+ }
+ }
+
+ public void tagAsHavingErrors() {
+ ignoreFurtherInvestigation = true;
+ }
+
+ public String toString(int tab) {
+
+ String s = ""; //$NON-NLS-1$
+ if (currentPackage != null)
+ s = tabString(tab) + "package " + currentPackage.toString(0, false) + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ if (imports != null)
+ for (int i = 0; i < imports.length; i++) {
+ s += tabString(tab) + "import " + imports[i].toString() + ";\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ };
+
+ if (types != null)
+ for (int i = 0; i < types.length; i++) {
+ s += types[i].toString(tab) + "\n"; //$NON-NLS-1$
+ }
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ CompilationUnitScope scope) {
+
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ if (visitor.visit(this, scope)) {
+ if (imports != null) {
+ int importLength = imports.length;
+ for (int i = 0; i < importLength; i++)
+ imports[i].traverse(visitor, scope);
+ }
+ if (types != null) {
+ int typesLength = types.length;
+ for (int i = 0; i < typesLength; i++)
+ types[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ } catch (AbortCompilationUnit e) {
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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);
+ 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 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;
+ 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 TypeBinding resolveType(BlockScope scope) {
+ constant = NotAConstant;
+ 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 += Object is valid wheraas Object -= 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.ResolveTypeTables[operator][ (lhsId << 4) + expressionId];
+ if (result == T_undefined) {
+ scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+ return null;
+ }
+ if (operator == PLUS){
+ if(scope.isJavaLangObject(lhsType)) {
+ // <Object> += <String> is illegal
+ scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+ return null;
+ } else if ((lhsType.isNumericType() || lhsId == T_boolean) && !expressionType.isNumericType()){
+ // <int | boolean> += <String> is illegal
+ scope.problemReporter().invalidOperator(this, lhsType, expressionType);
+ return null;
+ }
+ }
+ lhs.implicitConversion = result >>> 12;
+ expression.implicitConversion = (result >>> 4) & 0x000FF;
+ assignmentImplicitConversion = (lhsId << 4) + (result & 0x0000F);
+ return lhsType;
+}
+public boolean restrainUsageToNumericTypes(){
+ return false ;}
+public String toStringExpressionNoParenthesis() {
+
+ return lhs.toStringExpression() + " " + //$NON-NLS-1$
+ operatorToString() + " " + //$NON-NLS-1$
+ expression.toStringExpression() ; }
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ lhs.traverse(visitor, scope);
+ expression.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class ConditionalExpression extends OperatorExpression {
+
+ public Expression condition, valueIfTrue, valueIfFalse;
+ private int returnTypeSlotSize = 1;
+
+ // for local variables table attributes
+ int thenInitStateIndex = -1;
+ int elseInitStateIndex = -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 conditionConstant = condition.conditionalConstant();
+
+ flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo, conditionConstant == NotAConstant);
+
+ if (conditionConstant != NotAConstant) {
+ if (conditionConstant.booleanValue() == true) {
+ // TRUE ? left : right
+ FlowInfo resultInfo =
+ valueIfTrue.analyseCode(currentScope, flowContext, flowInfo.initsWhenTrue().unconditionalInits());
+ // analyse valueIfFalse, but do not take into account any of its infos
+ valueIfFalse.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.initsWhenFalse().copy().unconditionalInits().markAsFakeReachable(true));
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(resultInfo);
+ return resultInfo;
+ } else {
+ // FALSE ? left : right
+ // analyse valueIfTrue, but do not take into account any of its infos
+ valueIfTrue.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.initsWhenTrue().copy().unconditionalInits().markAsFakeReachable(true));
+ FlowInfo mergeInfo =
+ valueIfFalse.analyseCode(currentScope, flowContext, flowInfo.initsWhenFalse().unconditionalInits());
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergeInfo);
+ return mergeInfo;
+ }
+ }
+
+ // store a copy of the merged info, so as to compute the local variable attributes afterwards
+ FlowInfo trueInfo = flowInfo.initsWhenTrue();
+ thenInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(trueInfo);
+ FlowInfo falseInfo = flowInfo.initsWhenFalse();
+ elseInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(falseInfo);
+
+ // propagate analysis
+ trueInfo = valueIfTrue.analyseCode(currentScope, flowContext, trueInfo.copy());
+ falseInfo =
+ valueIfFalse.analyseCode(currentScope, flowContext, falseInfo.copy());
+
+ // merge back using a conditional info - 1GK2BLM
+ // if ((t && (v = t)) ? t : t && (v = f)) r = v; -- ok
+ FlowInfo mergedInfo =
+ FlowInfo.conditional(
+ trueInfo.initsWhenTrue().copy().unconditionalInits().mergedWith( // must copy, since could be shared with trueInfo.initsWhenFalse()...
+ falseInfo.initsWhenTrue().copy().unconditionalInits()),
+ trueInfo.initsWhenFalse().unconditionalInits().mergedWith(
+ falseInfo.initsWhenFalse().unconditionalInits()));
+ /*
+ FlowInfo mergedInfo = valueIfTrue.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.initsWhenTrue().copy()).
+ unconditionalInits().
+ mergedWith(
+ valueIfFalse.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.initsWhenFalse().copy()).
+ unconditionalInits());
+ */
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ 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.conditionalConstant();
+ 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 (thenInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ thenInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
+ }
+ // 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(returnTypeSlotSize);
+ }
+ }
+ }
+ if (needFalsePart) {
+ falseLabel.place();
+ if (elseInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ elseInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
+ }
+ 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;
+ }
+ int pc = codeStream.position;
+ Constant cst = condition.constant;
+ Constant condCst = condition.conditionalConstant();
+ 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 (thenInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ thenInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
+ }
+ // 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);
+ // Tune codestream stack size
+ //if (valueRequired) {
+ // codeStream.decrStackSize(returnTypeSlotSize);
+ //}
+ }
+ }
+ if (needFalsePart) {
+ internalFalseLabel.place();
+ if (elseInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ elseInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
+ }
+ 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.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ // specs p.368
+ constant = NotAConstant;
+ TypeBinding conditionType = condition.resolveTypeExpecting(scope, BooleanBinding);
+ TypeBinding valueIfTrueType = valueIfTrue.resolveType(scope);
+ 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
+ if (condition.constant != NotAConstant
+ && valueIfTrue.constant != NotAConstant
+ && valueIfFalse.constant != NotAConstant) {
+ // all terms are constant expression so we can propagate the constant
+ // from valueIFTrue or valueIfFalse to teh receiver constant
+ constant =
+ (condition.constant.booleanValue())
+ ? valueIfTrue.constant
+ : valueIfFalse.constant;
+ }
+ if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion
+ valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
+ valueIfFalse.implicitConversion = valueIfTrue.implicitConversion;
+ if (valueIfTrueType == LongBinding || valueIfTrueType == DoubleBinding) {
+ returnTypeSlotSize = 2;
+ }
+ this.typeBinding = valueIfTrueType;
+ return 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);
+ this.typeBinding = ShortBinding;
+ return 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);
+ this.typeBinding = valueIfTrueType;
+ return valueIfTrueType;
+ }
+ if ((valueIfFalseType == ByteBinding
+ || valueIfFalseType == ShortBinding
+ || valueIfFalseType == CharBinding)
+ && (valueIfTrueType == IntBinding
+ && valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) {
+ valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
+ valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+ this.typeBinding = valueIfFalseType;
+ return 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);
+ this.typeBinding = IntBinding;
+ return IntBinding;
+ }
+ // long
+ if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_long)
+ && BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_long)) {
+ valueIfTrue.implicitWidening(LongBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(LongBinding, valueIfFalseType);
+ returnTypeSlotSize = 2;
+ this.typeBinding = LongBinding;
+ return LongBinding;
+ }
+ // float
+ if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_float)
+ && BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_float)) {
+ valueIfTrue.implicitWidening(FloatBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(FloatBinding, valueIfFalseType);
+ this.typeBinding = FloatBinding;
+ return FloatBinding;
+ }
+ // double
+ valueIfTrue.implicitWidening(DoubleBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(DoubleBinding, valueIfFalseType);
+ returnTypeSlotSize = 2;
+ this.typeBinding = DoubleBinding;
+ return 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 (scope.areTypesCompatible(valueIfFalseType, valueIfTrueType)) {
+ valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
+ valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+ this.typeBinding = valueIfTrueType;
+ return valueIfTrueType;
+ }
+ if (scope.areTypesCompatible(valueIfTrueType, valueIfFalseType)) {
+ valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
+ valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+ this.typeBinding = valueIfFalseType;
+ return valueIfFalseType;
+ }
+ scope.problemReporter().conditionalArgumentsIncompatibleTypes(
+ this,
+ valueIfTrueType,
+ valueIfFalseType);
+ return null;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+ return condition.toStringExpression() + " ? " + //$NON-NLS-1$
+ valueIfTrue.toStringExpression() + " : " + //$NON-NLS-1$
+ valueIfFalse.toStringExpression();
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ condition.traverse(visitor, scope);
+ valueIfTrue.traverse(visitor, scope);
+ valueIfFalse.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+public class ConstructorDeclaration extends AbstractMethodDeclaration {
+
+ public ExplicitConstructorCall constructorCall;
+ public final static char[] ConstantPoolName = "<init>".toCharArray(); //$NON-NLS-1$
+ public boolean isDefaultConstructor = false;
+
+ public int referenceCount = 0;
+ // count how many times this constructor is referenced from other local constructors
+
+ public ConstructorDeclaration(CompilationResult compilationResult){
+ super(compilationResult);
+ }
+
+ public void analyseCode(
+ ClassScope classScope,
+ InitializationFlowContext initializerFlowContext,
+ FlowInfo flowInfo) {
+
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ ExceptionHandlingFlowContext constructorContext =
+ new ExceptionHandlingFlowContext(
+ initializerFlowContext.parent,
+ this,
+ binding.thrownExceptions,
+ scope,
+ FlowInfo.DeadEnd);
+ 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) {
+ for (int i = 0, count = statements.length; i < count; i++) {
+ Statement stat;
+ if (!flowInfo.complainIfUnreachable((stat = statements[i]), scope)) {
+ flowInfo = stat.analyseCode(scope, constructorContext, flowInfo);
+ }
+ }
+ }
+ // check for missing returning path
+ needFreeReturn =
+ !((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable());
+
+ // check missing blank final field initializations
+ if ((constructorCall != null)
+ && (constructorCall.accessMode != ExplicitConstructorCall.This)) {
+ flowInfo = flowInfo.mergedWith(initializerFlowContext.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);
+ }
+ }
+ }
+ } 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 {
+ if (statements != null) {
+ for (int i = 0, max = statements.length; i < max; i++)
+ statements[i].resetStateForCodeGeneration();
+ }
+ 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.getProblems();
+ 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.getProblems();
+ IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+ System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+ classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
+ }
+ }
+ }
+
+ 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 argSize = 0;
+ scope.computeLocalVariablePositions(// consider synthetic arguments if any
+ argSize =
+ declaringClass.isNestedType()
+ ? ((NestedTypeBinding) declaringClass).syntheticArgumentsOffset
+ : 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)) {
+ argSize += 2;
+ } else {
+ argSize++;
+ }
+ }
+ }
+ MethodScope initializerScope = declaringType.initializerScope;
+ initializerScope.computeLocalVariablePositions(argSize, codeStream);
+ // offset by the argument size (since not linked to method scope)
+
+ // 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 ((constructorCall != null)
+ && (constructorCall.accessMode != ExplicitConstructorCall.This)) {
+ // generate synthetic fields initialization
+ if (declaringClass.isNestedType()) {
+ NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
+ SyntheticArgumentBinding[] syntheticArgs =
+ nestedType.syntheticEnclosingInstances();
+ for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length;
+ i < max;
+ i++) {
+ if (syntheticArgs[i].matchingField != null) {
+ codeStream.aload_0();
+ codeStream.load(syntheticArgs[i]);
+ codeStream.putfield(syntheticArgs[i].matchingField);
+ }
+ }
+ syntheticArgs = nestedType.syntheticOuterLocalVariables();
+ for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length;
+ i < max;
+ i++) {
+ if (syntheticArgs[i].matchingField != null) {
+ codeStream.aload_0();
+ codeStream.load(syntheticArgs[i]);
+ codeStream.putfield(syntheticArgs[i].matchingField);
+ }
+ }
+ }
+ // 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 (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);
+ }
+ }
+
+ public boolean isConstructor() {
+
+ return true;
+ }
+
+ public boolean isDefaultConstructor() {
+
+ return isDefaultConstructor;
+ }
+
+ public boolean isInitializationMethod() {
+
+ return true;
+ }
+
+ public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+
+ //fill up the constructor body with its statements
+ if (ignoreFurtherInvestigation)
+ return;
+ if (isDefaultConstructor){
+ constructorCall =
+ new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+ constructorCall.sourceStart = sourceStart;
+ constructorCall.sourceEnd = sourceEnd;
+ return;
+ }
+ parser.parse(this, unit);
+
+ }
+
+ /*
+ * Type checking for constructor, just another method, except for special check
+ * for recursive constructor invocations.
+ */
+ public void resolveStatements(ClassScope upperScope) {
+/*
+ // checking for recursive constructor call (protection)
+ if (!ignoreFurtherInvestigation && constructorCall == null){
+ constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+ constructorCall.sourceStart = sourceStart;
+ constructorCall.sourceEnd = sourceEnd;
+ }
+*/
+ if (!CharOperation.equals(scope.enclosingSourceType().sourceName, selector)){
+ scope.problemReporter().missingReturnType(this);
+ }
+
+ // if null ==> an error has occurs at parsing time ....
+ if (constructorCall != null) {
+ // e.g. using super() in java.lang.Object
+ if (binding != null
+ && binding.declaringClass.id == T_Object
+ && constructorCall.accessMode != ExplicitConstructorCall.This) {
+ if (constructorCall.accessMode == ExplicitConstructorCall.Super) {
+ scope.problemReporter().cannotUseSuperInJavaLangObject(constructorCall);
+ }
+ constructorCall = null;
+ } else {
+ constructorCall.resolve(scope);
+ }
+ }
+
+ super.resolveStatements(upperScope);
+
+ // indirect reference: increment target constructor reference count
+ if (constructorCall != null){
+ if (constructorCall.binding != null
+ && !constructorCall.isSuperAccess()
+ && constructorCall.binding.isValidBinding()) {
+ ((ConstructorDeclaration)
+ (upperScope.referenceContext.declarationOf(constructorCall.binding))).referenceCount++;
+ }
+ }
+ }
+
+ public String toStringStatements(int tab) {
+
+ String s = " {"; //$NON-NLS-1$
+ if (constructorCall != null) {
+ s = s + "\n" + constructorCall.toString(tab) + ";"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (statements != null) {
+ for (int i = 0; i < statements.length; i++) {
+ s = s + "\n" + statements[i].toString(tab); //$NON-NLS-1$
+ if (!(statements[i] instanceof Block)) {
+ s += ";"; //$NON-NLS-1$
+ }
+ }
+ }
+ s += "\n" + tabString(tab == 0 ? 0 : tab - 1) + "}"; //$NON-NLS-1$ //$NON-NLS-2$
+ //$NON-NLS-2$ //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class Continue extends BranchStatement {
+
+ public Continue(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;
+ if (label == null) {
+ targetContext = flowContext.getTargetContextForDefaultContinue();
+ } else {
+ targetContext = flowContext.getTargetContextForContinueLabel(label);
+ }
+ if (targetContext == null) {
+ if (label == null) {
+ currentScope.problemReporter().invalidContinue(this);
+ } else {
+ currentScope.problemReporter().undefinedLabel(this); // need to improve
+ }
+ } else {
+ if (targetContext == FlowContext.NotContinuableContext) {
+ currentScope.problemReporter().invalidContinue(this);
+ return FlowInfo.DeadEnd;
+ }
+ targetLabel = targetContext.continueLabel();
+ targetContext.recordContinueFrom(flowInfo);
+ FlowContext traversedContext = flowContext;
+ int subIndex = 0, maxSub = 5;
+ subroutines = new AstNode[maxSub];
+ while (true) {
+ AstNode sub;
+ if ((sub = traversedContext.subRoutine()) != null) {
+ if (subIndex == maxSub) {
+ System.arraycopy(
+ subroutines,
+ 0,
+ (subroutines = new AstNode[maxSub *= 2]),
+ 0,
+ subIndex);
+ // grow
+ }
+ subroutines[subIndex++] = sub;
+ if (sub.cannotReturn()) {
+ break;
+ }
+ }
+ // remember the initialization at this
+ // point for dealing with blank final variables.
+ traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+
+ if (traversedContext == targetContext) {
+ break;
+ } else {
+ traversedContext = traversedContext.parent;
+ }
+ }
+ // resize subroutines
+ if (subIndex != maxSub) {
+ System.arraycopy(
+ subroutines,
+ 0,
+ (subroutines = new AstNode[subIndex]),
+ 0,
+ subIndex);
+ }
+ }
+ return FlowInfo.DeadEnd;
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ s = s + "continue "; //$NON-NLS-1$
+ if (label != null)
+ s = s + new String(label);
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class DefaultCase extends Statement {
+
+ public CaseLabel targetLabel;
+ /**
+ * DefautCase constructor comment.
+ */
+ public DefaultCase(int sourceEnd, int sourceStart) {
+
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ return flowInfo;
+ }
+
+ /**
+ * Default case code generation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ */
+ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+ if ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ int pc = codeStream.position;
+ targetLabel.place();
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+
+ }
+ public Constant resolveCase(
+ BlockScope scope,
+ TypeBinding testType,
+ SwitchStatement switchStatement) {
+
+ // remember the default case into the associated switch statement
+ if (switchStatement.defaultCase != null)
+ scope.problemReporter().duplicateDefaultCase(this);
+
+ // on error the last default will be the selected one .... (why not) ....
+ switchStatement.defaultCase = this;
+ resolve(scope);
+ return null;
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ s = s + "default : "; //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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;
+ }
+
+ 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 conditionConstant = condition.constant;
+ Constant conditionalConstant = condition.conditionalConstant();
+ boolean isFalseCondition =
+ ((conditionConstant != NotAConstant)
+ && (conditionConstant.booleanValue() == false))
+ || ((conditionalConstant != NotAConstant)
+ && (conditionalConstant.booleanValue() == false));
+
+ if ((action != null) && !action.isEmptyBlock()) {
+ flowInfo = action.analyseCode(currentScope, loopingContext, flowInfo.copy());
+
+ // code generation can be optimized when no need to continue in the loop
+ if ((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable()) {
+ if ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
+ || loopingContext.initsOnContinue.isFakeReachable()) {
+ continueLabel = null;
+ } else {
+ flowInfo = loopingContext.initsOnContinue; // for condition
+ if (isFalseCondition) {
+ // continueLabel = null; - cannot nil the label since may be targeted already by 'continue' statements
+ } else {
+ loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
+ }
+ }
+ } else {
+ if (isFalseCondition) {
+ // continueLabel = null; - cannot nil the label since may be targeted already by 'continue' statements
+ } else {
+ loopingContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
+ }
+ }
+ }
+ LoopingFlowContext condLoopContext;
+ flowInfo =
+ condition.analyseCode(
+ currentScope,
+ (condLoopContext =
+ new LoopingFlowContext(flowContext, this, null, null, currentScope)),
+ (action == null
+ ? flowInfo
+ : (flowInfo.mergedWith(loopingContext.initsOnContinue))));
+ condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, flowInfo);
+
+ // infinite loop
+ FlowInfo mergedInfo;
+ if ((condition.constant != NotAConstant)
+ && (condition.constant.booleanValue() == true)) {
+ mergedInfo = loopingContext.initsOnBreak;
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ }
+
+ // end of loop: either condition false or break
+ mergedInfo =
+ flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
+ loopingContext.initsOnBreak);
+ 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.codeStream = codeStream;
+ if (continueLabel != null) {
+ continueLabel.codeStream = 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.recordPositionsFrom(pc, this.sourceStart);
+
+ }
+
+ public void resetStateForCodeGeneration() {
+
+ this.breakLabel.resetStateForCodeGeneration();
+ this.continueLabel.resetStateForCodeGeneration();
+ }
+
+ public void resolve(BlockScope scope) {
+
+ TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
+ condition.implicitWidening(type, type);
+ if (action != null)
+ action.resolve(scope);
+ }
+
+ public String toString(int tab) {
+
+ String inFront, s = tabString(tab);
+ inFront = s;
+ s = s + "do"; //$NON-NLS-1$
+ if (action == null)
+ s = s + " {}\n"; //$NON-NLS-1$
+ else if (action instanceof Block)
+ s = s + "\n" + action.toString(tab + 1) + "\n"; //$NON-NLS-2$ //$NON-NLS-1$
+ else
+ s = s + " {\n" + action.toString(tab + 1) + ";}\n"; //$NON-NLS-1$ //$NON-NLS-2$
+ s = s + inFront + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ return s;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ if (action != null) {
+ action.traverse(visitor, scope);
+ }
+ condition.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+
+public class EmptyStatement extends Statement {
+
+ public EmptyStatement(int startPosition, int endPosition) {
+ this.sourceStart = startPosition;
+ this.sourceEnd = endPosition;
+ }
+
+ public void generateCode(BlockScope currentScope, CodeStream codeStream){
+ // no bytecode, no need to check for reachability or recording source positions
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+
+ public String toString(int tab) {
+ return tabString(tab) + ";"; //$NON-NLS-1$
+ }
+}
+
+
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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 castTb, TypeBinding expressionTb) {
+ //see specifications p.68
+ //A more complete version of this method is provided on
+ //CastExpression (it deals with constant and need runtime checkcast)
+
+
+ //========ARRAY===============
+ if (expressionTb.isArrayType()) {
+ if (castTb.isArrayType()) { //------- (castTb.isArray) expressionTb.isArray -----------
+ TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope);
+ if (expressionEltTb.isBaseType())
+ // <---stop the recursion-------
+ return ((ArrayBinding) castTb).elementsType(scope) == expressionEltTb;
+ //recursivly on the elts...
+ return areTypesCastCompatible(scope, ((ArrayBinding) castTb).elementsType(scope), expressionEltTb);
+ }
+ if (castTb.isBaseType()) {
+ return false;
+ }
+ if (castTb.isClass()) { //------(castTb.isClass) expressionTb.isArray ---------------
+ if (scope.isJavaLangObject(castTb))
+ return true;
+ return false;
+ }
+ if (castTb.isInterface()) { //------- (castTb.isInterface) expressionTb.isArray -----------
+ if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) {
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+ }
+
+ //------------(castType) null--------------
+ if (expressionTb == NullBinding) {
+ return !castTb.isBaseType();
+ }
+
+ //========BASETYPE==============
+ if (expressionTb.isBaseType()) {
+ return false;
+ }
+
+
+ //========REFERENCE TYPE===================
+
+ if (expressionTb.isClass()) {
+ if (castTb.isArrayType()) { // ---- (castTb.isArray) expressionTb.isClass -------
+ if (scope.isJavaLangObject(expressionTb))
+ return true;
+ }
+ if (castTb.isBaseType()) {
+ return false;
+ }
+ if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
+ if (scope.areTypesCompatible(expressionTb, castTb))
+ return true;
+ else {
+ if (scope.areTypesCompatible(castTb, expressionTb)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ if (castTb.isInterface()) { // ----- (castTb.isInterface) expressionTb.isClass -------
+ if (((ReferenceBinding) expressionTb).isFinal()) { //no subclass for expressionTb, thus compile-time check is valid
+ if (scope.areTypesCompatible(expressionTb, castTb))
+ return true;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ if (expressionTb.isInterface()) {
+ if (castTb.isArrayType()) { // ----- (castTb.isArray) expressionTb.isInterface ------
+ if (scope.isJavaLangCloneable(expressionTb) || scope.isJavaIoSerializable(expressionTb))
+ //potential runtime error
+ {
+ return true;
+ }
+ return false;
+ }
+ if (castTb.isBaseType()) {
+ return false;
+ }
+ if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isInterface --------
+ if (scope.isJavaLangObject(castTb))
+ return true;
+ if (((ReferenceBinding) castTb).isFinal()) { //no subclass for castTb, thus compile-time check is valid
+ if (scope.areTypesCompatible(castTb, expressionTb)) {
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ if (castTb.isInterface()) { // ----- (castTb.isInterface) expressionTb.isInterface -------
+ if (castTb != expressionTb && (Scope.compareTypes(castTb, expressionTb) == NotRelated)) {
+ MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods();
+ int castTbMethodsLength = castTbMethods.length;
+ MethodBinding[] expressionTbMethods = ((ReferenceBinding) expressionTb).methods();
+ int expressionTbMethodsLength = expressionTbMethods.length;
+ for (int i = 0; i < castTbMethodsLength; i++) {
+ for (int j = 0; j < expressionTbMethodsLength; j++) {
+ if (castTbMethods[i].selector == expressionTbMethods[j].selector) {
+ if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
+ if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+}
+public final void computeConstant(TypeBinding leftTb, TypeBinding rightTb) {
+ if ((left.constant != NotAConstant) && (right.constant != NotAConstant)) {
+ constant =
+ Constant.computeConstantOperationEQUAL_EQUAL(
+ left.constant,
+ leftTb.id,
+ EQUAL_EQUAL,
+ right.constant,
+ rightTb.id);
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT_EQUAL)
+ constant = Constant.fromValue(!constant.booleanValue());
+ } else {
+ constant = NotAConstant;
+ }
+}
+/**
+ * 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;
+ 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) && (constant.typeID() == T_boolean)) {
+ super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ return;
+ }
+ int pc = codeStream.position;
+ 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);
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+/**
+ * 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) {
+ int pc = codeStream.position;
+ // 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);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ 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);
+ 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
+ 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
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+/**
+ * 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 == null
+ if (right.constant == NullConstant.Default) {
+ 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;
+ }
+ // 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: null == x
+ if (left.constant == NullConstant.Default) {
+ 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;
+ }
+ // 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;
+ }
+ }
+ // 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) {
+ // always return BooleanBinding
+ TypeBinding leftTb = left.resolveType(scope);
+ TypeBinding rightTb = right.resolveType(scope);
+ if (leftTb == null || rightTb == null){
+ constant = NotAConstant;
+ return null;
+ }
+
+ // both base type
+ if (leftTb.isBaseType() && rightTb.isBaseType()) {
+ // the code is an int
+ // (cast) left == (cast) rigth --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+ int result = ResolveTypeTables[EQUAL_EQUAL][ (leftTb.id << 4) + rightTb.id];
+ left.implicitConversion = result >>> 12;
+ right.implicitConversion = (result >>> 4) & 0x000FF;
+ bits |= result & 0xF;
+ if ((result & 0x0000F) == T_undefined) {
+ constant = Constant.NotAConstant;
+ scope.problemReporter().invalidOperator(this, leftTb, rightTb);
+ return null;
+ }
+ computeConstant(leftTb, rightTb);
+ this.typeBinding = BooleanBinding;
+ return BooleanBinding;
+ }
+
+ // Object references
+ // spec 15.20.3
+ if (areTypesCastCompatible(scope, rightTb, leftTb) || areTypesCastCompatible(scope, leftTb, rightTb)) {
+ // (special case for String)
+ if ((rightTb.id == T_String) && (leftTb.id == T_String))
+ computeConstant(leftTb, rightTb);
+ else
+ constant = NotAConstant;
+ if (rightTb.id == T_String)
+ right.implicitConversion = String2String;
+ if (leftTb.id == T_String)
+ left.implicitConversion = String2String;
+ this.typeBinding = BooleanBinding;
+ return BooleanBinding;
+ }
+ constant = NotAConstant;
+ scope.problemReporter().notCompatibleTypesError(this, leftTb, rightTb);
+ return null;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ left.traverse(visitor, scope);
+ right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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);
+ manageSyntheticAccessIfNecessary(currentScope);
+ 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;
+ if ((targetType = binding.declaringClass).isNestedType()) {
+ codeStream.generateSyntheticArgumentValues(
+ 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);
+ }
+ }
+ 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) {
+ ReferenceBinding superType;
+
+ // 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,
+ true);
+ // request direct access
+ } else {
+ // locally propagate, since we already now the desired shape for sure
+ currentScope.propagateInnerEmulation(superType, qualification != null, true);
+ // request direct access
+
+ }
+ }
+ }
+
+ public void manageSyntheticAccessIfNecessary(BlockScope currentScope) {
+
+ // 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);
+ currentScope.problemReporter().needToEmulateMethodAccess(binding, this);
+ }
+ }
+ }
+
+ 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
+ try {
+ ((MethodScope) scope).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[] argTypes = NoParameters;
+ if (arguments != null) {
+ boolean argHasError = false; // typeChecks all arguments
+ int length = arguments.length;
+ argTypes = new TypeBinding[length];
+ for (int i = 0; i < length; i++)
+ if ((argTypes[i] = arguments[i].resolveType(scope)) == null)
+ argHasError = true;
+ if (argHasError)
+ return;
+ }
+ if ((binding = scope.getConstructor(receiverType, argTypes, 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], argTypes[i]);
+ }
+ } else {
+ if (binding.declaringClass == null)
+ binding.declaringClass = receiverType;
+ scope.problemReporter().invalidConstructor(this, binding);
+ }
+ } finally {
+ ((MethodScope) scope).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 String toString(int tab) {
+
+ String s = tabString(tab);
+ if (qualification != null)
+ s = s + qualification.toStringExpression() + "."; //$NON-NLS-1$
+ if (accessMode == This) {
+ s = s + "this("; //$NON-NLS-1$
+ } else {
+ s = s + "super("; //$NON-NLS-1$
+ }
+ if (arguments != null)
+ for (int i = 0; i < arguments.length; i++) {
+ s = s + arguments[i].toStringExpression();
+ if (i != arguments.length - 1)
+ s = s + ", "; //$NON-NLS-1$
+ }
+ s = s + ")"; //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ if (qualification != null) {
+ qualification.traverse(visitor, scope);
+ }
+ if (arguments != null) {
+ int argumentLength = arguments.length;
+ for (int i = 0; i < argumentLength; i++)
+ arguments[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.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 Constant constant;
+
+ public Expression() {
+ super();
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo,
+ boolean valueRequired) {
+
+ return analyseCode(currentScope, flowContext, flowInfo);
+ }
+
+ public Constant conditionalConstant() {
+
+ return 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
+ */
+ 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,
+ net.sourceforge.phpdt.internal.compiler.codegen.CodeStream codeStream,
+ int typeID) {
+
+ 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) {
+ codeStream.ldc(constant.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 resolveTypeExpecting(
+ BlockScope scope,
+ TypeBinding expectedTb) {
+
+ TypeBinding thisTb = this.resolveType(scope);
+ if (thisTb == null)
+ return null;
+ if (!scope.areTypesCompatible(thisTb, expectedTb)) {
+ scope.problemReporter().typeMismatchError(thisTb, expectedTb, this);
+ return null;
+ }
+ return thisTb;
+ }
+
+ public String toString(int tab) {
+
+ //Subclass re-define toStringExpression
+ String s = tabString(tab);
+ if (constant != null)
+ //before TC has runned
+ if (constant != NotAConstant)
+ //after the TC has runned
+ s += " /*cst:" + constant.toString() + "*/ "; //$NON-NLS-1$ //$NON-NLS-2$
+ return s + toStringExpression(tab);
+ }
+
+ //Subclass re-define toStringExpression
+ //This method is abstract and should never be called
+ //but we provide some code that is running.....just in case
+ //of developpement time (while every thing is not built)
+ public String toStringExpression() {
+
+ return super.toString(0);
+ }
+
+ public String toStringExpression(int tab) {
+ // default is regular toString expression (qualified allocation expressions redifine this method)
+ return this.toStringExpression();
+ }
+
+ public 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;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+
+public class ExtendedStringLiteral extends StringLiteral {
+
+ private static final int INIT_SIZE = 30;
+
+ /**
+ * 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 String toStringExpression() {
+
+ String str = "ExtendedStringLiteral{" + new String(source) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
+ return str;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class FieldDeclaration extends AbstractVariableDeclaration {
+ public FieldBinding binding;
+ boolean hasBeenResolved = false;
+
+ //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() {
+ }
+
+ public FieldDeclaration(
+ Expression initialization,
+ char[] name,
+ int sourceStart,
+ int sourceEnd) {
+
+ this.initialization = initialization;
+ 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) {
+
+ // cannot define static non-constant field inside nested class
+ if (binding != null
+ && binding.isValidBinding()
+ && binding.isStatic()
+ && binding.constant == NotAConstant
+ && binding.declaringClass.isNestedType()
+ && binding.declaringClass.isClass()
+ && !binding.declaringClass.isStatic()) {
+ initializationScope.problemReporter().unexpectedStaticModifierForField(
+ (SourceTypeBinding) binding.declaringClass,
+ this);
+ }
+
+ if (initialization != null) {
+ flowInfo =
+ initialization
+ .analyseCode(initializationScope, flowContext, flowInfo)
+ .unconditionalInits();
+ flowInfo.markAsDefinitelyAssigned(binding);
+ } else {
+ flowInfo.markAsDefinitelyNotAssigned(binding);
+ // clear the bit in case it was already set (from enclosing info)
+ }
+ return flowInfo;
+ }
+
+ /**
+ * Code generation for a field declaration:
+ * i.e. normal 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 ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ // do not generate initialization code if final and static (constant is then
+ // recorded inside the field itself).
+ int pc = codeStream.position;
+ boolean isStatic;
+ if (initialization != null
+ && !((isStatic = binding.isStatic()) && binding.constant != NotAConstant)) {
+ // non-static field, need receiver
+ if (!isStatic)
+ codeStream.aload_0();
+ // generate initialization value
+ initialization.generateCode(currentScope, codeStream, true);
+ // store into field
+ if (isStatic) {
+ codeStream.putstatic(binding);
+ } else {
+ codeStream.putfield(binding);
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ public TypeBinding getTypeBinding(Scope scope) {
+
+ return type.getTypeBinding(scope);
+ }
+
+ public boolean isField() {
+
+ return true;
+ }
+
+ public boolean isStatic() {
+
+ if (binding != null)
+ return binding.isStatic();
+ return (modifiers & AccStatic) != 0;
+ }
+
+ public String name() {
+
+ return String.valueOf(name);
+ }
+
+ 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 && binding != null && this.binding.isValidBinding()) {
+
+ this.hasBeenResolved = true;
+
+ if (isTypeUseDeprecated(this.binding.type, initializationScope))
+ initializationScope.problemReporter().deprecatedType(this.binding.type, this.type);
+
+ this.type.binding = this.binding.type; // update binding for type reference
+
+ // the resolution of the initialization hasn't been done
+ if (this.initialization == null) {
+ this.binding.constant = Constant.NotAConstant;
+ } else {
+ int previous = initializationScope.fieldDeclarationIndex;
+ try {
+ initializationScope.fieldDeclarationIndex = this.binding.id;
+
+ // break dead-lock cycles by forcing constant to NotAConstant
+ this.binding.constant = Constant.NotAConstant;
+
+ TypeBinding typeBinding = this.binding.type;
+ TypeBinding initializationTypeBinding;
+
+ if (initialization instanceof ArrayInitializer) {
+
+ if ((initializationTypeBinding = this.initialization.resolveTypeExpecting(initializationScope, typeBinding)) != null) {
+ ((ArrayInitializer) this.initialization).binding = (ArrayBinding) initializationTypeBinding;
+ this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+ }
+ } else if ((initializationTypeBinding = initialization.resolveType(initializationScope)) != null) {
+
+ if (this.initialization.isConstantValueOfTypeAssignableToType(initializationTypeBinding, typeBinding)
+ || (typeBinding.isBaseType() && BaseTypeBinding.isWidening(typeBinding.id, initializationTypeBinding.id))) {
+
+ this.initialization.implicitWidening(typeBinding, initializationTypeBinding);
+
+ } else if (initializationScope.areTypesCompatible(initializationTypeBinding, 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;
+ }
+ } finally {
+ initializationScope.fieldDeclarationIndex = previous;
+ if (this.binding.constant == null)
+ this.binding.constant = Constant.NotAConstant;
+ }
+ }
+ }
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, MethodScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ type.traverse(visitor, scope);
+ if (initialization != null)
+ initialization.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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.isFinal()
+ && 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);
+ }
+ if (assignment.expression != null) {
+ flowInfo =
+ assignment
+ .expression
+ .analyseCode(currentScope, flowContext, flowInfo)
+ .unconditionalInits();
+ }
+ flowInfo =
+ receiver
+ .analyseCode(currentScope, flowContext, flowInfo, !binding.isStatic())
+ .unconditionalInits();
+ manageSyntheticWriteAccessIfNecessary(currentScope);
+
+ // check if assigning a final field
+ if (binding.isFinal()) {
+ // in a context where it can be assigned?
+ if (receiver.isThis()
+ && !(receiver instanceof QualifiedThisReference)
+ && currentScope.allowBlankFinalFieldAssignment(binding)) {
+ if (flowInfo.isPotentiallyAssigned(binding)) {
+ currentScope.problemReporter().duplicateInitializationOfBlankFinalField(
+ binding,
+ this);
+ }
+ flowInfo.markAsDefinitelyAssigned(binding);
+ flowContext.recordSettingFinal(binding, this);
+ } else {
+ // assigning a final field outside an initializer or constructor
+ 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);
+ }
+ 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,
+ valueRequired && (!isStatic) && (this.codegenBinding.constant == NotAConstant));
+ 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 {
+ codeStream.generateConstant(this.codegenBinding.constant, implicitConversion);
+ }
+ }
+ }
+ 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,
+ boolean implicitReceiver,
+ Reference reference,
+ Scope referenceScope,
+ int indexInQualification) {
+
+ //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 (i.e. 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 (indexInQualification == 0) {
+ return binding.constant;
+ }
+ //see previous comment for the (sould-always-be) valid cast
+ QualifiedNameReference qualifiedReference = (QualifiedNameReference) reference;
+ if (indexInQualification == (qualifiedReference.indexOfFirstFieldBinding - 1)) {
+ 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);
+
+ //what scope to use (depend on the staticness of the field binding)
+ MethodScope fieldScope =
+ binding.isStatic()
+ ? typeDecl.staticInitializerScope
+ : typeDecl.initializerScope;
+
+ if (implicitReceiver) { //Determine if the ref is legal in the current class of the field
+ //i.e. not a forward reference .... (they are allowed when the receiver is explicit ! ... Please don't ask me why !...yet another java mystery...)
+ if (fieldScope.fieldDeclarationIndex == MethodScope.NotInFieldDecl) {
+ // no field is currently being analysed in typeDecl
+ fieldDecl.resolve(fieldScope); //side effect on binding :-) ...
+ return binding.constant;
+ }
+ //We are re-entering the same class fields analysing
+ if ((reference != null)
+ && (binding.declaringClass == referenceScope.enclosingSourceType()) // only complain for access inside same type
+ && (binding.id > fieldScope.fieldDeclarationIndex)) {
+ //forward reference. The declaration remains unresolved.
+ referenceScope.problemReporter().forwardReference(reference, indexInQualification, typeBinding);
+ return NotAConstant;
+ }
+ fieldDecl.resolve(fieldScope); //side effect on binding :-) ...
+ return binding.constant;
+ }
+ //the field reference is explicity. It has to be a "simple" like field reference to get the
+ //constant propagation. For example in Packahe.Type.field1.field2 , field1 may have its
+ //constant having a propagation where field2 is always not propagating its
+ if (indexInQualification == 0) {
+ fieldDecl.resolve(fieldScope); //side effect on binding :-) ...
+ return binding.constant;
+ }
+ // Side-effect on the field binding may not be propagated out for the qualified reference
+ // unless it occurs in first place of the name sequence
+ fieldDecl.resolve(fieldScope); //side effect on binding :-) ...
+ //see previous comment for the cast that should always be valid
+ QualifiedNameReference qualifiedReference = (QualifiedNameReference) reference;
+ if (indexInQualification == (qualifiedReference.indexOfFirstFieldBinding - 1)) {
+ return binding.constant;
+ } else {
+ 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) {
+
+ 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 1.4 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.complianceLevel >= CompilerOptions.JDK1_4
+ && 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) {
+
+ 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 1.4 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.complianceLevel >= CompilerOptions.JDK1_4
+ && 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 TypeBinding resolveType(BlockScope scope) {
+
+ // Answer the signature type of the field.
+ // constants are propaged when the field is final
+ // and initialized with a (compile time) constant
+
+ // regular receiver reference
+ this.receiverType = receiver.resolveType(scope);
+ if (this.receiverType == null) {
+ constant = NotAConstant;
+ return null;
+ }
+ // 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))
+ scope.problemReporter().deprecatedField(binding, this);
+
+ // check for this.x in static is done in the resolution of the receiver
+ constant =
+ FieldReference.getConstantFor(
+ binding,
+ receiver == ThisReference.ThisImplicit,
+ this,
+ scope,
+ 0);
+ if (receiver != ThisReference.ThisImplicit)
+ constant = NotAConstant;
+
+ return binding.type;
+ }
+
+ public void setActualReceiverType(ReferenceBinding receiverType) {
+ // ignored
+ }
+
+ public void setDepth(int depth) {
+
+ if (depth > 0) {
+ bits &= ~DepthMASK; // flush previous depth if any
+ bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+ }
+ }
+
+ public void setFieldIndex(int index) {
+ // ignored
+ }
+
+ public String toStringExpression() {
+
+ return receiver.toString() + "." //$NON-NLS-1$
+ + new String(token);
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ receiver.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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;
+ this.neededScope = neededScope;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ breakLabel = new Label();
+ continueLabel = new Label();
+
+ // process the initializations
+ if (initializations != null) {
+ int count = initializations.length, i = 0;
+ while (i < count) {
+ flowInfo = initializations[i++].analyseCode(scope, flowContext, flowInfo);
+ }
+ }
+ preCondInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(flowInfo);
+
+ boolean conditionIsInlinedToTrue =
+ condition == null || (condition.constant != NotAConstant && condition.constant.booleanValue() == true);
+ boolean conditionIsInlinedToFalse =
+ ! conditionIsInlinedToTrue && (condition.constant != NotAConstant && condition.constant.booleanValue() == false);
+
+ // process the condition
+ LoopingFlowContext condLoopContext = null;
+ if (condition != null) {
+ if (!conditionIsInlinedToTrue) {
+ 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()) {
+ if (condLoopContext != null)
+ condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+ if (conditionIsInlinedToTrue) {
+ return FlowInfo.DeadEnd;
+ } else {
+ if (conditionIsInlinedToFalse){
+ 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);
+
+ actionInfo = conditionIsInlinedToFalse
+ ? FlowInfo.DeadEnd // unreachable when condition inlined to false
+ : initsWhenTrue.copy();
+ if (!actionInfo.complainIfUnreachable(action, scope)) {
+ actionInfo = action.analyseCode(scope, loopingContext, actionInfo);
+ }
+
+ // code generation can be optimized when no need to continue in the loop
+ if (((actionInfo == FlowInfo.DeadEnd) || actionInfo.isFakeReachable())
+ && ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
+ || loopingContext.initsOnContinue.isFakeReachable())) {
+ continueLabel = null;
+ } else {
+ if (condLoopContext != null)
+ condLoopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+ loopingContext.complainOnFinalAssignmentsInLoop(scope, actionInfo);
+ actionInfo =
+ actionInfo.mergedWith(loopingContext.initsOnContinue.unconditionalInits());
+ // for increments
+ }
+ }
+ if ((continueLabel != null) && (increments != null)) {
+ LoopingFlowContext loopContext =
+ new LoopingFlowContext(flowContext, this, null, null, scope);
+ int i = 0, count = increments.length;
+ while (i < count)
+ actionInfo = increments[i++].analyseCode(scope, loopContext, actionInfo);
+ loopContext.complainOnFinalAssignmentsInLoop(scope, flowInfo);
+ }
+
+ // infinite loop
+ FlowInfo mergedInfo;
+ if (conditionIsInlinedToTrue) {
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(
+ mergedInfo = loopingContext.initsOnBreak);
+ return mergedInfo;
+ }
+
+ //end of loop: either condition false or break
+ mergedInfo =
+ flowInfo.initsWhenFalse().unconditionalInits().mergedWith(
+ loopingContext.initsOnBreak.unconditionalInits());
+ 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.codeStream = codeStream;
+ if (continueLabel != null) {
+ continueLabel.codeStream = 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.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ public void resetStateForCodeGeneration() {
+
+ this.breakLabel.resetStateForCodeGeneration();
+ this.continueLabel.resetStateForCodeGeneration();
+ }
+
+ 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 String toString(int tab) {
+
+ String s = tabString(tab) + "for ("; //$NON-NLS-1$
+ if (!neededScope)
+ s = s + " //--NO upperscope scope needed\n" + tabString(tab) + " "; //$NON-NLS-2$ //$NON-NLS-1$
+ //inits
+ if (initializations != null) {
+ for (int i = 0; i < initializations.length; i++) {
+ //nice only with expressions
+ s = s + initializations[i].toString(0);
+ if (i != (initializations.length - 1))
+ s = s + " , "; //$NON-NLS-1$
+ }
+ };
+ s = s + "; "; //$NON-NLS-1$
+ //cond
+ if (condition != null)
+ s = s + condition.toStringExpression();
+ s = s + "; "; //$NON-NLS-1$
+ //updates
+ if (increments != null) {
+ for (int i = 0; i < increments.length; i++) {
+ //nice only with expressions
+ s = s + increments[i].toString(0);
+ if (i != (increments.length - 1))
+ s = s + " , "; //$NON-NLS-1$
+ }
+ };
+ s = s + ") "; //$NON-NLS-1$
+ //block
+ if (action == null)
+ s = s + "{}"; //$NON-NLS-1$
+ else
+ s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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 s,
+ int e) {
+
+ this.condition = condition;
+ this.thenStatement = thenStatement;
+ sourceStart = s;
+ sourceEnd = e;
+ }
+
+ public IfStatement(
+ Expression condition,
+ Statement thenStatement,
+ Statement elseStatement,
+ int s,
+ int e) {
+
+ this.condition = condition;
+ this.thenStatement = thenStatement;
+ this.elseStatement = elseStatement;
+ sourceEnd = e;
+ sourceStart = s;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ FlowInfo thenFlowInfo, elseFlowInfo;
+
+ // process the condition
+ flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
+
+ // process the THEN part
+ if (thenStatement == null) {
+ thenFlowInfo = flowInfo.initsWhenTrue();
+ } else {
+ Constant cst;
+ thenFlowInfo =
+ ((((cst = condition.constant) != NotAConstant)
+ && (cst.booleanValue() == false))
+ || (((cst = condition.conditionalConstant()) != NotAConstant)
+ && (cst.booleanValue() == false)))
+ ? (flowInfo.initsWhenTrue().copy().markAsFakeReachable(true))
+ : flowInfo.initsWhenTrue().copy();
+ // Save info for code gen
+ thenInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(thenFlowInfo);
+ if (!thenFlowInfo.complainIfUnreachable(thenStatement, currentScope)) {
+ thenFlowInfo =
+ thenStatement.analyseCode(currentScope, flowContext, thenFlowInfo);
+ }
+ };
+ // optimizing the jump around the ELSE part
+ thenExit = (thenFlowInfo == FlowInfo.DeadEnd) || thenFlowInfo.isFakeReachable();
+
+ // process the ELSE part
+ if (elseStatement == null) {
+ elseFlowInfo = flowInfo.initsWhenFalse();
+ } else {
+ Constant cst;
+ elseFlowInfo =
+ ((((cst = condition.constant) != NotAConstant) && (cst.booleanValue() == true))
+ || (((cst = condition.conditionalConstant()) != NotAConstant)
+ && (cst.booleanValue() == true)))
+ ? (flowInfo.initsWhenFalse().copy().markAsFakeReachable(true))
+ : flowInfo.initsWhenFalse().copy();
+ // Save info for code gen
+ elseInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(elseFlowInfo);
+ if (!elseFlowInfo.complainIfUnreachable(elseStatement, currentScope)) {
+ elseFlowInfo =
+ elseStatement.analyseCode(currentScope, flowContext, elseFlowInfo);
+ }
+ }
+
+ // merge THEN & ELSE initializations
+ FlowInfo mergedInfo;
+ if ((condition.constant != NotAConstant)
+ && (condition.constant.booleanValue() == true)) {
+ // IF (TRUE)
+ if (thenExit) {
+ mergedInfo = elseFlowInfo.markAsFakeReachable(true);
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ } else {
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(thenFlowInfo);
+ return thenFlowInfo;
+ }
+ } else {
+ // IF (FALSE)
+ if ((condition.constant != NotAConstant)
+ && (condition.constant.booleanValue() == false)) {
+ if (elseFlowInfo.isDeadEnd()) {
+ mergedInfo = thenFlowInfo.markAsFakeReachable(true);
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ } else {
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(elseFlowInfo);
+ return elseFlowInfo;
+ }
+ }
+ }
+ mergedInfo = thenFlowInfo.mergedWith(elseFlowInfo.unconditionalInits());
+ 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 ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ int pc = codeStream.position;
+ Label endifLabel = new Label(codeStream);
+
+ // optimizing the then/else part code gen
+ Constant cst, condCst;
+ boolean hasThenPart =
+ !((((cst = condition.constant) != NotAConstant)
+ && (cst.booleanValue() == false))
+ || (thenStatement == null)
+ || (thenStatement.isEmptyBlock())
+ || (((condCst = condition.conditionalConstant()) != NotAConstant)
+ && (condCst.booleanValue() == false)));
+ boolean hasElsePart =
+ !(((cst != NotAConstant) && (cst.booleanValue() == true))
+ || (elseStatement == null)
+ || (elseStatement.isEmptyBlock())
+ || (((condCst = condition.conditionalConstant()) != NotAConstant)
+ && (condCst.booleanValue() == true)));
+
+ if (hasThenPart) {
+ Label falseLabel;
+ // generate boolean condition
+ 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
+ thenStatement.generateCode(currentScope, codeStream);
+ // jump around the else statement
+ if (hasElsePart && !thenExit) {
+ 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
+ condition.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ endifLabel,
+ null,
+ true);
+ } else {
+ // generate condition side-effects
+ 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);
+ }
+ 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 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 String toString(int tab) {
+
+ String inFront, s = tabString(tab);
+ inFront = s;
+ s = s + "if (" + condition.toStringExpression() + ") \n"; //$NON-NLS-1$ //$NON-NLS-2$
+ s = s + thenStatement.toString(tab + 2) + ";"; //$NON-NLS-1$
+ if (elseStatement != null)
+ s = s + "\n" + inFront + "else\n" + elseStatement.toString(tab + 2) + ";"; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.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 ImportReference(char[][] sources , long[] poss , boolean d) {
+ tokens = sources ;
+ sourcePositions = poss ;
+ onDemand = d;
+ sourceEnd = (int)(sourcePositions[sourcePositions.length-1] & 0x00000000FFFFFFFF);
+ sourceStart = (int)(sourcePositions[0]>>>32) ;
+}
+/**
+ * @return char[][]
+ */
+public char[][] getImportName() {
+ return tokens;
+}
+public String toString(int tab ){
+
+ return toString(tab,true);
+}
+public String toString(int tab, boolean withOnDemand) {
+ /* when withOnDemand is false, only the name is printed */
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < tokens.length; i++) {
+ buffer.append(tokens[i]);
+ if (i < (tokens.length - 1)) {
+ buffer.append("."); //$NON-NLS-1$
+ }
+ }
+ if (withOnDemand && onDemand) {
+ buffer.append(".*"); //$NON-NLS-1$
+ }
+ return buffer.toString();
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, CompilationUnitScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+
+public class Initializer extends FieldDeclaration {
+
+ public Block block;
+ public int lastFieldID;
+ public int bodyStart;
+ 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.
+ * i.e. normal 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 type,
+ CompilationUnitDeclaration unit) {
+
+ //fill up the method body with statement
+ parser.parse(this, type, unit);
+ }
+
+ public void resolve(MethodScope scope) {
+
+ int previous = scope.fieldDeclarationIndex;
+ try {
+ scope.fieldDeclarationIndex = lastFieldID;
+ if (isStatic()) {
+ ReferenceBinding declaringType = scope.enclosingSourceType();
+ if (declaringType.isNestedType() && !declaringType.isStatic())
+ scope.problemReporter().innerTypesCannotDeclareStaticInitializers(
+ declaringType,
+ this);
+ }
+ block.resolve(scope);
+ } finally {
+ scope.fieldDeclarationIndex = previous;
+ }
+ }
+
+ public String toString(int tab) {
+
+ if (modifiers != 0) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(tabString(tab));
+ buffer.append(modifiersString(modifiers));
+ buffer.append("{\n"); //$NON-NLS-1$
+ buffer.append(block.toStringStatements(tab));
+ buffer.append(tabString(tab));
+ buffer.append("}"); //$NON-NLS-1$
+ return buffer.toString();
+ } else {
+ return block.toString(tab);
+ }
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, MethodScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ block.traverse(visitor, scope);
+ }
+ visitor.visit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+
+public class InnerTypeDeclaration extends TypeDeclaration {
+
+ public InnerTypeDeclaration(CompilationResult compilationResult){
+ super(compilationResult);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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();
+ }
+
+ public final boolean areTypesCastCompatible(
+ BlockScope scope,
+ TypeBinding castTb,
+ TypeBinding expressionTb) {
+
+ // see specifications p.68
+ //A more cpmplete version of this method is provided on
+ //CastExpression (it deals with constant and need runtime checkcast)
+
+ //by grammatical construction, the first test is ALWAYS false
+ //if (castTb.isBaseType())
+ //{ if (expressionTb.isBaseType())
+ // { if (expression.isConstantValueOfTypeAssignableToType(expressionTb,castTb))
+ // { return true;}
+ // else
+ // { if (expressionTb==castTb)
+ // { return true;}
+ // else
+ // { if (scope.areTypesCompatible(expressionTb,castTb))
+ // { return true; }
+ //
+ // if (BaseTypeBinding.isNarrowing(castTb.id,expressionTb.id))
+ // { return true;}
+ // return false;}}}
+ // else
+ // { return false; }}
+ //else
+ { //-------------checkcast to something which is NOT a basetype----------------------------------
+
+ if (NullBinding == expressionTb)
+ //null is compatible with every thing ....
+ {
+ return true;
+ }
+ if (expressionTb.isArrayType()) {
+ if (castTb.isArrayType()) {
+ //------- (castTb.isArray) expressionTb.isArray -----------
+ TypeBinding expressionEltTb = ((ArrayBinding) expressionTb).elementsType(scope);
+ if (expressionEltTb.isBaseType())
+ // <---stop the recursion-------
+ return ((ArrayBinding) castTb).elementsType(scope) == expressionEltTb;
+ //recursivly on the elts...
+ return areTypesCastCompatible(
+ scope,
+ ((ArrayBinding) castTb).elementsType(scope),
+ expressionEltTb);
+ }
+ if (castTb.isClass()) {
+ //------(castTb.isClass) expressionTb.isArray ---------------
+ if (scope.isJavaLangObject(castTb))
+ return true;
+ return false;
+ }
+ if (castTb.isInterface()) {
+ //------- (castTb.isInterface) expressionTb.isArray -----------
+ if (scope.isJavaLangCloneable(castTb) || scope.isJavaIoSerializable(castTb)) {
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+ }
+ if (expressionTb.isBaseType()) {
+ return false;
+ }
+ if (expressionTb.isClass()) {
+ if (castTb.isArrayType()) {
+ // ---- (castTb.isArray) expressionTb.isClass -------
+ if (scope.isJavaLangObject(expressionTb)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ if (castTb.isClass()) { // ----- (castTb.isClass) expressionTb.isClass ------
+ if (scope.areTypesCompatible(expressionTb, castTb))
+ return true;
+ else {
+ if (scope.areTypesCompatible(castTb, expressionTb)) {
+ return true;
+ }
+ return false;
+ }
+ }
+ if (castTb.isInterface()) {
+ // ----- (castTb.isInterface) expressionTb.isClass -------
+ if (((ReferenceBinding) expressionTb).isFinal()) {
+ //no subclass for expressionTb, thus compile-time check is valid
+ if (scope.areTypesCompatible(expressionTb, castTb))
+ return true;
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ if (expressionTb.isInterface()) {
+ if (castTb.isArrayType()) {
+ // ----- (castTb.isArray) expressionTb.isInterface ------
+ if (scope.isJavaLangCloneable(expressionTb)
+ || scope.isJavaIoSerializable(expressionTb))
+ //potential runtime error
+ {
+ return true;
+ }
+ return false;
+ }
+ if (castTb.isClass()) {
+ // ----- (castTb.isClass) expressionTb.isInterface --------
+ if (scope.isJavaLangObject(castTb))
+ return true;
+ if (((ReferenceBinding) castTb).isFinal()) {
+ //no subclass for castTb, thus compile-time check is valid
+ if (scope.areTypesCompatible(castTb, expressionTb)) {
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ if (castTb.isInterface()) {
+ // ----- (castTb.isInterface) expressionTb.isInterface -------
+ if (castTb != expressionTb
+ && (Scope.compareTypes(castTb, expressionTb) == NotRelated)) {
+ MethodBinding[] castTbMethods = ((ReferenceBinding) castTb).methods();
+ int castTbMethodsLength = castTbMethods.length;
+ MethodBinding[] expressionTbMethods =
+ ((ReferenceBinding) expressionTb).methods();
+ int expressionTbMethodsLength = expressionTbMethods.length;
+ for (int i = 0; i < castTbMethodsLength; i++) {
+ for (int j = 0; j < expressionTbMethodsLength; j++) {
+ if (castTbMethods[i].selector == expressionTbMethods[j].selector) {
+ if (castTbMethods[i].returnType != expressionTbMethods[j].returnType) {
+ if (castTbMethods[i].areParametersEqual(expressionTbMethods[j])) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+ }
+ }
+ /**
+ * 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.binding);
+ if (!valueRequired)
+ codeStream.pop();
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ constant = NotAConstant;
+ TypeBinding expressionTb = expression.resolveType(scope);
+ TypeBinding checkTb = type.resolveType(scope);
+ if (expressionTb == null || checkTb == null)
+ return null;
+
+ if (!areTypesCastCompatible(scope, checkTb, expressionTb)) {
+ scope.problemReporter().notCompatibleTypesError(this, expressionTb, checkTb);
+ return null;
+ }
+ this.typeBinding = BooleanBinding;
+ return BooleanBinding;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+
+ return expression.toStringExpression() + " instanceof " + //$NON-NLS-1$
+ type.toString(0);
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ expression.traverse(visitor, scope);
+ type.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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);
+ return null;
+ }
+ return tb;
+}
+public String toStringExpression(){
+
+ if (source == null)
+ /* special optimized IntLiteral that are created by the compiler */
+ return String.valueOf(value);
+
+ return super.toStringExpression();}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.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*/ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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[] l, Statement st, int s, int e) {
+
+ this.statement = st;
+ this.label = l;
+ this.sourceStart = s;
+ this.sourceEnd = e;
+ }
+
+ 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();
+ }
+
+ /**
+ * 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.codeStream = 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.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ public void resolve(BlockScope scope) {
+
+ statement.resolve(scope);
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ s += new String(label) + ": " + statement.toString(0); //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ statement.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+
+ public void resetStateForCodeGeneration() {
+
+ this.targetLabel.resetStateForCodeGeneration();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public abstract class Literal extends Expression {
+
+
+public Literal(int s,int e) {
+ sourceStart = s ;
+ sourceEnd= e;
+}
+public abstract void computeConstant() ;
+ //ON ERROR constant STAYS NULL
+public abstract TypeBinding literalType(BlockScope scope);
+public TypeBinding resolveType(BlockScope scope) {
+ // compute the real value, which must range its type's range
+
+ computeConstant();
+ if (constant == null) {
+ scope.problemReporter().constantOutOfRange(this);
+ constant = Constant.NotAConstant;
+ return null;
+ }
+ return literalType(scope);
+}
+public abstract char[] source() ;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class LocalDeclaration extends AbstractVariableDeclaration {
+
+ public LocalVariableBinding binding;
+
+ public LocalDeclaration(
+ Expression expr,
+ char[] name,
+ int sourceStart,
+ int sourceEnd) {
+
+ initialization = expr;
+ this.name = name;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+ if (initialization != null) {
+ this.declarationSourceEnd = initialization.sourceEnd;
+ } else {
+ this.declarationSourceEnd = sourceEnd;
+ }
+ this.declarationEnd = this.declarationSourceEnd;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ // record variable initialization if any
+ if (!flowInfo.isDeadEnd() && !flowInfo.isFakeReachable()) {
+ bits |= IsLocalDeclarationReachableMASK; // only set if actually reached
+ }
+ if (initialization == null)
+ return flowInfo;
+ flowInfo =
+ initialization
+ .analyseCode(currentScope, flowContext, flowInfo)
+ .unconditionalInits();
+ flowInfo.markAsDefinitelyAssigned(binding);
+ return flowInfo;
+ }
+
+ public void checkModifiers() {
+ //only potential valid modifier is <<final>>
+
+ if (((modifiers & AccJustFlag) | AccFinal) != AccFinal)
+ //AccModifierProblem -> other (non-visibility problem)
+ //AccAlternateModifierProblem -> duplicate modifier
+ //AccModifierProblem | AccAlternateModifierProblem -> visibility problem"
+ // -x-1 returns the bitInvert
+
+ modifiers =
+ (modifiers & (-AccAlternateModifierProblem - 1)) | AccModifierProblem;
+ }
+
+ /**
+ * Code generation for a local declaration:
+ * i.e. normal assignment to a local variable + unused variable handling
+ */
+ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+ if ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ int pc = codeStream.position;
+ Constant inlinedValue;
+ // something to initialize?
+ if (binding.resolvedPosition != -1) {
+ codeStream.addVisibleLocalVariable(binding);
+ }
+ 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) {
+ 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 String name() {
+
+ return String.valueOf(name);
+ }
+
+ public void resolve(BlockScope scope) {
+
+ // create a binding and add it to the scope
+ TypeBinding tb = type.resolveType(scope);
+
+ checkModifiers();
+
+ if (tb != null) {
+ if (tb == VoidBinding) {
+ scope.problemReporter().variableTypeCannotBeVoid(this);
+ return;
+ }
+ if (tb.isArrayType() && ((ArrayBinding) tb).leafComponentType == VoidBinding) {
+ scope.problemReporter().variableTypeCannotBeVoidArray(this);
+ return;
+ }
+ }
+
+ // duplicate checks
+ if ((binding = scope.duplicateName(name)) != null) {
+ // the name already exists... may carry on with the first binding...
+ scope.problemReporter().redefineLocal(this);
+ } else {
+ binding = new LocalVariableBinding(this, tb, modifiers, false);
+ scope.addLocalVariable(binding);
+ binding.constant = NotAConstant;
+ // allow to recursivelly target the binding....
+ // the correct constant is harmed if correctly computed at the end of this method
+ }
+
+ if (tb == null) {
+ if (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 initTb = initialization.resolveTypeExpecting(scope, tb);
+ if (initTb != null) {
+ ((ArrayInitializer) initialization).binding = (ArrayBinding) initTb;
+ initialization.implicitWidening(tb, initTb);
+ }
+ } else {
+ TypeBinding initTb = initialization.resolveType(scope);
+ if (initTb != null) {
+ if (initialization.isConstantValueOfTypeAssignableToType(initTb, tb)
+ || (tb.isBaseType() && BaseTypeBinding.isWidening(tb.id, initTb.id))
+ || scope.areTypesCompatible(initTb, tb))
+ initialization.implicitWidening(tb, initTb);
+ else
+ scope.problemReporter().typeMismatchError(initTb, tb, this);
+ }
+ }
+
+ // change the constant in the binding when it is final
+ // (the optimization of the constant propagation will be done later on)
+ // cast from constant actual type to variable type
+ binding.constant =
+ binding.isFinal()
+ ? initialization.constant.castTo((tb.id << 4) + initialization.constant.typeID())
+ : NotAConstant;
+ }
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ type.traverse(visitor, scope);
+ if (initialization != null)
+ initialization.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+
+public class LocalTypeDeclaration extends InnerTypeDeclaration {
+ public AbstractMethodDeclaration enclosingMethod;
+
+public LocalTypeDeclaration(CompilationResult compilationResult){
+ super(compilationResult);
+}
+
+/**
+ * Iteration for a local innertype
+ *
+ */
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ if (visitor.visit(this, blockScope)) {
+ if (superclass != null)
+ superclass.traverse(visitor, scope);
+ if (superInterfaces != null) {
+ int superInterfaceLength = superInterfaces.length;
+ for (int i = 0; i < superInterfaceLength; i++)
+ superInterfaces[i].traverse(visitor, scope);
+ }
+ if (memberTypes != null) {
+ int memberTypesLength = memberTypes.length;
+ for (int i = 0; i < memberTypesLength; i++)
+ memberTypes[i].traverse(visitor, scope);
+ }
+ if (fields != null) {
+ int fieldsLength = fields.length;
+ for (int i = 0; i < fieldsLength; i++) {
+ FieldDeclaration field;
+ if ((field = fields[i]).isStatic()) {
+ // local type cannot have static fields
+ } else {
+ field.traverse(visitor, initializerScope);
+ }
+ }
+ }
+ if (methods != null) {
+ int methodsLength = methods.length;
+ for (int i = 0; i < methodsLength; i++)
+ methods[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, blockScope);
+ } catch (AbortType e) {
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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);
+ return null;
+ }
+ return tb;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.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*/}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+public abstract class MagicLiteral extends Literal {
+public MagicLiteral(int s , int e) {
+ super(s,e);
+}
+public boolean isValidJavaStatement(){
+ //should never be reach, but with a bug in the ast tree....
+ //see comment on the Statement class
+
+ return false ;}
+/**
+ * source method comment.
+ */
+public char[] source() {
+ return null;
+}
+public String toStringExpression(){
+
+ return new String(source()) ; }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.ClassScope;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortType;
+
+public class MemberTypeDeclaration extends InnerTypeDeclaration {
+ public TypeDeclaration enclosingType;
+
+public MemberTypeDeclaration(CompilationResult compilationResult){
+ super(compilationResult);
+}
+/**
+ * Iteration for a member innertype
+ *
+ */
+public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope classScope) {
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ if (visitor.visit(this, classScope)) {
+ if (superclass != null)
+ superclass.traverse(visitor, scope);
+ if (superInterfaces != null) {
+ int superInterfaceLength = superInterfaces.length;
+ for (int i = 0; i < superInterfaceLength; i++)
+ superInterfaces[i].traverse(visitor, scope);
+ }
+ if (memberTypes != null) {
+ int memberTypesLength = memberTypes.length;
+ for (int i = 0; i < memberTypesLength; i++)
+ memberTypes[i].traverse(visitor, scope);
+ }
+ if (fields != null) {
+ int fieldsLength = fields.length;
+ for (int i = 0; i < fieldsLength; i++) {
+ FieldDeclaration field;
+ if ((field = fields[i]).isStatic()) {
+ field.traverse(visitor, staticInitializerScope);
+ } else {
+ field.traverse(visitor, initializerScope);
+ }
+ }
+ }
+ if (methods != null) {
+ int methodsLength = methods.length;
+ for (int i = 0; i < methodsLength; i++)
+ methods[i].traverse(visitor, scope);
+ }
+ }
+ visitor.endVisit(this, classScope);
+ } catch (AbortType e) {
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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 MessageSend() {
+
+}
+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);
+ }
+ // if invoking through an enclosing instance, then must perform the field generation -- only if reachable
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ manageSyntheticAccessIfNecessary(currentScope);
+ 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 == ThisReference.ThisImplicit)){
+ // outer method can be reached through emulation if implicit access
+ Object[] path = currentScope.getExactEmulationPath(currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT));
+ if (path == null) {
+ // emulation was not possible (should not happen per construction)
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(path, this, 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 manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+ if (((bits & DepthMASK) != 0) && !binding.isStatic() && (receiver == ThisReference.ThisImplicit)) {
+ ReferenceBinding compatibleType = currentScope.enclosingSourceType();
+ // the declaringClass of the target binding must be compatible with the enclosing
+ // type at <depth> levels outside
+ for (int i = 0, depth = (bits & DepthMASK) >> DepthSHIFT; i < depth; i++) {
+ compatibleType = compatibleType.enclosingType();
+ }
+ currentScope.emulateOuterAccess((SourceTypeBinding) compatibleType, false); // request cascade of accesses
+ }
+}
+public void manageSyntheticAccessIfNecessary(BlockScope currentScope){
+
+ 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);
+ 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);
+ 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);
+ 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 1.4 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.complianceLevel >= CompilerOptions.JDK1_4
+ && (receiver != ThisReference.ThisImplicit || !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);
+ }
+}
+
+public TypeBinding resolveType(BlockScope scope) {
+ // Answer the signature return type
+ // Base type promotion
+
+ constant = NotAConstant;
+ this.qualifyingType = this.receiverType = receiver.resolveType(scope);
+
+ // 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++){
+ if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null){
+ argHasError = true;
+ }
+ }
+ if (argHasError){
+ MethodBinding closestMethod = null;
+ 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 == ThisReference.ThisImplicit
+ ? 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 { // really bad error ....
+ 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.problemId() == ProblemReasons.NotFound){
+ this.codegenBinding = this.binding = ((ProblemMethodBinding)binding).closestMatch;
+ }
+ return null;
+ }
+ if (!binding.isStatic()) {
+ // the "receiver" must not be a type, i.e. a NameReference that the TC has bound to a Type
+ if (receiver instanceof NameReference) {
+ if ((((NameReference) receiver).bits & BindingIds.TYPE) != 0) {
+ scope.problemReporter().mustUseAStaticMethod(this, binding);
+ return null;
+ }
+ }
+ }
+ if (arguments != null)
+ for (int i = 0; i < arguments.length; i++)
+ arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
+
+ //-------message send that are known to fail at compile time-----------
+ if (binding.isAbstract()) {
+ if (receiver.isSuper()) {
+ scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, binding);
+ return null;
+ }
+ // abstract private methods cannot occur nor abstract static............
+ }
+ if (isMethodUseDeprecated(binding, scope))
+ scope.problemReporter().deprecatedMethod(binding, this);
+
+ return binding.returnType;
+}
+public void setActualReceiverType(ReferenceBinding receiverType) {
+ this.qualifyingType = receiverType;
+}
+public void setDepth(int depth) {
+ if (depth > 0) {
+ bits &= ~DepthMASK; // flush previous depth if any
+ bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+ }
+}
+public void setFieldIndex(int depth) {
+ // ignore for here
+}
+
+public String toStringExpression(){
+
+ String s = ""; //$NON-NLS-1$
+ if (receiver != ThisReference.ThisImplicit)
+ s = s + receiver.toStringExpression()+"."; //$NON-NLS-1$
+ s = s + new String(selector) + "(" ; //$NON-NLS-1$
+ if (arguments != null)
+ for (int i = 0; i < arguments.length ; i ++)
+ { s = s + arguments[i].toStringExpression();
+ if ( i != arguments.length -1 ) s = s + " , " ;};; //$NON-NLS-1$
+ s =s + ")" ; //$NON-NLS-1$
+ return s;
+}
+
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ 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);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+public class MethodDeclaration extends AbstractMethodDeclaration {
+
+ public TypeReference returnType;
+
+ /**
+ * MethodDeclaration constructor comment.
+ */
+ public MethodDeclaration(CompilationResult compilationResult) {
+ super(compilationResult);
+ }
+
+
+ public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
+
+ //fill up the method body with statement
+ if (ignoreFurtherInvestigation)
+ return;
+ parser.parse(this, unit);
+ }
+
+ public void resolveStatements(ClassScope upperScope) {
+
+ // ========= abort on fatal error =============
+ if (this.returnType != null && this.binding != null) {
+ this.returnType.binding = 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);
+
+ 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().methodNeedingAbstractModifier(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(upperScope);
+ }
+
+ public String returnTypeToString(int tab) {
+
+ if (returnType == null)
+ return ""; //$NON-NLS-1$
+ return returnType.toString(tab) + " "; //$NON-NLS-1$
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public abstract class NameReference extends Reference implements InvocationSite, BindingIds {
+
+ public Binding binding, codegenBinding; //may be aTypeBinding-aFieldBinding-aLocalVariableBinding
+
+ public TypeBinding receiverType, actualReceiverType;
+
+ //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) {
+ if (depth > 0) {
+ bits &= ~DepthMASK; // flush previous depth if any
+ bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits
+ }
+}
+public void setFieldIndex(int index){
+ // ignored
+}
+
+public abstract String unboundReferenceErrorName();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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 = Constant.fromValue(null);}
+/**
+ * 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(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+public abstract class NumberLiteral extends Literal {
+ char[] source;
+public NumberLiteral(char[] token, int s, int e) {
+ this(s,e) ;
+ source = token ;
+}
+public NumberLiteral(int s, int e) {
+ super (s,e) ;
+}
+public boolean isValidJavaStatement(){
+ //should never be reach, but with a bug in the ast tree....
+ //see comment on the Statement class
+
+ return false ;}
+public char[] source(){
+ return source;}
+public String toStringExpression(){
+
+ return new String(source);}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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 opConstant = left.conditionalConstant();
+ if (opConstant != NotAConstant) {
+ if (opConstant.booleanValue() == false) {
+ // 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, rightInfo;
+ 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 !
+ rightInfo = leftInfo.initsWhenFalse().unconditionalInits().copy();
+ if (opConstant != NotAConstant && opConstant.booleanValue() == true) rightInfo.markAsFakeReachable(true);
+
+ rightInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(rightInfo);
+ rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
+ 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()),
+ rightInfo.initsWhenFalse().copy());
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ }
+
+ /**
+ * Code generation for a binary operation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+ public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
+ 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;
+ generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ (falseLabel = new Label(codeStream)),
+ valueRequired);
+ /* improving code gen for such a case: boolean b = i < 0 || true;
+ * since the label has never been used, we have the inlined value on the stack. */
+ if (falseLabel.hasForwardReferences()) {
+ if (valueRequired) {
+ codeStream.iconst_1();
+ if ((bits & ValueForReturnMASK) != 0) {
+ codeStream.ireturn();
+ falseLabel.place();
+ codeStream.iconst_0();
+ } else {
+ codeStream.goto_(endLabel = new Label(codeStream));
+ codeStream.decrStackSize(1);
+ falseLabel.place();
+ codeStream.iconst_0();
+ endLabel.place();
+ }
+ } else {
+ falseLabel.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;
+ }
+ int pc = codeStream.position;
+ Constant condConst;
+ if ((condConst = left.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // <something equivalent to true> || x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_1();
+ } else {
+ if (trueLabel != null) {
+ codeStream.goto_(trueLabel);
+ }
+ }
+ }
+ } else {
+ // <something equivalent to false> || x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ right.generateCode(currentScope, codeStream, valueRequired);
+ } else {
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ return;
+ }
+ if ((condConst = right.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // x || <something equivalent to true>
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_1();
+ } else {
+ if (trueLabel != null) {
+ codeStream.goto_(trueLabel);
+ }
+ }
+ }
+ } else {
+ // x || <something equivalent to false>
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ left.generateCode(currentScope, codeStream, valueRequired);
+ } else {
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ return;
+ }
+ // default case
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ null,
+ valueRequired);
+ }
+ } else {
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ Label internalTrueLabel = new Label(codeStream);
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ internalTrueLabel,
+ null,
+ true);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ falseLabel,
+ valueRequired);
+ internalTrueLabel.place();
+ } else {
+ // no implicit fall through TRUE/FALSE --> should never occur
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ }
+
+ public boolean isCompactableOperation() {
+ return false;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor 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
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public abstract class OperatorExpression extends Expression implements OperatorIds {
+
+ public static int[][] ResolveTypeTables = new int[NumberOfTables][];
+ public TypeBinding typeBinding;
+ static {classInitialize();}
+
+ /**
+ * OperatorExpression constructor comment.
+ */
+ public OperatorExpression() {
+ super();
+ }
+ public static final void classInitialize() {
+ ResolveTypeTables[AND] = get_AND();
+ ResolveTypeTables[AND_AND] = get_AND_AND();
+ ResolveTypeTables[DIVIDE] = get_DIVIDE();
+ ResolveTypeTables[EQUAL_EQUAL] = get_EQUAL_EQUAL();
+ ResolveTypeTables[GREATER] = get_GREATER();
+ ResolveTypeTables[GREATER_EQUAL] = get_GREATER_EQUAL();
+ ResolveTypeTables[LEFT_SHIFT] = get_LEFT_SHIFT();
+ ResolveTypeTables[LESS] = get_LESS();
+ ResolveTypeTables[LESS_EQUAL] = get_LESS_EQUAL();
+ ResolveTypeTables[MINUS] = get_MINUS();
+ ResolveTypeTables[MULTIPLY] = get_MULTIPLY();
+ ResolveTypeTables[OR] = get_OR();
+ ResolveTypeTables[OR_OR] = get_OR_OR();
+ ResolveTypeTables[PLUS] = get_PLUS();
+ ResolveTypeTables[REMAINDER] = get_REMAINDER();
+ ResolveTypeTables[RIGHT_SHIFT] = get_RIGHT_SHIFT();
+ ResolveTypeTables[UNSIGNED_RIGHT_SHIFT] = get_UNSIGNED_RIGHT_SHIFT();
+ ResolveTypeTables[XOR] = get_XOR();
+ }
+
+ 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 = (ResolveTypeTables[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 String toStringExpression(){
+
+ //subclass redefine toStringExpressionNoParenthesis()
+ return "(" + toStringExpressionNoParenthesis() + ")"; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ public abstract String toStringExpressionNoParenthesis();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.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;
+ 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 boolean restrainUsageToNumericTypes() {
+
+ return true;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+
+ return lhs.toStringExpression() + " " + operatorToString(); //$NON-NLS-1$
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ lhs.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class PrefixExpression extends CompoundAssignment {
+
+ /**
+ * PrefixExpression constructor comment.
+ * @param l org.eclipse.jdt.internal.compiler.ast.Expression
+ * @param r 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 boolean restrainUsageToNumericTypes() {
+
+ return true;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+
+ return operatorToString() + " " + lhs.toStringExpression(); //$NON-NLS-1$
+
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ if (visitor.visit(this, scope)) {
+ lhs.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class QualifiedAllocationExpression extends AllocationExpression {
+
+ //qualification may be on both side
+ public Expression enclosingInstance;
+ public AnonymousLocalTypeDeclaration anonymousType;
+
+ public QualifiedAllocationExpression() {
+ }
+
+ public QualifiedAllocationExpression(AnonymousLocalTypeDeclaration anonymousType) {
+ this.anonymousType = anonymousType;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ // variation on allocation, where can be specified an enclosing instance and an anonymous type
+
+ // analyse the enclosing instance
+ if (enclosingInstance != null) {
+ flowInfo = enclosingInstance.analyseCode(currentScope, flowContext, 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);
+ manageSyntheticAccessIfNecessary(currentScope);
+ return flowInfo;
+ }
+
+ public Expression enclosingInstance() {
+
+ return enclosingInstance;
+ }
+
+ public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
+
+ int pc = codeStream.position;
+ ReferenceBinding allocatedType = binding.declaringClass;
+ if (allocatedType.isLocalType()) {
+ LocalTypeBinding localType = (LocalTypeBinding) allocatedType;
+ localType.constantPoolName(
+ codeStream.classFile.outerMostEnclosingClassFile().computeConstantPoolName(
+ localType));
+ }
+ codeStream.new_(allocatedType);
+ if (valueRequired) {
+ codeStream.dup();
+ }
+ // better highlight for allocation: display the type individually
+ codeStream.recordPositionsFrom(pc, type.sourceStart);
+
+ // handling innerclass instance allocation
+ if (allocatedType.isNestedType()) {
+ // make sure its name is computed before arguments, since may be necessary for argument emulation
+ codeStream.generateSyntheticArgumentValues(
+ 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);
+ }
+ }
+ // 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) {
+
+ 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,
+ false);
+ // request cascade of accesses
+ } else {
+ // locally propagate, since we already now the desired shape for sure
+ currentScope.propagateInnerEmulation(
+ allocatedType,
+ enclosingInstance != null,
+ false);
+ // request cascade of accesses
+ }
+ }
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ if (anonymousType == null && enclosingInstance == null)
+ return super.resolveType(scope);
+ // added for code assist... is not possible with 'normal' code
+
+ // 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 enclosingInstTb = null;
+ TypeBinding recType;
+ if (anonymousType == null) {
+ //----------------no anonymous class------------------------
+ if ((enclosingInstTb = enclosingInstance.resolveType(scope)) == null)
+ return null;
+ if (enclosingInstTb.isBaseType() | enclosingInstTb.isArrayType()) {
+ scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(
+ enclosingInstTb,
+ enclosingInstance);
+ return null;
+ }
+ recType =
+ ((SingleTypeReference) type).resolveTypeEnclosing(
+ scope,
+ (ReferenceBinding) enclosingInstTb);
+ // will check for null after args are resolved
+ TypeBinding[] argumentTypes = NoParameters;
+ if (arguments != null) {
+ boolean argHasError = false;
+ int length = arguments.length;
+ argumentTypes = new TypeBinding[length];
+ for (int i = 0; i < length; i++)
+ if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+ argHasError = true;
+ if (argHasError)
+ return recType;
+ }
+ if (recType == null)
+ return null;
+ if (!recType.canBeInstantiated()) {
+ scope.problemReporter().cannotInstantiate(type, recType);
+ return recType;
+ }
+ if ((binding =
+ scope.getConstructor((ReferenceBinding) recType, argumentTypes, this))
+ .isValidBinding()) {
+ 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]);
+ } else {
+ if (binding.declaringClass == null)
+ binding.declaringClass = (ReferenceBinding) recType;
+ scope.problemReporter().invalidConstructor(this, binding);
+ return recType;
+ }
+
+ // The enclosing instance must be compatible with the innermost enclosing type
+ ReferenceBinding expectedType = binding.declaringClass.enclosingType();
+ if (scope.areTypesCompatible(enclosingInstTb, expectedType))
+ return recType;
+ scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+ enclosingInstance,
+ enclosingInstTb,
+ expectedType);
+ return recType;
+ }
+
+ //--------------there is an anonymous type declaration-----------------
+ if (enclosingInstance != null) {
+ if ((enclosingInstTb = enclosingInstance.resolveType(scope)) == null)
+ return null;
+ if (enclosingInstTb.isBaseType() | enclosingInstTb.isArrayType()) {
+ scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(
+ enclosingInstTb,
+ enclosingInstance);
+ return null;
+ }
+ }
+ // due to syntax-construction, recType is a ReferenceBinding
+ recType =
+ (enclosingInstance == null)
+ ? type.resolveType(scope)
+ : ((SingleTypeReference) type).resolveTypeEnclosing(
+ scope,
+ (ReferenceBinding) enclosingInstTb);
+ if (recType == null)
+ return null;
+ if (((ReferenceBinding) recType).isFinal()) {
+ scope.problemReporter().anonymousClassCannotExtendFinalClass(type, recType);
+ return null;
+ }
+ TypeBinding[] argumentTypes = NoParameters;
+ if (arguments != null) {
+ int length = arguments.length;
+ argumentTypes = new TypeBinding[length];
+ for (int i = 0; i < length; i++)
+ if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
+ return null;
+ }
+
+ // an anonymous class inherits from java.lang.Object when declared "after" an interface
+ ReferenceBinding superBinding =
+ recType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) recType;
+ MethodBinding inheritedBinding =
+ scope.getConstructor(superBinding, argumentTypes, this);
+ if (!inheritedBinding.isValidBinding()) {
+ if (inheritedBinding.declaringClass == null)
+ inheritedBinding.declaringClass = superBinding;
+ scope.problemReporter().invalidConstructor(this, inheritedBinding);
+ return null;
+ }
+ if (enclosingInstance != null) {
+ if (!scope
+ .areTypesCompatible(
+ enclosingInstTb,
+ inheritedBinding.declaringClass.enclosingType())) {
+ scope.problemReporter().typeMismatchErrorActualTypeExpectedType(
+ enclosingInstance,
+ enclosingInstTb,
+ inheritedBinding.declaringClass.enclosingType());
+ return null;
+ }
+ }
+
+ // 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]);
+
+ // Update the anonymous inner class : superclass, interface
+ scope.addAnonymousType(anonymousType, (ReferenceBinding) recType);
+ anonymousType.resolve(scope);
+ binding = anonymousType.createsInternalConstructorWithBinding(inheritedBinding);
+ return anonymousType.binding; // 1.2 change
+ }
+
+ public String toStringExpression(int tab) {
+
+ String s = ""; //$NON-NLS-1$
+ if (enclosingInstance != null)
+ s += enclosingInstance.toString() + "."; //$NON-NLS-1$
+ s += super.toStringExpression(tab);
+ if (anonymousType != null) {
+ s += anonymousType.toString(tab);
+ } //allows to restart just after the } one line under ....
+ return s;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+
+ 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class QualifiedNameReference extends NameReference {
+
+ public char[][] tokens;
+ 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,
+ int sourceStart,
+ int sourceEnd) {
+ super();
+ tokens = sources;
+ this.sourceStart = sourceStart;
+ this.sourceEnd = sourceEnd;
+ }
+ public FlowInfo analyseAssignment(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo,
+ Assignment assignment,
+ boolean isCompound) {
+
+ if (assignment.expression != null) {
+ flowInfo =
+ assignment
+ .expression
+ .analyseCode(currentScope, flowContext, flowInfo)
+ .unconditionalInits();
+ }
+ // 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;
+ int indexOfFirstValueRequired = otherBindingsCount;
+ while (indexOfFirstValueRequired > 0) {
+ FieldBinding otherBinding = otherBindings[indexOfFirstValueRequired - 1];
+ if (otherBinding.isStatic())
+ break; // no longer need any value before this point
+ indexOfFirstValueRequired--;
+ }
+ FieldBinding lastFieldBinding = null;
+ if ((bits & FIELD) != 0) {
+ // reading from a field
+ // check if final blank field
+ if ((lastFieldBinding = (FieldBinding) binding).isFinal()
+ && currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) {
+ if (!flowInfo.isDefinitelyAssigned(lastFieldBinding)) {
+ currentScope.problemReporter().uninitializedBlankFinalField(
+ lastFieldBinding,
+ this);
+ }
+ }
+ } else {
+ if ((bits & LOCAL) != 0) {
+ // first binding is a local variable
+ LocalVariableBinding localBinding;
+ if (!flowInfo
+ .isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+ currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
+ }
+ if (!flowInfo.isFakeReachable())
+ localBinding.used = true;
+ }
+ }
+ if (indexOfFirstValueRequired == 0) {
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ // only for first binding
+ }
+ // all intermediate field accesses are read accesses
+ if (otherBindings != null) {
+ int start = indexOfFirstValueRequired == 0 ? 0 : indexOfFirstValueRequired - 1;
+ for (int i = start; i < otherBindingsCount; i++) {
+ if (lastFieldBinding != null) { // could be null if first was a local variable
+ TypeBinding lastReceiverType;
+ switch(i){
+ case 0 :
+ lastReceiverType = this.actualReceiverType;
+ break;
+ case 1 :
+ lastReceiverType = ((VariableBinding)binding).type;
+ break;
+ default :
+ lastReceiverType = otherBindings[i-1].type;
+ }
+ manageSyntheticReadAccessIfNecessary(
+ currentScope,
+ lastFieldBinding,
+ lastReceiverType,
+ i);
+ }
+ lastFieldBinding = otherBindings[i];
+ }
+ }
+ if (isCompound) {
+ if (binding == lastFieldBinding
+ && 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);
+ }
+ // the last field access is a write access
+ if (lastFieldBinding.isFinal()) {
+ // in a context where it can be assigned?
+ if (currentScope.allowBlankFinalFieldAssignment(lastFieldBinding)) {
+ if (flowInfo.isPotentiallyAssigned(lastFieldBinding)) {
+ if (indexOfFirstFieldBinding == 1) {
+ // was an implicit reference to the first field binding
+ currentScope.problemReporter().duplicateInitializationOfBlankFinalField(
+ lastFieldBinding,
+ this);
+ } else {
+ currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this);
+ // attempting to assign a non implicit reference
+ }
+ }
+ flowInfo.markAsDefinitelyAssigned(lastFieldBinding);
+ flowContext.recordSettingFinal(lastFieldBinding, this);
+ } else {
+ currentScope.problemReporter().cannotAssignToFinalField(lastFieldBinding, this);
+ }
+ }
+ // 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);
+
+ 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;
+ int indexOfFirstValueRequired;
+ if (valueRequired) {
+ indexOfFirstValueRequired = otherBindingsCount;
+ while (indexOfFirstValueRequired > 0) {
+ FieldBinding otherBinding = otherBindings[indexOfFirstValueRequired - 1];
+ if (otherBinding.isStatic())
+ break; // no longer need any value before this point
+ indexOfFirstValueRequired--;
+ }
+ } else {
+ indexOfFirstValueRequired = otherBindingsCount + 1;
+ }
+ switch (bits & RestrictiveFlagMASK) {
+ case FIELD : // reading a field
+ if (indexOfFirstValueRequired == 0) {
+ manageSyntheticReadAccessIfNecessary(currentScope, (FieldBinding) binding, this.actualReceiverType, 0);
+ }
+ // check if reading a final blank field
+ FieldBinding fieldBinding;
+ if ((fieldBinding = (FieldBinding) binding).isFinal()
+ && (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.isFakeReachable())
+ localBinding.used = true;
+ }
+ if (indexOfFirstValueRequired == 0) {
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ // only for first binding
+ }
+ if (otherBindings != null) {
+ int start = indexOfFirstValueRequired == 0 ? 0 : indexOfFirstValueRequired - 1;
+ for (int i = start; i < otherBindingsCount; i++) {
+ manageSyntheticReadAccessIfNecessary(
+ currentScope,
+ otherBindings[i],
+ i == 0
+ ? ((VariableBinding)binding).type
+ : otherBindings[i-1].type,
+ i + 1);
+ }
+ }
+ 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.fieldDeclarationIndex != methodScope.NotInFieldDecl
+ && fieldBinding.id >= methodScope.fieldDeclarationIndex) {
+ 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, true);
+ 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, valueRequired);
+ if (valueRequired) {
+ if (lastFieldBinding.declaringClass == null) { // array length
+ codeStream.arraylength();
+ codeStream.generateImplicitConversion(implicitConversion);
+ } else {
+ if (lastFieldBinding.constant != NotAConstant) {
+ // 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);
+ }
+ }
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+ public void generateCompoundAssignment(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ Expression expression,
+ int operator,
+ int assignmentImplicitConversion,
+ boolean valueRequired) {
+
+ generateReadSequence(currentScope, codeStream, true);
+ 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, true);
+ 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,
+ boolean valueRequired) {
+ // determine the rank until which we now we do not need any actual value for the field access
+ int otherBindingsCount = this.otherCodegenBindings == null ? 0 : otherCodegenBindings.length;
+ int indexOfFirstValueRequired;
+ if (valueRequired) {
+ indexOfFirstValueRequired = otherBindingsCount;
+ while (indexOfFirstValueRequired > 0) {
+ FieldBinding otherBinding = this.otherCodegenBindings[indexOfFirstValueRequired - 1];
+ if (otherBinding.isStatic() || otherBinding.constant != NotAConstant)
+ break; // no longer need any value before this point
+ indexOfFirstValueRequired--;
+ }
+ } else {
+ indexOfFirstValueRequired = otherBindingsCount + 1;
+ }
+ if (indexOfFirstValueRequired == 0) {
+ switch (bits & RestrictiveFlagMASK) {
+ case FIELD :
+ lastFieldBinding = (FieldBinding) this.codegenBinding;
+ // if first field is actually constant, we can inline it
+ if (lastFieldBinding.constant != NotAConstant) {
+ codeStream.generateConstant(lastFieldBinding.constant, 0);
+ // no implicit conversion
+ lastFieldBinding = null; // will not generate it again
+ break;
+ }
+ if (!lastFieldBinding.isStatic()) {
+ if ((bits & DepthMASK) != 0) {
+ Object[] emulationPath =
+ currentScope.getExactEmulationPath(
+ currentScope.enclosingSourceType().enclosingTypeAt(
+ (bits & DepthMASK) >> DepthSHIFT));
+ if (emulationPath == null) {
+ // internal error, per construction we should have found it
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(emulationPath, this, currentScope);
+ }
+ } else {
+ generateReceiver(codeStream);
+ }
+ }
+ break;
+ case LOCAL : // reading the first local variable
+ lastFieldBinding = null;
+ 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);
+ if (path == null) {
+ // emulation was not possible (should not happen per construction)
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(path, this, currentScope);
+ }
+ } else {
+ codeStream.load(localBinding);
+ }
+ }
+ }
+ } else {
+ lastFieldBinding = null;
+ }
+ // all intermediate field accesses are read accesses
+ // only the last field binding is a write access
+ if (this.otherCodegenBindings != null) {
+ int start = indexOfFirstValueRequired == 0 ? 0 : indexOfFirstValueRequired - 1;
+ for (int i = start; i < otherBindingsCount; i++) {
+ if (lastFieldBinding != null) {
+ MethodBinding accessor =
+ syntheticReadAccessors == null ? null : syntheticReadAccessors[i];
+ if (accessor == null)
+ if (lastFieldBinding.isStatic())
+ codeStream.getstatic(lastFieldBinding);
+ else
+ codeStream.getfield(lastFieldBinding);
+ else
+ codeStream.invokestatic(accessor);
+ }
+ lastFieldBinding = otherCodegenBindings[i];
+ }
+ }
+ }
+ 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)
+ if ((bits & FIELD) != 0) {
+ if (!((FieldBinding) binding).isStatic()) {
+ //must check for the static status....
+ if (indexOfFirstFieldBinding == 1) {
+ //the field is the first token of the qualified reference....
+ if (scope.methodScope().isStatic) {
+ scope.problemReporter().staticFieldAccessToNonStaticVariable(
+ this,
+ (FieldBinding) binding);
+ return null;
+ }
+ } else { //accessing to a field using a type as "receiver" is allowed only with static field
+ scope.problemReporter().staticFieldAccessToNonStaticVariable(
+ this,
+ (FieldBinding) binding);
+ return null;
+ }
+ }
+ if (isFieldUseDeprecated((FieldBinding) binding, scope))
+ scope.problemReporter().deprecatedField((FieldBinding) binding, this);
+ }
+ TypeBinding type = ((VariableBinding) binding).type;
+ int index = indexOfFirstFieldBinding;
+ int length = tokens.length;
+ if (index == length) { // restrictiveFlag == FIELD
+ constant =
+ FieldReference.getConstantFor((FieldBinding) binding, false, this, scope, index - 1);
+ 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)
+ constant =
+ ((bits & FIELD) != 0)
+ ? FieldReference.getConstantFor((FieldBinding) binding, false, this, scope, index - 1)
+ : ((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()) {
+ if (isFieldUseDeprecated(field, scope))
+ scope.problemReporter().deprecatedField(field, this);
+ Constant someConstant =
+ FieldReference.getConstantFor(field, false, this, scope, place);
+ // constant propagation can only be performed as long as the previous one is a constant too.
+ if (constant != NotAConstant) {
+ constant = someConstant;
+ }
+ 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) {
+ //If inlinable field, forget the access emulation, the code gen will directly target it
+ if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) {
+ return;
+ }
+ switch (bits & RestrictiveFlagMASK) {
+ case FIELD :
+ FieldBinding fieldBinding;
+ if ((fieldBinding = (FieldBinding) binding).isStatic()
+ || (fieldBinding.constant != NotAConstant))
+ return;
+ ReferenceBinding compatibleType = currentScope.enclosingSourceType();
+ // the declaringClass of the target binding must be compatible with the enclosing
+ // type at <depth> levels outside
+ for (int i = 0, depth = (bits & DepthMASK) >> DepthSHIFT; i < depth; i++) {
+ compatibleType = compatibleType.enclosingType();
+ }
+ currentScope.emulateOuterAccess(compatibleType, false);
+ // request cascade of accesses
+ break;
+ case LOCAL :
+ currentScope.emulateOuterAccess((LocalVariableBinding) binding);
+ }
+ }
+ public void manageSyntheticReadAccessIfNecessary(
+ BlockScope currentScope,
+ FieldBinding fieldBinding,
+ TypeBinding lastReceiverType,
+ int index) {
+ // 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 1.4 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.complianceLevel >= CompilerOptions.JDK1_4
+ && (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) {
+ 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 1.4 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.complianceLevel >= CompilerOptions.JDK1_4
+ && (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);
+ }
+ }
+
+ }
+ /**
+ * 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))
+ .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 getOtherFieldBindings(scope);
+ }
+ if (binding instanceof FieldBinding) {
+ // check for forward references
+ FieldBinding fieldBinding = (FieldBinding) binding;
+ MethodScope methodScope = scope.methodScope();
+ if (methodScope.enclosingSourceType() == fieldBinding.declaringClass
+ && methodScope.fieldDeclarationIndex != methodScope.NotInFieldDecl
+ && fieldBinding.id >= methodScope.fieldDeclarationIndex) {
+ if ((!fieldBinding.isStatic() || methodScope.isStatic)
+ && this.indexOfFirstFieldBinding == 1)
+ scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
+ }
+ bits &= ~RestrictiveFlagMASK; // clear bits
+ bits |= FIELD;
+ return getOtherFieldBindings(scope);
+ }
+ // thus it was a type
+ bits &= ~RestrictiveFlagMASK; // clear bits
+ bits |= TYPE;
+ case TYPE : //=============only type ==============
+ //deprecated test
+ if (isTypeUseDeprecated((TypeBinding) binding, scope))
+ scope.problemReporter().deprecatedType((TypeBinding) binding, this);
+ return (TypeBinding) binding;
+ }
+ }
+ //========error cases===============
+ return this.reportError(scope);
+ }
+ public void setFieldIndex(int index) {
+ this.indexOfFirstFieldBinding = index;
+ }
+ public String toStringExpression() {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < tokens.length; i++) {
+ buffer.append(tokens[i]);
+ if (i < (tokens.length - 1)) {
+ buffer.append("."); //$NON-NLS-1$
+ }
+ }
+ return buffer.toString();
+ }
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+ }
+ public String unboundReferenceErrorName() {
+ return new String(tokens[0]);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.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 TypeBinding resolveType(BlockScope scope) {
+
+ super.resolveType(scope);
+ if (currentCompatibleType == null)
+ return null; // error case
+
+ if (scope.isJavaLangObject(currentCompatibleType)) {
+ scope.problemReporter().cannotUseSuperInJavaLangObject(this);
+ return null;
+ }
+ return currentCompatibleType.superclass();
+ }
+
+ public String toStringExpression() {
+
+ return qualification.toString(0) + ".super"; //$NON-NLS-1$
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ qualification.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class QualifiedThisReference extends ThisReference {
+
+ public TypeReference qualification;
+ ReferenceBinding currentCompatibleType;
+
+ public QualifiedThisReference(TypeReference name, int pos, int sourceEnd) {
+
+ qualification = name;
+ this.sourceEnd = sourceEnd;
+ this.sourceStart = name.sourceStart;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ return flowInfo;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo,
+ boolean valueRequired) {
+
+ if (valueRequired) {
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ }
+ return flowInfo;
+ }
+
+ protected boolean checkAccess(
+ MethodScope methodScope,
+ TypeBinding targetType) {
+
+ // 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().incorrectEnclosingInstanceReference(
+ this,
+ targetType);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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.getExactEmulationPath(currentCompatibleType);
+ if (emulationPath == null) {
+ // internal error, per construction we should have found it
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(emulationPath, this, currentScope);
+ }
+ } else {
+ // nothing particular after all
+ codeStream.aload_0();
+ }
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
+
+ currentScope.emulateOuterAccess(
+ (SourceTypeBinding) currentCompatibleType,
+ false);
+ // request cascade of accesses
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+
+ constant = NotAConstant;
+ TypeBinding qualificationTb = qualification.resolveType(scope);
+ if (qualificationTb == 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;
+ currentCompatibleType = scope.referenceType().binding;
+ while (currentCompatibleType != null
+ && currentCompatibleType != qualificationTb) {
+ depth++;
+ currentCompatibleType =
+ currentCompatibleType.isStatic() ? null : currentCompatibleType.enclosingType();
+ }
+ bits &= ~DepthMASK; // flush previous depth if any
+ bits |= (depth & 0xFF) << DepthSHIFT; // encoded depth into 8 bits
+
+ if (currentCompatibleType == null) {
+ scope.problemReporter().incorrectEnclosingInstanceReference(
+ this,
+ qualificationTb);
+ return null;
+ }
+
+ // Ensure one cannot write code like: B() { super(B.this); }
+ if (depth == 0) {
+ if (!checkAccess(scope.methodScope(), qualificationTb))
+ return null;
+ } else {
+ // Could also be targeting an enclosing instance inside a super constructor invocation
+ // class X {
+ // public X(int i) {
+ // this(new Object() { Object obj = X.this; });
+ // }
+ // }
+
+ MethodScope methodScope = scope.methodScope();
+ while (methodScope != null) {
+ if (methodScope.enclosingSourceType() == currentCompatibleType) {
+ if (!this.checkAccess(methodScope, qualificationTb))
+ return null;
+ break;
+ }
+ methodScope = methodScope.parent.methodScope();
+ }
+ }
+ return qualificationTb;
+ }
+
+ public String toStringExpression() {
+
+ return qualification.toString(0) + ".this"; //$NON-NLS-1$
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ qualification.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.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 tb , long[] poss) {
+ this(sources,poss);
+ binding = tb;
+}
+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 (binding != null)
+ return binding;
+ return scope.getType(tokens);
+}
+public char[][] getTypeName(){
+
+ return tokens;
+}
+public String toStringExpression(int tab) {
+ StringBuffer buffer = new StringBuffer();
+ for (int i = 0; i < tokens.length; i++) {
+ buffer.append(tokens[i]);
+ if (i < (tokens.length - 1)) {
+ buffer.append("."); //$NON-NLS-1$
+ }
+ }
+ return buffer.toString();
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+public abstract class Reference extends Expression {
+/**
+ * BaseLevelReference constructor comment.
+ */
+public Reference() {
+ super();
+}
+public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) {
+ throw new ShouldNotImplement(Util.bind("ast.variableShouldProvide")); //$NON-NLS-1$
+}
+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 void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
+ throw new ShouldNotImplement(Util.bind("ast.compoundPreShouldProvide")); //$NON-NLS-1$
+}
+public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
+ throw new ShouldNotImplement(Util.bind("ast.compoundVariableShouldProvide")); //$NON-NLS-1$
+}
+public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
+ throw new ShouldNotImplement(Util.bind("ast.postIncrShouldProvide")); //$NON-NLS-1$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class ReturnStatement extends Statement {
+ public Expression expression;
+
+ public TypeBinding expressionType;
+ public boolean isSynchronized;
+ public AstNode[] subroutines;
+ 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;
+ while (true) {
+ AstNode sub;
+ if ((sub = traversedContext.subRoutine()) != null) {
+ if (this.subroutines == null){
+ this.subroutines = new AstNode[maxSub];
+ }
+ if (subIndex == maxSub) {
+ System.arraycopy(this.subroutines, 0, (this.subroutines = new AstNode[maxSub *= 2]), 0, subIndex); // grow
+ }
+ this.subroutines[subIndex++] = sub;
+ if (sub.cannotReturn()) {
+ saveValueNeeded = false;
+ break;
+ }
+ }
+ AstNode node;
+
+ if ((node = traversedContext.associatedNode) instanceof SynchronizedStatement) {
+ isSynchronized = true;
+
+ } else if (node instanceof TryStatement && hasValueToSave) {
+ if (this.saveValueVariable == null){ // closest subroutine secret variable is used
+ prepareSaveValueLocation((TryStatement)node);
+ }
+ saveValueNeeded = true;
+
+ } else if (traversedContext instanceof InitializationFlowContext) {
+ currentScope.problemReporter().cannotReturnInInitializer(this);
+ return FlowInfo.DeadEnd;
+ }
+
+ // remember the initialization at this
+ // point for dealing with blank final variables.
+ traversedContext.recordReturnFrom(flowInfo.unconditionalInits());
+
+ FlowContext parentContext;
+ if ((parentContext = traversedContext.parent) == null) { // top-context
+ break;
+ } else {
+ traversedContext = parentContext;
+ }
+ }
+ // resize subroutines
+ if ((subroutines != null) && (subIndex != maxSub)) {
+ System.arraycopy(subroutines, 0, (subroutines = new AstNode[subIndex]), 0, subIndex);
+ }
+
+ // secret local variable for return value (note that this can only occur in a real method)
+ if (saveValueNeeded) {
+ if (this.saveValueVariable != null) {
+ this.saveValueVariable.used = true;
+ }
+ } else {
+ this.saveValueVariable = null;
+ if ((!isSynchronized) && (expressionType == BooleanBinding)) {
+ this.expression.bits |= ValueForReturnMASK;
+ }
+ }
+ return FlowInfo.DeadEnd;
+}
+
+/**
+ * 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(currentScope, codeStream);
+ }
+
+ // generation of code responsible for invoking the finally blocks in sequence
+ if (subroutines != null) {
+ for (int i = 0, max = subroutines.length; i < max; i++) {
+ AstNode sub;
+ if ((sub = subroutines[i]) instanceof SynchronizedStatement) {
+ codeStream.load(((SynchronizedStatement) sub).synchroVariable);
+ codeStream.monitorexit();
+ } else {
+ TryStatement trySub = (TryStatement) sub;
+ if (trySub.subRoutineCannotReturn) {
+ codeStream.goto_(trySub.subRoutineStartLabel);
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ } else {
+ codeStream.jsr(trySub.subRoutineStartLabel);
+ }
+ }
+ }
+ }
+ if (saveValueVariable != null) codeStream.load(saveValueVariable);
+
+ if ((expression != null) && (expression.constant != NotAConstant)) {
+ codeStream.generateConstant(expression.constant, expression.implicitConversion);
+ generateStoreSaveValueIfNecessary(currentScope, codeStream);
+ }
+ // output the suitable return bytecode or wrap the value inside a descriptor for doits
+ this.generateReturnBytecode(currentScope, codeStream);
+
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+/**
+ * Dump the suitable return bytecode for a return statement
+ *
+ */
+public void generateReturnBytecode(BlockScope currentScope, 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(BlockScope currentScope, 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 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 && scope.areTypesCompatible(expressionType, methodType)) {
+ expression.implicitWidening(methodType, expressionType);
+ return;
+ }
+ if (methodType != null){
+ scope.problemReporter().typeMismatchErrorActualTypeExpectedType(expression, expressionType, methodType);
+ }
+}
+public String toString(int tab){
+
+ String s = tabString(tab) ;
+ s = s + "return "; //$NON-NLS-1$
+ if (expression != null )
+ s = s + expression.toStringExpression() ;
+ return s;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ if (expression != null)
+ expression.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+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) {
+
+ // 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).isFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
+ if (!flowInfo.isDefinitelyAssigned(fieldBinding)) {
+ currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this);
+ // we could improve error msg here telling "cannot use compound assignment on final blank field"
+ }
+ }
+ manageSyntheticReadAccessIfNecessary(currentScope);
+ break;
+ case LOCAL : // reading a local variable
+ // check if assigning a final blank field
+ LocalVariableBinding localBinding;
+ if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) {
+ currentScope.problemReporter().uninitializedLocalVariable(localBinding, this);
+ // we could improve error msg here telling "cannot use compound assignment on final local variable"
+ }
+ if (!flowInfo.isFakeReachable()) localBinding.used = true;
+ }
+ }
+ if (assignment.expression != null) {
+ flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ }
+ switch (bits & RestrictiveFlagMASK) {
+ case FIELD : // assigning to a field
+ manageSyntheticWriteAccessIfNecessary(currentScope);
+
+ // check if assigning a final field
+ FieldBinding fieldBinding;
+ if ((fieldBinding = (FieldBinding) binding).isFinal()) {
+ // inside a context where allowed
+ if (currentScope.allowBlankFinalFieldAssignment(fieldBinding)) {
+ if (flowInfo.isPotentiallyAssigned(fieldBinding)) {
+ currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this);
+ }
+ flowInfo.markAsDefinitelyAssigned(fieldBinding);
+ flowContext.recordSettingFinal(fieldBinding, this);
+ } else {
+ currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this);
+ }
+ }
+ break;
+ case LOCAL : // assigning to a local variable
+ LocalVariableBinding localBinding = (LocalVariableBinding) binding;
+ if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes
+ bits |= FirstAssignmentToLocalMASK;
+ } else {
+ bits &= ~FirstAssignmentToLocalMASK;
+ }
+ if (localBinding.isFinal()) {
+ if ((bits & DepthMASK) == 0) {
+ if (flowInfo.isPotentiallyAssigned(localBinding)) {
+ currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this);
+ }
+ flowContext.recordSettingFinal(localBinding, this);
+ } else {
+ currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this);
+ }
+ }
+ flowInfo.markAsDefinitelyAssigned(localBinding);
+ }
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ return flowInfo;
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ return analyseCode(currentScope, flowContext, flowInfo, true);
+}
+public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) {
+
+ switch (bits & RestrictiveFlagMASK) {
+ case FIELD : // reading a field
+ if (valueRequired) {
+ manageSyntheticReadAccessIfNecessary(currentScope);
+ }
+ // check if reading a final blank field
+ FieldBinding fieldBinding;
+ if ((fieldBinding = (FieldBinding) binding).isFinal() && 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.isFakeReachable()) localBinding.used = true;
+ }
+ if (valueRequired) {
+ manageEnclosingInstanceAccessIfNecessary(currentScope);
+ }
+ 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 null;
+ }
+ }
+ constant = FieldReference.getConstantFor(fieldBinding, true, this, scope, 0);
+ if (isFieldUseDeprecated(fieldBinding, scope))
+ scope.problemReporter().deprecatedField(fieldBinding, this);
+
+ //===============================================
+ //cycle are forbidden ONLY within the same class...why ?????? (poor javac....)
+ //Cycle can be done using cross class ref but not direct into a same class reference ????
+ //class A { static int k = B.k+1;}
+ //class B { static int k = A.k+2;}
+ //The k-cycle in this example is valid.
+
+ //class C { static int k = k + 1 ;}
+ //here it is forbidden ! ????
+ //but the next one is valid !!!
+ //class C { static int k = C.k + 1;}
+
+ //notice that the next one is also valid ?!?!
+ //class A { static int k = foo().k+1 ; static A foo(){return new A();}}
+
+ //for all these reasons, the next piece of code is only here and not
+ //commun for all FieldRef and QualifiedNameRef....(i.e. in the getField(..) API.....
+
+ //instance field may refer to forward static field, like in
+ //int i = staticI;
+ //static int staticI = 2 ;
+
+ MethodScope ms = scope.methodScope();
+ if (ms.enclosingSourceType() == fieldBinding.declaringClass
+ && ms.fieldDeclarationIndex != ms.NotInFieldDecl
+ && fieldBinding.id >= ms.fieldDeclarationIndex) {
+ //if the field is static and ms is not .... then it is valid
+ if (!fieldBinding.isStatic() || ms.isStatic)
+ scope.problemReporter().forwardReference(this, 0, scope.enclosingSourceType());
+ }
+ //====================================================
+
+ return fieldBinding.type;
+
+}
+public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
+
+ // optimizing assignment like: i = i + 1 or i = 1 + i
+ if (assignment.expression.isCompactableOperation()) {
+ BinaryExpression operation = (BinaryExpression) assignment.expression;
+ SingleNameReference variableReference;
+ if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == binding)) {
+ // i = i + value, then use the variable on the right hand side, since it has the correct implicit conversion
+ variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.right, (operation.bits & OperatorMASK) >> OperatorSHIFT, operation.left.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
+ return;
+ }
+ int operator = (operation.bits & OperatorMASK) >> OperatorSHIFT;
+ if ((operation.right instanceof SingleNameReference)
+ && ((operator == PLUS) || (operator == MULTIPLY)) // only commutative operations
+ && ((variableReference = (SingleNameReference) operation.right).binding == binding)
+ && (operation.left.constant != NotAConstant) // exclude non constant expressions, since could have side-effect
+ && ((operation.left.implicitConversion >> 4) != T_String) // exclude string concatenation which would occur backwards
+ && ((operation.right.implicitConversion >> 4) != T_String)) { // exclude string concatenation which would occur backwards
+ // i = value + i, then use the variable on the right hand side, since it has the correct implicit conversion
+ variableReference.generateCompoundAssignment(currentScope, codeStream, syntheticAccessors == null ? null : syntheticAccessors[WRITE], operation.left, operator, operation.right.implicitConversion /*should be equivalent to no conversion*/, valueRequired);
+ return;
+ }
+ }
+ switch (bits & RestrictiveFlagMASK) {
+ case FIELD : // assigning to a field
+ FieldBinding fieldBinding;
+ if (!(fieldBinding = (FieldBinding) this.codegenBinding).isStatic()) { // need a receiver?
+ if ((bits & DepthMASK) != 0) {
+ Object[] emulationPath = currentScope.getExactEmulationPath(currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT));
+ if (emulationPath == null) {
+ // internal error, per construction we should have found it
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(emulationPath, this, 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;
+ }
+ // 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) {
+ Object[] emulationPath = currentScope.getExactEmulationPath(currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT));
+ if (emulationPath == null) {
+ // internal error, per construction we should have found it
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(emulationPath, this, 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);
+ if (path == null) {
+ // emulation was not possible (should not happen per construction)
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(path, this, 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) {
+ Object[] emulationPath = currentScope.getExactEmulationPath(currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT));
+ if (emulationPath == null) {
+ // internal error, per construction we should have found it
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(emulationPath, this, 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) {
+ Object[] emulationPath = currentScope.getExactEmulationPath(currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT));
+ if (emulationPath == null) {
+ // internal error, per construction we should have found it
+ currentScope.problemReporter().needImplementation();
+ } else {
+ codeStream.generateOuterAccess(emulationPath, this, 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) {
+
+ //If inlinable field, forget the access emulation, the code gen will directly target it
+ if (((bits & DepthMASK) == 0) || (constant != NotAConstant)) return;
+
+ switch (bits & RestrictiveFlagMASK) {
+ case FIELD :
+ FieldBinding fieldBinding;
+ if ((fieldBinding = (FieldBinding)binding).isStatic() || (fieldBinding.constant != NotAConstant)) return;
+ ReferenceBinding compatibleType = currentScope.enclosingSourceType();
+ // the declaringClass of the target binding must be compatible with the enclosing
+ // type at <depth> levels outside
+ for (int i = 0, depth = (bits & DepthMASK) >> DepthSHIFT; i < depth; i++) {
+ compatibleType = compatibleType.enclosingType();
+ }
+ currentScope.emulateOuterAccess(compatibleType, false); // request cascade of accesses
+ break;
+ case LOCAL :
+ currentScope.emulateOuterAccess((LocalVariableBinding) binding);
+ }
+}
+public void manageSyntheticReadAccessIfNecessary(BlockScope currentScope) {
+
+ //If inlinable field, forget the access emulation, the code gen will directly target it
+ if (constant != NotAConstant)
+ return;
+
+ if ((bits & FIELD) != 0) {
+ FieldBinding fieldBinding = (FieldBinding) binding;
+ if (((bits & DepthMASK) != 0)
+ && (fieldBinding.isPrivate() // private access
+ || (fieldBinding.isProtected() // implicit protected access
+ && fieldBinding.declaringClass.getPackage()
+ != currentScope.enclosingSourceType().getPackage()))) {
+ if (syntheticAccessors == null)
+ syntheticAccessors = new MethodBinding[2];
+ syntheticAccessors[READ] =
+ ((SourceTypeBinding)currentScope.enclosingSourceType().
+ enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
+ addSyntheticMethod(fieldBinding, true);
+ currentScope.problemReporter().needToEmulateFieldReadAccess(fieldBinding, this);
+ return;
+ }
+ // if the binding declaring class is not visible, need special action
+ // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+ // NOTE: from 1.4 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.complianceLevel >= CompilerOptions.JDK1_4
+ && !fieldBinding.isStatic()
+ && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+ || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+ this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+ }
+ }
+}
+public void manageSyntheticWriteAccessIfNecessary(BlockScope currentScope) {
+
+ if ((bits & FIELD) != 0) {
+ FieldBinding fieldBinding = (FieldBinding) binding;
+ if (((bits & DepthMASK) != 0)
+ && (fieldBinding.isPrivate() // private access
+ || (fieldBinding.isProtected() // implicit protected access
+ && fieldBinding.declaringClass.getPackage()
+ != currentScope.enclosingSourceType().getPackage()))) {
+ if (syntheticAccessors == null)
+ syntheticAccessors = new MethodBinding[2];
+ syntheticAccessors[WRITE] =
+ ((SourceTypeBinding)currentScope.enclosingSourceType().
+ enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).
+ addSyntheticMethod(fieldBinding, false);
+ currentScope.problemReporter().needToEmulateFieldWriteAccess(fieldBinding, this);
+ return;
+ }
+ // if the binding declaring class is not visible, need special action
+ // for runtime compatibility on 1.2 VMs : change the declaring class of the binding
+ // NOTE: from 1.4 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.complianceLevel >= CompilerOptions.JDK1_4
+ && !fieldBinding.isStatic()
+ && fieldBinding.declaringClass.id != T_Object) // no change for Object fields (if there was any)
+ || !fieldBinding.declaringClass.canBeSeenBy(currentScope))){
+ this.codegenBinding = currentScope.enclosingSourceType().getUpdatedFieldBinding(fieldBinding, (ReferenceBinding)this.actualReceiverType);
+ }
+ }
+}
+public TypeBinding reportError(BlockScope scope) {
+ //=====error cases=======
+ constant = Constant.NotAConstant;
+ if (binding instanceof ProblemFieldBinding) {
+ scope.problemReporter().invalidField(this, (FieldBinding) binding);
+ } else if (binding instanceof ProblemReferenceBinding) {
+ scope.problemReporter().invalidType(this, (TypeBinding) binding);
+ } else {
+ scope.problemReporter().unresolvableReference(this, binding);
+ }
+ return null;
+}
+public TypeBinding resolveType(BlockScope scope) {
+ // for code gen, harm the restrictiveFlag
+
+ this.actualReceiverType = this.receiverType = scope.enclosingSourceType();
+
+ if ((this.codegenBinding = this.binding = scope.getBinding(token, bits & RestrictiveFlagMASK, this)).isValidBinding()) {
+ switch (bits & RestrictiveFlagMASK) {
+ case VARIABLE : // =========only variable============
+ case VARIABLE | TYPE : //====both variable and type============
+ if (binding instanceof VariableBinding) {
+ VariableBinding vb = (VariableBinding) binding;
+ if (binding instanceof LocalVariableBinding) {
+ bits &= ~RestrictiveFlagMASK; // clear bits
+ bits |= LOCAL;
+ constant = vb.constant;
+ if ((!vb.isFinal()) && ((bits & DepthMASK) != 0))
+ scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)vb, this);
+ return vb.type;
+ }
+ // a field
+ return 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 (TypeBinding) binding;
+ }
+ }
+
+ // error scenarii
+ return this.reportError(scope);
+}
+public String toStringExpression(){
+
+ return new String(token);}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+public String unboundReferenceErrorName(){
+
+ return new String(token);}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.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 tb, long pos) {
+ this(source, pos) ;
+ binding = tb ;
+}
+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 (binding != null)
+ return binding;
+ return scope.getType(token);
+}
+public char [][] getTypeName() {
+ return new char[][] { token };
+}
+public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
+ ReferenceBinding memberTb = scope.getMemberType(token, enclosingType);
+ if (!memberTb.isValidBinding()) {
+ scope.problemReporter().invalidEnclosingType(this, memberTb, enclosingType);
+ return null;
+ }
+ if (isTypeUseDeprecated(memberTb, scope))
+ scope.problemReporter().deprecatedType(memberTb, this);
+ return binding = memberTb;
+}
+public String toStringExpression(int tab){
+ return new String(token) ;
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+public abstract class Statement extends AstNode {
+
+ /**
+ * Statement constructor comment.
+ */
+ public Statement() {
+ super();
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+ return flowInfo;
+ }
+
+ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+ throw new ShouldNotImplement(Util.bind("ast.missingStatement")); //$NON-NLS-1$
+ }
+
+ 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 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;
+ }
+
+ public void resetStateForCodeGeneration() {
+ }
+
+ /**
+ * INTERNAL USE ONLY.
+ * Do nothing by default. This is used to redirect inter-statements jumps.
+ */
+ public void branchChainTo(Label label) {
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.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);
+}
+/**
+ * Code generation for string 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.ldc(constant.stringValue());
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public TypeBinding literalType(BlockScope scope) {
+ return scope.getJavaLangString();
+}
+/**
+ * source method comment.
+ */
+public char[] source() {
+ return source;
+}
+public String toStringExpression() {
+
+ // handle some special char.....
+ StringBuffer result = new StringBuffer("\""); //$NON-NLS-1$
+ for (int i = 0; i < source.length; i++) {
+ switch (source[i]) {
+ case '\b' :
+ result.append("\\b"); //$NON-NLS-1$
+ break;
+ case '\t' :
+ result.append("\\t"); //$NON-NLS-1$
+ break;
+ case '\n' :
+ result.append("\\n"); //$NON-NLS-1$
+ break;
+ case '\f' :
+ result.append("\\f"); //$NON-NLS-1$
+ break;
+ case '\r' :
+ result.append("\\r"); //$NON-NLS-1$
+ break;
+ case '\"' :
+ result.append("\\\""); //$NON-NLS-1$
+ break;
+ case '\'' :
+ result.append("\\'"); //$NON-NLS-1$
+ break;
+ case '\\' : //take care not to display the escape as a potential real char
+ result.append("\\\\"); //$NON-NLS-1$
+ break;
+ default :
+ result.append(source[i]);
+ }
+ }
+ result.append("\""); //$NON-NLS-1$
+ return result.toString();
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.SourceTypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class SuperReference extends ThisReference {
+ public static final SuperReference Super = new SuperReference();
+
+/**
+ * SuperReference constructor comment.
+ */
+public SuperReference() {
+ super();
+}
+public SuperReference(int pos, int sourceEnd) {
+ super();
+ sourceStart = pos;
+ this.sourceEnd = sourceEnd;
+}
+public static ExplicitConstructorCall implicitSuperConstructorCall() {
+ return new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+}
+public boolean isSuper() {
+
+ return true;
+}
+public boolean isThis() {
+
+ return false ;
+}
+public TypeBinding resolveType(BlockScope scope) {
+ constant = NotAConstant;
+ if (!checkAccess(scope.methodScope()))
+ return null;
+ SourceTypeBinding enclosingTb = scope.enclosingSourceType();
+ if (scope.isJavaLangObject(enclosingTb)) {
+ scope.problemReporter().cannotUseSuperInJavaLangObject(this);
+ return null;
+ }
+ return enclosingTb.superclass;
+}
+public String toStringExpression(){
+
+ return "super"; //$NON-NLS-1$
+
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class SwitchStatement extends Statement {
+ public Expression testExpression;
+ public Statement[] statements;
+ public BlockScope scope;
+ public int explicitDeclarations;
+ public Label breakLabel;
+ public Case[] cases;
+ public DefaultCase defaultCase;
+ public int caseCount = 0;
+
+ // for local variables table attributes
+ int preSwitchInitStateIndex = -1;
+ int mergedInitStateIndex = -1;
+ /**
+ * SwitchStatement constructor comment.
+ */
+ public SwitchStatement() {
+ super();
+ }
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+ flowInfo = testExpression.analyseCode(currentScope, flowContext, flowInfo);
+ 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.DeadEnd;
+ // in case of statements before the first case
+ preSwitchInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(flowInfo);
+ int caseIndex = 0;
+ if (statements != null) {
+ for (int i = 0, max = statements.length; i < max; i++) {
+ Statement statement = statements[i];
+ if ((caseIndex < caseCount)
+ && (statement == cases[caseIndex])) { // statements[i] is a case or a default case
+ caseIndex++;
+ caseInits = caseInits.mergedWith(flowInfo.copy().unconditionalInits());
+ } else {
+ if (statement == defaultCase) {
+ caseInits = caseInits.mergedWith(flowInfo.copy().unconditionalInits());
+ }
+ }
+ if (!caseInits.complainIfUnreachable(statement, scope)) {
+ caseInits = statement.analyseCode(scope, switchContext, caseInits);
+ }
+ }
+ }
+
+ // 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;
+ }
+ /**
+ * 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) {
+ int[] sortedIndexes = new int[caseCount];
+ int[] localKeysCopy;
+ if ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ int pc = codeStream.position;
+
+ // prepare the labels and constants
+ breakLabel.codeStream = 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
+ testExpression.generateCode(currentScope, codeStream, needSwitch);
+
+ // generate the appropriate switch table
+ if (needSwitch) {
+ int max = localKeysCopy[caseCount - 1];
+ int min = localKeysCopy[0];
+ if ((long) (caseCount * 2.5) > ((long) max - (long) min)) {
+ 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
+ if (preSwitchInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ preSwitchInitStateIndex);
+ caseIndex++;
+ }
+ } else {
+ if (statement == defaultCase) { // statements[i] is a case or a default case
+ 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);
+ }
+
+
+ public void resetStateForCodeGeneration() {
+
+ this.breakLabel.resetStateForCodeGeneration();
+ }
+
+ public void resolve(BlockScope upperScope) {
+
+ TypeBinding testType = testExpression.resolveType(upperScope);
+ if (testType == null)
+ return;
+ testExpression.implicitWidening(testType, testType);
+ if (!(testExpression
+ .isConstantValueOfTypeAssignableToType(testType, IntBinding))) {
+ if (!upperScope.areTypesCompatible(testType, IntBinding)) {
+ upperScope.problemReporter().incorrectSwitchType(testExpression, 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 Case[length = statements.length];
+ int[] casesValues = new int[length];
+ int counter = 0;
+ for (int i = 0; i < length; i++) {
+ Constant cst;
+ if ((cst = statements[i].resolveCase(scope, testType, this)) != null) {
+ //----check for duplicate case statement------------
+ if (cst != NotAConstant) {
+ int key = cst.intValue();
+ for (int j = 0; j < counter; j++) {
+ if (casesValues[j] == key) {
+ scope.problemReporter().duplicateCase((Case) statements[i], cst);
+ }
+ }
+ casesValues[counter++] = key;
+ }
+ }
+ }
+ }
+ }
+ public String toString(int tab) {
+
+ String inFront, s = tabString(tab);
+ inFront = s;
+ s = s + "switch (" + testExpression.toStringExpression() + ") "; //$NON-NLS-1$ //$NON-NLS-2$
+ if (statements == null) {
+ s = s + "{}"; //$NON-NLS-1$
+ return s;
+ } else
+ s = s + "{"; //$NON-NLS-1$
+ s = s
+ + (explicitDeclarations != 0
+ ? "// ---scope needed for " //$NON-NLS-1$
+ + String.valueOf(explicitDeclarations)
+ + " locals------------ \n"//$NON-NLS-1$
+ : "// ---NO scope needed------ \n"); //$NON-NLS-1$
+
+ int i = 0;
+ String tabulation = " "; //$NON-NLS-1$
+ try {
+ while (true) {
+ //use instanceof in order not to polluate classes with behavior only needed for printing purpose.
+ if (statements[i] instanceof Expression)
+ s = s + "\n" + inFront + tabulation; //$NON-NLS-1$
+ if (statements[i] instanceof Break)
+ s = s + statements[i].toString(0);
+ else
+ s = s + "\n" + statements[i].toString(tab + 2); //$NON-NLS-1$
+ //=============
+ if ((statements[i] instanceof Case)
+ || (statements[i] instanceof DefaultCase)) {
+ i++;
+ while (!((statements[i] instanceof Case)
+ || (statements[i] instanceof DefaultCase))) {
+ if ((statements[i] instanceof Expression) || (statements[i] instanceof Break))
+ s = s + statements[i].toString(0) + " ; "; //$NON-NLS-1$
+ else
+ s = s + "\n" + statements[i].toString(tab + 6) + " ; "; //$NON-NLS-1$ //$NON-NLS-2$
+ i++;
+ }
+ } else {
+ s = s + " ;"; //$NON-NLS-1$
+ i++;
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ };
+ s = s + "}"; //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ testExpression.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);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class SynchronizedStatement extends Statement {
+
+ 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.used = true;
+
+ // simple propagation to subnodes
+ flowInfo =
+ block.analyseCode(
+ scope,
+ new InsideSubRoutineFlowContext(flowContext, this),
+ expression.analyseCode(scope, flowContext, flowInfo));
+
+ // optimizing code gen
+ if ((flowInfo == FlowInfo.DeadEnd) || flowInfo.isFakeReachable()) {
+ blockExit = true;
+ }
+ return flowInfo;
+ }
+
+ /**
+ * 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;
+ }
+ 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
+ ExceptionLabel anyExceptionHandler = new ExceptionLabel(codeStream, null);
+ //'null' denotes any kind of exception
+ 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
+ anyExceptionHandler.placeEnd();
+ anyExceptionHandler.place();
+ 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);
+ }
+
+ 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 String toString(int tab) {
+
+ String s = tabString(tab);
+ s = s + "synchronized (" + expression.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ s = s + "\n" + block.toString(tab + 1); //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ expression.traverse(visitor, scope);
+ block.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class ThisReference extends Reference {
+
+ public static final ThisReference ThisImplicit = new ThisReference();
+
+/**
+ * ThisReference constructor comment.
+ */
+public ThisReference() {
+ super();
+}
+public ThisReference(int s, int sourceEnd) {
+ this();
+ this.sourceStart = s ;
+ this.sourceEnd = sourceEnd;
+}
+protected 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;
+}
+public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+ int pc = codeStream.position;
+ if (valueRequired)
+ codeStream.aload_0();
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+}
+public boolean isThis() {
+
+ return true ;
+}
+public TypeBinding resolveType(BlockScope scope) {
+ // implicit this
+ constant = NotAConstant;
+ if (this != ThisImplicit && !checkAccess(scope.methodScope()))
+ return null;
+ return scope.enclosingSourceType();
+}
+public String toStringExpression(){
+
+ if (this == ThisImplicit) return "" ; //$NON-NLS-1$
+ return "this"; //$NON-NLS-1$
+}
+public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ visitor.visit(this, blockScope);
+ visitor.endVisit(this, blockScope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.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.DeadEnd;
+ }
+
+ /**
+ * 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 void resolve(BlockScope scope) {
+
+ exceptionType = exception.resolveTypeExpecting(scope, scope.getJavaLangThrowable());
+
+ if (exceptionType == NullBinding
+ && scope.environment().options.complianceLevel <= CompilerOptions.JDK1_3){
+ // if compliant with 1.4, this problem will not be reported
+ scope.problemReporter().cannotThrowNull(this);
+ }
+ exception.implicitWidening(exceptionType, exceptionType);
+ }
+
+ public String toString(int tab) {
+ String s = tabString(tab);
+ s = s + "throw "; //$NON-NLS-1$
+ s = s + exception.toStringExpression();
+ return s;
+ }
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
+ if (visitor.visit(this, blockScope))
+ exception.traverse(visitor, blockScope);
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
+import net.sourceforge.phpdt.internal.compiler.codegen.Label;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.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(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ visitor.visit(this, scope);
+ visitor.endVisit(this, scope);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class TryStatement extends Statement {
+
+ public Block tryBlock;
+ public Block[] catchBlocks;
+ public Argument[] catchArguments;
+ public Block finallyBlock;
+ BlockScope scope;
+
+ public boolean subRoutineCannotReturn = true;
+ // 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.used = true;
+ }
+ if (returnAddressVariable != null) {
+ returnAddressVariable.used = true;
+ }
+ 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.DeadEnd) || subInfo.isFakeReachable())) {
+ subRoutineCannotReturn = false;
+ }
+ }
+ // 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.statements == null) {
+ tryInfo = flowInfo;
+ tryBlockExit = false;
+ } else {
+ tryInfo = tryBlock.analyseCode(currentScope, handlingContext, flowInfo.copy());
+ tryBlockExit = (tryInfo == FlowInfo.DeadEnd) || tryInfo.isFakeReachable();
+ }
+
+ // check unreachable catch blocks
+ handlingContext.complainIfUnusedExceptionHandlers(catchBlocks, 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]."
+ */
+ if (tryBlock.statements == null) {
+ catchInfo.markAsFakeReachable(true);
+ }
+ catchInfo =
+ catchBlocks[i].analyseCode(
+ currentScope,
+ insideSubContext == null ? flowContext : insideSubContext,
+ catchInfo);
+ catchExits[i] =
+ ((catchInfo == FlowInfo.DeadEnd) || catchInfo.isFakeReachable());
+ 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
+ tryInfo.addPotentialInitializationsFrom(insideSubContext.initsOnReturn);
+ finallyContext.complainOnRedundantFinalAssignments(tryInfo, currentScope);
+ if (subInfo == FlowInfo.DeadEnd) {
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(subInfo);
+ return subInfo;
+ } else {
+ FlowInfo mergedInfo = tryInfo.addInitializationsFrom(subInfo);
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
+ }
+ }
+
+ public boolean cannotReturn() {
+
+ return subRoutineCannotReturn;
+ }
+
+ /**
+ * Try statement code generation
+ *
+ */
+ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
+
+ if ((bits & IsReachableMASK) == 0) {
+ return;
+ }
+ if (tryBlock.isEmptyBlock()) {
+ if (subRoutineStartLabel != null) {
+ // since not passing the finallyScope, the block generation will exitUserScope(finallyScope)
+ finallyBlock.generateCode(scope, codeStream);
+ }
+ // May loose some local variable initializations : affecting the local variable attributes
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ // no local bytecode produced so no need for position remembering
+ return;
+ }
+ int pc = codeStream.position;
+ Label endLabel = new Label(codeStream);
+ boolean requiresNaturalJsr = false;
+
+ // preparing exception labels
+ int maxCatches;
+ ExceptionLabel[] exceptionLabels =
+ new ExceptionLabel[maxCatches =
+ catchArguments == null ? 0 : catchArguments.length];
+ for (int i = 0; i < maxCatches; i++) {
+ boolean preserveCurrentHandler =
+ (preserveExceptionHandler[i
+ / ExceptionHandlingFlowContext.BitCacheSize]
+ & (1 << (i % ExceptionHandlingFlowContext.BitCacheSize)))
+ != 0;
+ if (preserveCurrentHandler) {
+ exceptionLabels[i] =
+ new ExceptionLabel(
+ codeStream,
+ (ReferenceBinding) catchArguments[i].binding.type);
+ }
+ }
+ ExceptionLabel anyExceptionLabel = null;
+ if (subRoutineStartLabel != null) {
+ subRoutineStartLabel.codeStream = codeStream;
+ anyExceptionLabel = new ExceptionLabel(codeStream, null);
+ }
+ // generate the try block
+ tryBlock.generateCode(scope, codeStream);
+ boolean tryBlockHasSomeCode = codeStream.position != pc;
+ // flag telling if some bytecodes were issued inside the try block
+
+ // natural exit: only if necessary
+ boolean nonReturningSubRoutine =
+ (subRoutineStartLabel != null) && subRoutineCannotReturn;
+ if ((!tryBlockExit) && tryBlockHasSomeCode) {
+ int position = codeStream.position;
+ if (nonReturningSubRoutine) {
+ codeStream.goto_(subRoutineStartLabel);
+ } else {
+ requiresNaturalJsr = true;
+ codeStream.goto_(endLabel);
+ }
+ codeStream.updateLastRecordedEndPC(position);
+ //goto is tagged as part of the try block
+ }
+ // place end positions of user-defined exception labels
+ if (tryBlockHasSomeCode) {
+ for (int i = 0; i < maxCatches; i++) {
+ boolean preserveCurrentHandler =
+ (preserveExceptionHandler[i
+ / ExceptionHandlingFlowContext.BitCacheSize]
+ & (1 << (i % ExceptionHandlingFlowContext.BitCacheSize)))
+ != 0;
+ if (preserveCurrentHandler) {
+ exceptionLabels[i].placeEnd();
+ }
+ }
+ /* generate sequence of handler, all starting by storing the TOS (exception
+ thrown) into their own catch variables, the one specified in the source
+ that must denote the handled exception.
+ */
+ if (catchArguments == null) {
+ if (anyExceptionLabel != null) {
+ anyExceptionLabel.placeEnd();
+ }
+ } else {
+ for (int i = 0; i < maxCatches; i++) {
+ boolean preserveCurrentHandler =
+ (preserveExceptionHandler[i
+ / ExceptionHandlingFlowContext.BitCacheSize]
+ & (1 << (i % ExceptionHandlingFlowContext.BitCacheSize)))
+ != 0;
+ if (preserveCurrentHandler) {
+ // May loose some local variable initializations : affecting the local variable attributes
+ if (preTryInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ preTryInitStateIndex);
+ }
+ exceptionLabels[i].place();
+ codeStream.incrStackSize(1);
+ // optimizing the case where the exception variable is not actually used
+ LocalVariableBinding catchVar;
+ int varPC = codeStream.position;
+ if ((catchVar = catchArguments[i].binding).resolvedPosition != -1) {
+ codeStream.store(catchVar, false);
+ catchVar.recordInitializationStartPC(codeStream.position);
+ codeStream.addVisibleLocalVariable(catchVar);
+ } else {
+ codeStream.pop();
+ }
+ codeStream.recordPositionsFrom(varPC, catchArguments[i].sourceStart);
+ // Keep track of the pcs at diverging point for computing the local attribute
+ // since not passing the catchScope, the block generation will exitUserScope(catchScope)
+ catchBlocks[i].generateCode(scope, codeStream);
+ }
+ if (i == maxCatches - 1) {
+ if (anyExceptionLabel != null) {
+ anyExceptionLabel.placeEnd();
+ }
+ if (subRoutineStartLabel != null) {
+ if (!catchExits[i] && preserveCurrentHandler) {
+ requiresNaturalJsr = true;
+ codeStream.goto_(endLabel);
+ }
+ }
+ } else {
+ if (!catchExits[i] && preserveCurrentHandler) {
+ if (nonReturningSubRoutine) {
+ codeStream.goto_(subRoutineStartLabel);
+ } else {
+ requiresNaturalJsr = true;
+ codeStream.goto_(endLabel);
+ }
+ }
+ }
+ }
+ }
+ // addition of a special handler so as to ensure that any uncaught exception (or exception thrown
+ // inside catch blocks) will run the finally block
+ int finallySequenceStartPC = codeStream.position;
+ if (subRoutineStartLabel != null) {
+ // the additional handler is doing: jsr finallyBlock and rethrow TOS-exception
+ anyExceptionLabel.place();
+
+ if (preTryInitStateIndex != -1) {
+ // reset initialization state, as for a normal catch block
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ preTryInitStateIndex);
+ }
+
+ codeStream.incrStackSize(1);
+ if (nonReturningSubRoutine) {
+ codeStream.pop();
+ // "if subroutine cannot return, no need to jsr/jump to subroutine since it will be entered in sequence
+ } else {
+ codeStream.store(anyExceptionVariable, false);
+ codeStream.jsr(subRoutineStartLabel);
+ codeStream.load(anyExceptionVariable);
+ codeStream.athrow();
+ }
+ }
+ // end of catch sequence, place label that will correspond to the finally block beginning, or end of statement
+ endLabel.place();
+ if (subRoutineStartLabel != null) {
+ if (nonReturningSubRoutine) {
+ requiresNaturalJsr = false;
+ }
+ Label veryEndLabel = new Label(codeStream);
+ if (requiresNaturalJsr) {
+ codeStream.jsr(subRoutineStartLabel);
+ codeStream.goto_(veryEndLabel);
+ }
+ subRoutineStartLabel.place();
+ if (!nonReturningSubRoutine) {
+ codeStream.incrStackSize(1);
+ codeStream.store(returnAddressVariable, false);
+ }
+ codeStream.recordPositionsFrom(
+ finallySequenceStartPC,
+ finallyBlock.sourceStart);
+ // entire sequence for finally is associated to finally block
+ finallyBlock.generateCode(scope, codeStream);
+ if (!nonReturningSubRoutine) {
+ int position = codeStream.position;
+ codeStream.ret(returnAddressVariable.resolvedPosition);
+ codeStream.updateLastRecordedEndPC(position);
+ // the ret bytecode is part of the subroutine
+ }
+ if (requiresNaturalJsr) {
+ veryEndLabel.place();
+ }
+ }
+ } else {
+ // 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);
+ }
+
+ 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
+ && finallyBlock.statements != null) {
+
+ finallyScope = new BlockScope(scope, false); // don't add it yet to parent scope
+
+ // provision for returning and forcing the finally block to run
+ MethodScope methodScope = scope.methodScope();
+
+ // the type does not matter as long as its not a normal base type
+ this.returnAddressVariable =
+ new LocalVariableBinding(SecretReturnName, upperScope.getJavaLangObject(), AccDefault, false);
+ finallyScope.addLocalVariable(returnAddressVariable);
+ this.returnAddressVariable.constant = NotAConstant; // not inlinable
+ this.subRoutineStartLabel = new Label();
+
+ this.anyExceptionVariable =
+ new LocalVariableBinding(SecretAnyHandlerName, scope.getJavaLangThrowable(), AccDefault, false);
+ finallyScope.addLocalVariable(this.anyExceptionVariable);
+ this.anyExceptionVariable.constant = NotAConstant; // not inlinable
+
+ if (!methodScope.isInsideInitializer()) {
+ MethodBinding methodBinding =
+ ((AbstractMethodDeclaration) methodScope.referenceContext).binding;
+ if (methodBinding != null) {
+ TypeBinding methodReturnType = methodBinding.returnType;
+ if (methodReturnType.id != T_void) {
+ this.secretReturnValue =
+ new LocalVariableBinding(
+ SecretLocalDeclarationName,
+ methodReturnType,
+ AccDefault,
+ false);
+ finallyScope.addLocalVariable(this.secretReturnValue);
+ this.secretReturnValue.constant = NotAConstant; // not inlinable
+ }
+ }
+ }
+ 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 (scope.areTypesCompatible(caughtExceptionTypes[i], argumentTypes[j])) {
+ scope.problemReporter().wrongSequenceOfExceptionTypesError(this, i, j);
+ return;
+ }
+ }
+ }
+ } 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 String toString(int tab) {
+ String s = tabString(tab);
+ //try
+ s = s + "try "; //$NON-NLS-1$
+ if (tryBlock == Block.None)
+ s = s + "{}"; //$NON-NLS-1$
+ else
+ s = s + "\n" + tryBlock.toString(tab + 1); //$NON-NLS-1$
+
+ //catches
+ if (catchBlocks != null)
+ for (int i = 0; i < catchBlocks.length; i++)
+ s = s + "\n" + tabString(tab) + "catch (" //$NON-NLS-2$ //$NON-NLS-1$
+ +catchArguments[i].toString(0) + ") " //$NON-NLS-1$
+ +catchBlocks[i].toString(tab + 1);
+ //finally
+ if (finallyBlock != null) {
+ if (finallyBlock == Block.None)
+ s = s + "\n" + tabString(tab) + "finally {}"; //$NON-NLS-2$ //$NON-NLS-1$
+ else
+ s = s + "\n" + tabString(tab) + "finally\n" + //$NON-NLS-2$ //$NON-NLS-1$
+ finallyBlock.toString(tab + 1);
+ }
+
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ 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);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+public class TypeDeclaration
+ extends Statement
+ implements ProblemSeverities, ReferenceContext {
+
+ public int modifiers;
+ public int modifiersSourceStart;
+ public char[] name;
+ public TypeReference superclass;
+ public TypeReference[] superInterfaces;
+ public FieldDeclaration[] fields;
+ public AbstractMethodDeclaration[] methods;
+ public MemberTypeDeclaration[] 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 TypeDeclaration(CompilationResult compilationResult){
+ this.compilationResult = compilationResult;
+ }
+
+ /*
+ * We cause the compilation task to abort to a given extent.
+ */
+ public void abort(int abortLevel) {
+
+ if (scope == null) {
+ throw new AbortCompilation(); // cannot do better
+ }
+
+ CompilationResult compilationResult =
+ scope.referenceCompilationUnit().compilationResult;
+
+ switch (abortLevel) {
+ case AbortCompilation :
+ throw new AbortCompilation(compilationResult);
+ case AbortCompilationUnit :
+ throw new AbortCompilationUnit(compilationResult);
+ case AbortMethod :
+ throw new AbortMethod(compilationResult);
+ default :
+ throw new AbortType(compilationResult);
+ }
+ }
+ /**
+ * 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[] methods;
+ if ((methods = this.methods) == null) {
+ length = 0;
+ methods = new AbstractMethodDeclaration[1];
+ } else {
+ length = methods.length;
+ System.arraycopy(
+ methods,
+ 0,
+ (methods = new AbstractMethodDeclaration[length + 1]),
+ 1,
+ length);
+ }
+ Clinit clinit = new Clinit(this.compilationResult);
+ methods[0] = clinit;
+ // clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
+ clinit.declarationSourceStart = clinit.sourceStart = sourceStart;
+ clinit.declarationSourceEnd = clinit.sourceEnd = sourceEnd;
+ clinit.bodyEnd = sourceEnd;
+ this.methods = methods;
+ }
+ }
+
+ /**
+ * Flow analysis for a local innertype
+ *
+ */
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ if (ignoreFurtherInvestigation)
+ return flowInfo;
+ try {
+ // remember local types binding for innerclass emulation propagation
+ currentScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
+
+ InitializationFlowContext initializerContext =
+ new InitializationFlowContext(null, this, initializerScope);
+ // propagate down the max field count
+ updateMaxFieldCount();
+ FlowInfo fieldInfo = flowInfo.copy();
+ // so as not to propagate changes outside this type
+ if (fields != null) {
+ for (int i = 0, count = fields.length; i < count; i++) {
+ fieldInfo =
+ fields[i].analyseCode(initializerScope, initializerContext, fieldInfo);
+ if (fieldInfo == FlowInfo.DeadEnd) {
+ // 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.
+ initializerScope.problemReporter().initializerMustCompleteNormally(fields[i]);
+ fieldInfo = FlowInfo.initial(maxFieldCount).markAsFakeReachable(true);
+ }
+ }
+ }
+ if (memberTypes != null) {
+ for (int i = 0, count = memberTypes.length; i < count; i++) {
+ memberTypes[i].analyseCode(scope, flowContext, fieldInfo.copy());
+ }
+ }
+ if (methods != null) {
+ int recursionBalance = 0; // check constructor recursions
+ for (int i = 0, count = methods.length; i < count; i++) {
+ AbstractMethodDeclaration method = methods[i];
+ if (method.ignoreFurtherInvestigation)
+ continue;
+ if (method.isConstructor()) { // constructor
+ ConstructorDeclaration constructor = (ConstructorDeclaration) method;
+ constructor.analyseCode(scope, initializerContext, fieldInfo.copy());
+ // compute the recursive invocation balance:
+ // how many thisReferences vs. superReferences to constructors
+ int refCount;
+ if ((refCount = constructor.referenceCount) > 0) {
+ if ((constructor.constructorCall == null)
+ || constructor.constructorCall.isSuperAccess()
+ || !constructor.constructorCall.binding.isValidBinding()) {
+ recursionBalance -= refCount;
+ constructor.referenceCount = -1;
+ // for error reporting propagation
+ } else {
+ recursionBalance += refCount;
+ }
+ }
+ } else { // regular method
+ method.analyseCode(scope, null, flowInfo.copy());
+ }
+ }
+ if (recursionBalance > 0) {
+ // there is one or more cycle(s) amongst constructor invocations
+ scope.problemReporter().recursiveConstructorInvocation(this);
+ }
+ }
+ } catch (AbortType e) {
+ this.ignoreFurtherInvestigation = true;
+ }
+ return flowInfo;
+ }
+
+ /**
+ * Flow analysis for a member innertype
+ *
+ */
+ public void analyseCode(ClassScope classScope1) {
+
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ // propagate down the max field count
+ updateMaxFieldCount();
+ FlowInfo flowInfo = FlowInfo.initial(maxFieldCount); // start fresh init info
+ InitializationFlowContext initializerContext =
+ new InitializationFlowContext(null, this, initializerScope);
+ InitializationFlowContext staticInitializerContext =
+ new InitializationFlowContext(null, this, staticInitializerScope);
+ FlowInfo nonStaticFieldInfo = flowInfo.copy(),
+ staticFieldInfo = flowInfo.copy();
+ if (fields != null) {
+ for (int i = 0, count = fields.length; i < count; i++) {
+ if (fields[i].isStatic()) {
+ staticFieldInfo =
+ fields[i].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.DeadEnd) {
+ staticInitializerScope.problemReporter().initializerMustCompleteNormally(
+ fields[i]);
+ staticFieldInfo = FlowInfo.initial(maxFieldCount).markAsFakeReachable(true);
+ }
+ } else {
+ nonStaticFieldInfo =
+ fields[i].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.DeadEnd) {
+ initializerScope.problemReporter().initializerMustCompleteNormally(fields[i]);
+ nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).markAsFakeReachable(true);
+ }
+ }
+ }
+ }
+ if (memberTypes != null) {
+ for (int i = 0, count = memberTypes.length; i < count; i++) {
+ memberTypes[i].analyseCode(scope);
+ }
+ }
+ if (methods != null) {
+ int recursionBalance = 0; // check constructor recursions
+ 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>
+ ((Clinit) method).analyseCode(scope, staticInitializerContext, staticFieldInfo);
+ } else { // constructor
+ ConstructorDeclaration constructor = (ConstructorDeclaration) method;
+ constructor.analyseCode(scope, initializerContext, nonStaticFieldInfo.copy());
+ // compute the recursive invocation balance:
+ // how many thisReferences vs. superReferences to constructors
+ int refCount;
+ if ((refCount = constructor.referenceCount) > 0) {
+ if ((constructor.constructorCall == null)
+ || constructor.constructorCall.isSuperAccess()
+ || !constructor.constructorCall.binding.isValidBinding()) {
+ recursionBalance -= refCount;
+ constructor.referenceCount = -1; // for error reporting propagation
+ } else {
+ recursionBalance += refCount;
+ }
+ }
+ }
+ } else { // regular method
+ method.analyseCode(scope, null, FlowInfo.initial(maxFieldCount));
+ }
+ }
+ if (recursionBalance > 0) {
+ // there is one or more cycle(s) amongst constructor invocations
+ scope.problemReporter().recursiveConstructorInvocation(this);
+ }
+ }
+ } 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 {
+ // remember local types binding for innerclass emulation propagation
+ currentScope.referenceCompilationUnit().record((LocalTypeBinding) binding);
+
+ /* force to emulation of access to direct enclosing instance: only for local members.
+ * 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.
+ */
+ initializerScope.emulateOuterAccess(
+ (SourceTypeBinding) binding.enclosingType(),
+ false);
+
+ InitializationFlowContext initializerContext =
+ new InitializationFlowContext(null, this, initializerScope);
+ // propagate down the max field count
+ updateMaxFieldCount();
+ FlowInfo fieldInfo = flowInfo.copy();
+ // so as not to propagate changes outside this type
+ if (fields != null) {
+ for (int i = 0, count = fields.length; i < count; i++) {
+ if (!fields[i].isStatic()) {
+ fieldInfo =
+ fields[i].analyseCode(initializerScope, initializerContext, fieldInfo);
+ if (fieldInfo == FlowInfo.DeadEnd) {
+ // 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.
+ initializerScope.problemReporter().initializerMustCompleteNormally(fields[i]);
+ fieldInfo = FlowInfo.initial(maxFieldCount).markAsFakeReachable(true);
+ }
+ }
+ }
+ }
+ if (memberTypes != null) {
+ for (int i = 0, count = memberTypes.length; i < count; i++) {
+ memberTypes[i].analyseCode(scope, flowContext, fieldInfo.copy());
+ }
+ }
+ if (methods != null) {
+ int recursionBalance = 0; // check constructor recursions
+ for (int i = 0, count = methods.length; i < count; i++) {
+ AbstractMethodDeclaration method = methods[i];
+ if (method.ignoreFurtherInvestigation)
+ continue;
+ if (method.isConstructor()) { // constructor
+ ConstructorDeclaration constructor = (ConstructorDeclaration) method;
+ constructor.analyseCode(scope, initializerContext, fieldInfo.copy());
+ // compute the recursive invocation balance:
+ // how many thisReferences vs. superReferences to constructors
+ int refCount;
+ if ((refCount = constructor.referenceCount) > 0) {
+ if ((constructor.constructorCall == null)
+ || constructor.constructorCall.isSuperAccess()
+ || !constructor.constructorCall.binding.isValidBinding()) {
+ recursionBalance -= refCount;
+ constructor.referenceCount = -1; // for error reporting propagation
+ } else {
+ recursionBalance += refCount;
+ }
+ }
+ } else { // regular method
+ method.analyseCode(scope, null, flowInfo.copy());
+ }
+ }
+ if (recursionBalance > 0) {
+ // there is one or more cycle(s) amongst constructor invocations
+ scope.problemReporter().recursiveConstructorInvocation(this);
+ }
+ }
+ } catch (AbortType e) {
+ this.ignoreFurtherInvestigation = true;
+ };
+ }
+
+ /**
+ * Flow analysis for a package member type
+ *
+ */
+ public void analyseCode(CompilationUnitScope unitScope) {
+
+ if (ignoreFurtherInvestigation)
+ return;
+ try {
+ FlowInfo flowInfo = FlowInfo.initial(maxFieldCount); // start fresh init info
+ InitializationFlowContext initializerContext =
+ new InitializationFlowContext(null, this, initializerScope);
+ InitializationFlowContext staticInitializerContext =
+ new InitializationFlowContext(null, this, staticInitializerScope);
+ FlowInfo nonStaticFieldInfo = flowInfo.copy(),
+ staticFieldInfo = flowInfo.copy();
+ if (fields != null) {
+ for (int i = 0, count = fields.length; i < count; i++) {
+ if (fields[i].isStatic()) {
+ staticFieldInfo =
+ fields[i].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.DeadEnd) {
+ staticInitializerScope.problemReporter().initializerMustCompleteNormally(
+ fields[i]);
+ staticFieldInfo = FlowInfo.initial(maxFieldCount).markAsFakeReachable(true);
+ }
+ } else {
+ nonStaticFieldInfo =
+ fields[i].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.DeadEnd) {
+ initializerScope.problemReporter().initializerMustCompleteNormally(fields[i]);
+ nonStaticFieldInfo = FlowInfo.initial(maxFieldCount).markAsFakeReachable(true);
+ }
+ }
+ }
+ }
+ if (memberTypes != null) {
+ for (int i = 0, count = memberTypes.length; i < count; i++) {
+ memberTypes[i].analyseCode(scope);
+ }
+ }
+ if (methods != null) {
+ int recursionBalance = 0; // check constructor recursions
+ 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>
+ ((Clinit) method).analyseCode(scope, staticInitializerContext, staticFieldInfo);
+ } else { // constructor
+ ConstructorDeclaration constructor = (ConstructorDeclaration) method;
+ constructor.analyseCode(scope, initializerContext, nonStaticFieldInfo.copy());
+ // compute the recursive invocation balance:
+ // how many thisReferences vs. superReferences to constructors
+ int refCount;
+ if ((refCount = constructor.referenceCount) > 0) {
+ if ((constructor.constructorCall == null)
+ || constructor.constructorCall.isSuperAccess()
+ || !constructor.constructorCall.binding.isValidBinding()) {
+ recursionBalance -= refCount;
+ constructor.referenceCount = -1; // for error reporting propagation
+ } else {
+ recursionBalance += refCount;
+ }
+ }
+ }
+ } else { // regular method
+ method.analyseCode(scope, null, FlowInfo.initial(maxFieldCount));
+ }
+ }
+ if (recursionBalance > 0) {
+ // there is one or more cycle(s) amongst constructor invocations
+ scope.problemReporter().recursiveConstructorInvocation(this);
+ }
+ }
+ } 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 = new MethodDeclaration(this.compilationResult);
+ m.sourceStart = c.sourceStart;
+ m.sourceEnd = c.sourceEnd;
+ m.bodyStart = c.bodyStart;
+ m.bodyEnd = c.bodyEnd;
+ m.declarationSourceEnd = c.declarationSourceEnd;
+ m.declarationSourceStart = c.declarationSourceStart;
+ m.selector = c.selector;
+ m.statements = c.statements;
+ m.modifiers = c.modifiers;
+ m.arguments = c.arguments;
+ m.thrownExceptions = c.thrownExceptions;
+ m.explicitDeclarations = c.explicitDeclarations;
+ m.returnType = null;
+ methods[i] = m;
+ }
+ } else {
+ if (this.isInterface()) {
+ // report the problem and continue the parsing
+ parser.problemReporter().interfaceCannotHaveConstructors(
+ (ConstructorDeclaration) am);
+ }
+ hasConstructor = true;
+ }
+ }
+ }
+ }
+ return hasConstructor;
+ }
+
+ public CompilationResult compilationResult() {
+
+ return this.compilationResult;
+ }
+
+ public ConstructorDeclaration createsInternalConstructor(
+ boolean needExplicitConstructorCall,
+ boolean needToInsert) {
+
+ //Add to method'set, the default constuctor that just recall the
+ //super constructor with no arguments
+ //The arguments' type will be positionned by the TC so just use
+ //the default int instead of just null (consistency purpose)
+
+ //the constructor
+ ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
+ constructor.isDefaultConstructor = true;
+ constructor.selector = name;
+ if (modifiers != AccDefault) {
+ constructor.modifiers =
+ ((this instanceof MemberTypeDeclaration) && (modifiers & AccPrivate) != 0)
+ ? AccDefault
+ : modifiers & AccVisibilityMASK;
+ }
+
+ //if you change this setting, please update the
+ //SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
+ constructor.declarationSourceStart = constructor.sourceStart = sourceStart;
+ constructor.declarationSourceEnd =
+ constructor.sourceEnd = constructor.bodyEnd = sourceEnd;
+
+ //the super call inside the constructor
+ if (needExplicitConstructorCall) {
+ constructor.constructorCall =
+ new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+ constructor.constructorCall.sourceStart = sourceStart;
+ constructor.constructorCall.sourceEnd = sourceEnd;
+ }
+
+ //adding the constructor in the methods list
+ if (needToInsert) {
+ if (methods == null) {
+ methods = new AbstractMethodDeclaration[] { constructor };
+ } else {
+ AbstractMethodDeclaration[] newMethods;
+ System.arraycopy(
+ methods,
+ 0,
+ newMethods = new AbstractMethodDeclaration[methods.length + 1],
+ 1,
+ methods.length);
+ newMethods[0] = constructor;
+ methods = newMethods;
+ }
+ }
+ return constructor;
+ }
+
+ /**
+ * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
+ * It is used to report errors for missing abstract methods.
+ */
+ 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;
+ }
+
+ /*
+ * 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);
+ }
+
+ // 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 (hasBeenGenerated)
+ return;
+ int pc = codeStream.position;
+ if (binding != null) {
+ ((NestedTypeBinding) binding).computeSyntheticArgumentsOffset();
+ }
+ 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;
+ ((NestedTypeBinding) binding).computeSyntheticArgumentsOffset();
+ generateCode(enclosingClassFile);
+ }
+
+ /**
+ * Bytecode generation for a package member
+ */
+ public void generateCode(CompilationUnitScope unitScope) {
+
+ generateCode((ClassFile) null);
+ }
+
+ public boolean isInterface() {
+
+ return (modifiers & AccInterface) != 0;
+ }
+
+ public boolean hasErrors() {
+ return this.ignoreFurtherInvestigation;
+ }
+
+ /**
+ * 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;
+
+ // no scope were created, so cannot report further errors
+// if (binding == null)
+// return;
+
+ //members
+ if (memberTypes != null) {
+ for (int i = memberTypes.length; --i >= 0;)
+ memberTypes[i].parseMethod(parser, unit);
+ }
+
+ //methods
+ if (methods != null) {
+ for (int i = methods.length; --i >= 0;)
+ methods[i].parseStatements(parser, unit);
+ }
+
+ //initializers
+ if (fields != null) {
+ for (int i = fields.length; --i >= 0;) {
+ if (fields[i] instanceof Initializer) {
+ ((Initializer) fields[i]).parseStatements(parser, this, unit);
+ }
+ }
+ }
+ }
+
+ public void resolve() {
+
+ if (binding == null) {
+ ignoreFurtherInvestigation = true;
+ return;
+ }
+
+ try {
+ // check superclass & interfaces
+ if (binding.superclass != null) // watch out for Object ! (and other roots)
+ if (isTypeUseDeprecated(binding.superclass, scope))
+ scope.problemReporter().deprecatedType(binding.superclass, superclass);
+ if (superInterfaces != null)
+ for (int i = superInterfaces.length; --i >= 0;)
+ if (superInterfaces[i].binding != null)
+ if (isTypeUseDeprecated(superInterfaces[i].binding, scope))
+ scope.problemReporter().deprecatedType(
+ superInterfaces[i].binding,
+ superInterfaces[i]);
+ maxFieldCount = 0;
+ int lastFieldID = -1;
+ if (fields != null) {
+ for (int i = 0, count = fields.length; i < count; i++) {
+ FieldDeclaration field = fields[i];
+ if (field.isField()) {
+ if (field.binding == null) {
+ ignoreFurtherInvestigation = true;
+ continue;
+ }
+ maxFieldCount++;
+ lastFieldID = field.binding.id;
+ } else { // initializer
+ ((Initializer) field).lastFieldID = lastFieldID + 1;
+ }
+ field.resolve(field.isStatic() ? staticInitializerScope : initializerScope);
+ }
+ }
+ if (memberTypes != null)
+ for (int i = 0, count = memberTypes.length; i < count; i++)
+ memberTypes[i].resolve(scope);
+ if (methods != null)
+ for (int i = 0, count = methods.length; i < count; i++)
+ methods[i].resolve(scope);
+ } catch (AbortType e) {
+ this.ignoreFurtherInvestigation = true;
+ return;
+ };
+ }
+
+ public void resolve(BlockScope blockScope) {
+ // local type declaration
+
+ // need to build its scope first and proceed with binding's creation
+ blockScope.addLocalType(this);
+
+ // and TC....
+ if (binding != null) {
+ // 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
+
+ resolve();
+ updateMaxFieldCount();
+ }
+
+ public void resolve(CompilationUnitScope upperScope) {
+ // top level : scope are already created
+
+ resolve();
+ updateMaxFieldCount();
+ }
+
+ public void tagAsHavingErrors() {
+ ignoreFurtherInvestigation = true;
+ }
+
+ public String toString(int tab) {
+
+ return tabString(tab) + toStringHeader() + toStringBody(tab);
+ }
+
+ public String toStringBody(int tab) {
+
+ String s = " {"; //$NON-NLS-1$
+ if (memberTypes != null) {
+ for (int i = 0; i < memberTypes.length; i++) {
+ if (memberTypes[i] != null) {
+ s += "\n" + memberTypes[i].toString(tab + 1); //$NON-NLS-1$
+ }
+ }
+ }
+ if (fields != null) {
+ for (int fieldI = 0; fieldI < fields.length; fieldI++) {
+ if (fields[fieldI] != null) {
+ s += "\n" + fields[fieldI].toString(tab + 1); //$NON-NLS-1$
+ if (fields[fieldI].isField())
+ s += ";"; //$NON-NLS-1$
+ }
+ }
+ }
+ if (methods != null) {
+ for (int i = 0; i < methods.length; i++) {
+ if (methods[i] != null) {
+ s += "\n" + methods[i].toString(tab + 1); //$NON-NLS-1$
+ }
+ }
+ }
+ s += "\n" + tabString(tab) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
+ return s;
+ }
+
+ public String toStringHeader() {
+
+ String s = ""; //$NON-NLS-1$
+ if (modifiers != AccDefault) {
+ s += modifiersString(modifiers);
+ }
+ s += (isInterface() ? "interface " : "class ") + new String(name);//$NON-NLS-1$ //$NON-NLS-2$
+ if (superclass != null)
+ s += " extends " + superclass.toString(0); //$NON-NLS-1$
+ if (superInterfaces != null && superInterfaces.length > 0) {
+ s += (isInterface() ? " extends " : " implements ");//$NON-NLS-2$ //$NON-NLS-1$
+ for (int i = 0; i < superInterfaces.length; i++) {
+ s += superInterfaces[i].toString(0);
+ if (i != superInterfaces.length - 1)
+ s += ", "; //$NON-NLS-1$
+ };
+ };
+ return s;
+ }
+
+ /**
+ * Iteration for a package member type
+ *
+ */
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ 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);
+ }
+ }
+ } catch (AbortType e) {
+ }
+ }
+
+ /**
+ * 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
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public abstract class TypeReference extends Expression {
+ public TypeBinding binding;
+public TypeReference() {
+ super () ;
+ }
+// allows us to trap completion & selection nodes
+
+public void aboutToResolve(Scope scope) {}
+/*
+ * 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 scope) {
+ // handle the error here
+ constant = NotAConstant;
+ if (binding != null) { // is a shared type reference which was already resolved
+ if (!binding.isValidBinding())
+ return null; // already reported error
+ } else {
+ binding = getTypeBinding(scope);
+ if (!binding.isValidBinding()) {
+ scope.problemReporter().invalidType(this, binding);
+ return null;
+ }
+ if (isTypeUseDeprecated(binding, scope))
+ scope.problemReporter().deprecatedType(binding, this);
+ }
+ return binding;
+}
+public abstract void traverse(IAbstractSyntaxTreeVisitor visitor, ClassScope classScope);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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 expression
+ .analyseCode(currentScope, flowContext, flowInfo)
+ .asNegatedCondition();
+ } else {
+ return expression.analyseCode(currentScope, flowContext, flowInfo);
+ }
+ }
+
+ public Constant conditionalConstant() {
+ return optimizedBooleanConstant == null ? constant : 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 (constant != Constant.NotAConstant) {
+ // inlined value
+ if (valueRequired) {
+ codeStream.generateConstant(constant, implicitConversion);
+ }
+ codeStream.recordPositionsFrom(pc, this.sourceStart);
+ return;
+ }
+ switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+ case NOT :
+ switch (expression.implicitConversion >> 4) /* runtime type */ {
+ case T_boolean :
+ // ! <boolean>
+ // Generate code for the condition
+ 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 (expression.implicitConversion >> 4 /* runtime */
+ ) {
+ case T_int :
+ // ~int
+ expression.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ codeStream.iconst_m1();
+ codeStream.ixor();
+ }
+ break;
+ case T_long :
+ expression.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ codeStream.ldc2_w(-1L);
+ codeStream.lxor();
+ }
+ }
+ break;
+ case MINUS :
+ // - <num>
+ if (constant != NotAConstant) {
+ if (valueRequired) {
+ switch (expression.implicitConversion >> 4 /* runtime */
+ ) {
+ case T_int :
+ codeStream.generateInlinedValue(constant.intValue() * -1);
+ break;
+ case T_float :
+ codeStream.generateInlinedValue(constant.floatValue() * -1.0f);
+ break;
+ case T_long :
+ codeStream.generateInlinedValue(constant.longValue() * -1L);
+ break;
+ case T_double :
+ codeStream.generateInlinedValue(constant.doubleValue() * -1.0);
+ }
+ }
+ } else {
+ 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 :
+ expression.generateCode(currentScope, codeStream, valueRequired);
+ }
+ 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;
+ }
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+ expression.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ falseLabel,
+ trueLabel,
+ valueRequired);
+ } else {
+ super.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ TypeBinding expressionTb = expression.resolveType(scope);
+ if (expressionTb == null) {
+ constant = NotAConstant;
+ return null;
+ }
+ int expressionId = expressionTb.id;
+ if (expressionId > 15) {
+ constant = NotAConstant;
+ scope.problemReporter().invalidOperator(this, expressionTb);
+ 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 result = ResolveTypeTables[tableId][(expressionId << 4) + expressionId];
+ expression.implicitConversion = result >>> 12;
+ bits |= result & 0xF;
+ switch (result & 0xF) { // only switch on possible result type.....
+ case T_boolean :
+ this.typeBinding = BooleanBinding;
+ break;
+ case T_byte :
+ this.typeBinding = ByteBinding;
+ break;
+ case T_char :
+ this.typeBinding = CharBinding;
+ break;
+ case T_double :
+ this.typeBinding = DoubleBinding;
+ break;
+ case T_float :
+ this.typeBinding = FloatBinding;
+ break;
+ case T_int :
+ this.typeBinding = IntBinding;
+ break;
+ case T_long :
+ this.typeBinding = LongBinding;
+ break;
+ default : //error........
+ constant = Constant.NotAConstant;
+ if (expressionId != T_undefined)
+ scope.problemReporter().invalidOperator(this, expressionTb);
+ return null;
+ }
+ // compute the constant when valid
+ if (expression.constant != Constant.NotAConstant) {
+ constant =
+ Constant.computeConstantOperation(
+ expression.constant,
+ expressionId,
+ (bits & OperatorMASK) >> OperatorSHIFT);
+ } else {
+ constant = Constant.NotAConstant;
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+ Constant cst = expression.conditionalConstant();
+ if (cst.typeID() == T_boolean)
+ optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
+ }
+ }
+ return this.typeBinding;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+ return operatorToString() + " " + expression.toStringExpression(); //$NON-NLS-1$
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+ if (visitor.visit(this, blockScope)) {
+ expression.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.ast;
+
+import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.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;
+ sourceStart = s;
+ sourceEnd = e;
+ }
+
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+
+ breakLabel = new Label();
+ continueLabel = new Label();
+
+ preCondInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(flowInfo);
+ LoopingFlowContext condLoopContext;
+ FlowInfo postCondInfo =
+ condition.analyseCode(
+ currentScope,
+ (condLoopContext =
+ new LoopingFlowContext(flowContext, this, null, null, currentScope)),
+ flowInfo);
+
+ LoopingFlowContext loopingContext;
+ if ((action == null) || action.isEmptyBlock()) {
+ condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+ if ((condition.constant != NotAConstant)
+ && (condition.constant.booleanValue() == true)) {
+ return FlowInfo.DeadEnd;
+ } else {
+ FlowInfo mergedInfo = postCondInfo.initsWhenFalse().unconditionalInits();
+ 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);
+ FlowInfo actionInfo =
+ ((condition.constant != Constant.NotAConstant)
+ && (condition.constant.booleanValue() == false))
+ ? FlowInfo.DeadEnd
+ : postCondInfo.initsWhenTrue().copy();
+
+ // for computing local var attributes
+ condIfTrueInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(
+ postCondInfo.initsWhenTrue());
+
+ if (!actionInfo.complainIfUnreachable(action, currentScope)) {
+ actionInfo = action.analyseCode(currentScope, loopingContext, actionInfo);
+ }
+
+ // code generation can be optimized when no need to continue in the loop
+ if (((actionInfo == FlowInfo.DeadEnd) || actionInfo.isFakeReachable())
+ && ((loopingContext.initsOnContinue == FlowInfo.DeadEnd)
+ || loopingContext.initsOnContinue.isFakeReachable())) {
+ continueLabel = null;
+ } else {
+ condLoopContext.complainOnFinalAssignmentsInLoop(currentScope, postCondInfo);
+ loopingContext.complainOnFinalAssignmentsInLoop(currentScope, actionInfo);
+ }
+ }
+
+ // infinite loop
+ FlowInfo mergedInfo;
+ if ((condition.constant != Constant.NotAConstant)
+ && (condition.constant.booleanValue() == true)) {
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(
+ mergedInfo = loopingContext.initsOnBreak);
+ return mergedInfo;
+ }
+
+ // end of loop: either condition false or break
+ mergedInfo =
+ postCondInfo.initsWhenFalse().unconditionalInits().mergedWith(
+ loopingContext.initsOnBreak);
+ 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.codeStream = codeStream;
+
+ // generate condition
+ if (continueLabel == null) {
+ // no need to reverse condition
+ if (condition.constant == NotAConstant) {
+ condition.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ breakLabel,
+ true);
+ }
+ } else {
+ continueLabel.codeStream = 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.recordPositionsFrom(pc, this.sourceStart);
+ }
+
+ public void resetStateForCodeGeneration() {
+
+ this.breakLabel.resetStateForCodeGeneration();
+ this.continueLabel.resetStateForCodeGeneration();
+ }
+
+ public void resolve(BlockScope scope) {
+
+ TypeBinding type = condition.resolveTypeExpecting(scope, BooleanBinding);
+ condition.implicitWidening(type, type);
+ if (action != null)
+ action.resolve(scope);
+ }
+
+ public String toString(int tab) {
+
+ String s = tabString(tab);
+ s = s + "while (" + condition.toStringExpression() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ if (action == null)
+ s = s + " {} ;"; //$NON-NLS-1$
+ else if (action instanceof Block)
+ s = s + "\n" + action.toString(tab + 1); //$NON-NLS-1$
+ else
+ s = s + " {\n" + action.toString(tab + 1) + "}"; //$NON-NLS-2$ //$NON-NLS-1$
+ return s;
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+
+ if (visitor.visit(this, blockScope)) {
+ condition.traverse(visitor, blockScope);
+ if (action != null)
+ action.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.batch;
+
+import java.io.File;
+import java.util.Hashtable;
+
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileReader;
+import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
+
+public class ClasspathDirectory implements FileSystem.Classpath {
+
+String path;
+Hashtable directoryCache;
+String[] missingPackageHolder = new String[1];
+String encoding;
+public int mode; // ability to only consider one kind of files (source vs. binaries), by default use both
+
+public static final int SOURCE = 1;
+public static final int BINARY = 2;
+
+ClasspathDirectory(File directory, String encoding, int mode) {
+ this.mode = mode;
+ this.path = directory.getAbsolutePath();
+ if (!path.endsWith(File.separator))
+ this.path += File.separator;
+ this.directoryCache = new Hashtable(11);
+ this.encoding = encoding;
+}
+
+ClasspathDirectory(File directory, String encoding) {
+ this(directory, encoding, SOURCE | BINARY); // by default consider both sources and binaries
+}
+
+String[] directoryList(String qualifiedPackageName) {
+ String[] dirList = (String[]) directoryCache.get(qualifiedPackageName);
+ if (dirList == missingPackageHolder) return null; // package exists in another classpath directory or jar
+ if (dirList != null) return dirList;
+
+ File dir = new File(path + qualifiedPackageName);
+ notFound : if (dir != null && dir.isDirectory()) {
+ // must protect against a case insensitive File call
+ // walk the qualifiedPackageName backwards looking for an uppercase character before the '/'
+ int index = qualifiedPackageName.length();
+ int last = qualifiedPackageName.lastIndexOf(File.separatorChar);
+ while (--index > last && !Character.isUpperCase(qualifiedPackageName.charAt(index))) {}
+ if (index > last) {
+ if (last == -1) {
+ if (!doesFileExist(qualifiedPackageName, "")) //$NON-NLS-1$
+ break notFound;
+ } else {
+ String packageName = qualifiedPackageName.substring(last + 1);
+ String parentPackage = qualifiedPackageName.substring(0, last);
+ if (!doesFileExist(packageName, parentPackage))
+ break notFound;
+ }
+ }
+ if ((dirList = dir.list()) == null)
+ dirList = new String[0];
+ directoryCache.put(qualifiedPackageName, dirList);
+ return dirList;
+ }
+ directoryCache.put(qualifiedPackageName, missingPackageHolder);
+ return null;
+}
+boolean doesFileExist(String fileName, String qualifiedPackageName) {
+ String[] dirList = directoryList(qualifiedPackageName);
+ if (dirList == null) return false; // most common case
+
+ for (int i = dirList.length; --i >= 0;)
+ if (fileName.equals(dirList[i]))
+ return true;
+ return false;
+}
+public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+ if (!isPackage(qualifiedPackageName)) return null; // most common case
+
+ String fileName = new String(typeName);
+ boolean binaryExists = ((this.mode & BINARY) != 0) && doesFileExist(fileName + ".class", qualifiedPackageName); //$NON-NLS-1$
+ boolean sourceExists = ((this.mode & SOURCE) != 0) && doesFileExist(fileName + ".java", qualifiedPackageName); //$NON-NLS-1$
+ if (sourceExists) {
+ String fullSourcePath = path + qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - 6) + ".java"; //$NON-NLS-1$
+ if (!binaryExists)
+ return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
+
+ String fullBinaryPath = path + qualifiedBinaryFileName;
+ long binaryModified = new File(fullBinaryPath).lastModified();
+ long sourceModified = new File(fullSourcePath).lastModified();
+ if (sourceModified > binaryModified)
+ return new NameEnvironmentAnswer(new CompilationUnit(null, fullSourcePath, this.encoding));
+ }
+ if (binaryExists) {
+ try {
+ ClassFileReader reader = ClassFileReader.read(path + qualifiedBinaryFileName);
+ if (reader != null) return new NameEnvironmentAnswer(reader);
+ } catch (Exception e) {} // treat as if file is missing
+ }
+ return null;
+}
+public boolean isPackage(String qualifiedPackageName) {
+ return directoryList(qualifiedPackageName) != null;
+}
+public void reset() {
+ this.directoryCache = new Hashtable(11);
+}
+public String toString() {
+ return "ClasspathDirectory " + path; //$NON-NLS-1$
+}
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileReader;
+import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
+
+public class ClasspathJar implements FileSystem.Classpath {
+
+ZipFile zipFile;
+Hashtable packageCache;
+boolean closeZipFileAtEnd;
+
+public ClasspathJar(File file) throws IOException {
+ this(new ZipFile(file), true);
+}
+public ClasspathJar(ZipFile zipFile, boolean closeZipFileAtEnd) throws IOException {
+ this.zipFile = zipFile;
+ this.packageCache = null;
+ this.closeZipFileAtEnd = closeZipFileAtEnd;
+}
+public NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName) {
+ if (!isPackage(qualifiedPackageName)) return null; // most common case
+
+ try {
+ ClassFileReader reader = ClassFileReader.read(zipFile, qualifiedBinaryFileName);
+ if (reader != null) return new NameEnvironmentAnswer(reader);
+ } catch (Exception e) {} // treat as if class file is missing
+ return null;
+}
+public boolean isPackage(String qualifiedPackageName) {
+ if (packageCache != null)
+ return packageCache.containsKey(qualifiedPackageName);
+
+ this.packageCache = new Hashtable(41);
+ packageCache.put("", ""); //$NON-NLS-1$ //$NON-NLS-2$
+
+ nextEntry : for (Enumeration e = zipFile.entries(); e.hasMoreElements(); ) {
+ String fileName = ((ZipEntry) e.nextElement()).getName();
+
+ // add the package name & all of its parent packages
+ int last = fileName.lastIndexOf('/');
+ while (last > 0) {
+ // extract the package name
+ String packageName = fileName.substring(0, last);
+ if (packageCache.containsKey(packageName))
+ continue nextEntry;
+ packageCache.put(packageName, packageName);
+ last = packageName.lastIndexOf('/');
+ }
+ }
+ return packageCache.containsKey(qualifiedPackageName);
+}
+public void reset() {
+ if (zipFile != null && closeZipFileAtEnd) {
+ try { zipFile.close(); } catch(IOException e) {}
+ }
+ this.packageCache = null;
+}
+public String toString() {
+ return "Classpath for jar file " + zipFile; //$NON-NLS-1$
+}
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.IOException;
+
+import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+public class CompilationUnit implements ICompilationUnit {
+ public char[] contents;
+ public char[] fileName;
+ public char[] mainTypeName;
+ String encoding;
+
+public CompilationUnit(char[] contents, String fileName, String encoding) {
+ this.contents = contents;
+ if (File.separator.equals("/")) { //$NON-NLS-1$
+ if (fileName.indexOf("\\") != -1) { //$NON-NLS-1$
+ fileName = fileName.replace('\\', File.separatorChar);
+ }
+ } else {
+ // the file separator is \
+ if (fileName.indexOf('/') != -1) {
+ fileName = fileName.replace('/', File.separatorChar);
+ }
+ }
+ this.fileName = fileName.toCharArray();
+
+ int start = fileName.lastIndexOf("/") + 1; //$NON-NLS-1$
+ if (start == 0 || start < fileName.lastIndexOf("\\")) //$NON-NLS-1$
+ start = fileName.lastIndexOf("\\") + 1; //$NON-NLS-1$
+
+ int end = fileName.lastIndexOf("."); //$NON-NLS-1$
+ if (end == -1)
+ end = fileName.length();
+
+ this.mainTypeName = fileName.substring(start, end).toCharArray();
+ this.encoding = encoding;
+}
+public char[] getContents() {
+ if (contents != null)
+ return contents; // answer the cached source
+
+ // otherwise retrieve it
+ try {
+ return Util.getFileCharContent(new File(new String(fileName)), encoding);
+ } catch (IOException e) {
+ }
+ return new char[0];
+}
+public char[] getFileName() {
+ return fileName;
+}
+public char[] getMainTypeName() {
+ return mainTypeName;
+}
+public char[][] getPackageName() {
+ return null;
+}
+public String toString() {
+ return "CompilationUnit[" + new String(fileName) + "]"; //$NON-NLS-2$ //$NON-NLS-1$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.batch;
+
+import java.io.File;
+
+public class FileFinder {
+ private final int INITIAL_SIZE = 10;
+ public String[] resultFiles = new String[INITIAL_SIZE];
+ public int counter = 0;
+public void find(File f, String pattern, boolean verbose) {
+ if (verbose) {
+ System.out.println(Main.bind("scanning.start",f.getAbsolutePath())); //$NON-NLS-1$
+ }
+ find0(f, pattern, verbose);
+ System.arraycopy(resultFiles, 0, (resultFiles = new String[counter]), 0, counter);
+}
+public void find0(File f, String pattern, boolean verbose) {
+ if (f.isDirectory()) {
+ String[] files = f.list();
+ if (files == null) return;
+ for (int i = 0, max = files.length; i < max; i++) {
+ File current = new File(f, files[i]);
+ if (current.isDirectory()) {
+ find0(current, pattern, verbose);
+ } else {
+ if (current.getName().toUpperCase().endsWith(pattern)) {
+ int length;
+ if ((length = resultFiles.length) == counter) {
+ System.arraycopy(resultFiles, 0, (resultFiles = new String[length * 2]), 0, length);
+ }
+ resultFiles[counter++] = current.getAbsolutePath();
+ if (verbose && (counter % 100) == 0)
+ System.out.print('.');
+ }
+ }
+ }
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.zip.ZipFile;
+
+import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
+import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class FileSystem implements INameEnvironment {
+ Classpath[] classpaths;
+ String[] knownFileNames;
+
+ interface Classpath {
+ NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String qualifiedBinaryFileName);
+ boolean isPackage(String qualifiedPackageName);
+ /**
+ * This method resets the environment. The resulting state is equivalent to
+ * a new name environment without creating a new object.
+ */
+ void reset();
+ }
+/*
+ classPathNames is a collection is Strings representing the full path of each class path
+ initialFileNames is a collection is Strings, the trailing '.java' will be removed if its not already.
+*/
+
+public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding) {
+ this(classpathNames, initialFileNames, encoding, null);
+}
+public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding, int[] classpathDirectoryModes) {
+ int classpathSize = classpathNames.length;
+ classpaths = new Classpath[classpathSize];
+ String[] pathNames = new String[classpathSize];
+ int problemsOccured = 0;
+ for (int i = 0; i < classpathSize; i++) {
+ try {
+ File file = new File(convertPathSeparators(classpathNames[i]));
+ if (file.isDirectory()) {
+ if (file.exists()) {
+ if (classpathDirectoryModes == null){
+ classpaths[i] = new ClasspathDirectory(file, encoding);
+ } else {
+ classpaths[i] = new ClasspathDirectory(file, encoding, classpathDirectoryModes[i]);
+ }
+ pathNames[i] = ((ClasspathDirectory) classpaths[i]).path;
+ }
+ } else if (classpathNames[i].endsWith(".jar") | (classpathNames[i].endsWith(".zip"))) { //$NON-NLS-2$ //$NON-NLS-1$
+ classpaths[i] = this.getClasspathJar(file); // will throw an IOException if file does not exist
+ pathNames[i] = classpathNames[i].substring(0, classpathNames[i].lastIndexOf('.'));
+ }
+ } catch (IOException e) {
+ classpaths[i] = null;
+ }
+ if (classpaths[i] == null)
+ problemsOccured++;
+ }
+ if (problemsOccured > 0) {
+ Classpath[] newPaths = new Classpath[classpathSize - problemsOccured];
+ String[] newNames = new String[classpathSize - problemsOccured];
+ for (int i = 0, current = 0; i < classpathSize; i++)
+ if (classpaths[i] != null) {
+ newPaths[current] = classpaths[i];
+ newNames[current++] = pathNames[i];
+ }
+ classpathSize = newPaths.length;
+ classpaths = newPaths;
+ pathNames = newNames;
+ }
+
+ knownFileNames = new String[initialFileNames.length];
+ for (int i = initialFileNames.length; --i >= 0;) {
+ String fileName = initialFileNames[i];
+ String matchingPathName = null;
+ if (fileName.lastIndexOf(".") != -1) //$NON-NLS-1$
+ fileName = fileName.substring(0, fileName.lastIndexOf('.')); // remove trailing ".java"
+
+ fileName = convertPathSeparators(fileName);
+ for (int j = 0; j < classpathSize; j++)
+ if (fileName.startsWith(pathNames[j]))
+ matchingPathName = pathNames[j];
+ if (matchingPathName == null)
+ knownFileNames[i] = fileName; // leave as is...
+ else
+ knownFileNames[i] = fileName.substring(matchingPathName.length());
+ }
+}
+public void cleanup() {
+ for (int i = 0, max = classpaths.length; i < max; i++)
+ classpaths[i].reset();
+}
+private String convertPathSeparators(String path) {
+ return File.separatorChar == '/'
+ ? path.replace('\\', '/')
+ : path.replace('/', '\\');
+}
+private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName){
+ for (int i = 0, length = knownFileNames.length; i < length; i++)
+ if (qualifiedTypeName.equals(knownFileNames[i]))
+ return null; // looking for a file which we know was provided at the beginning of the compilation
+
+ String qualifiedBinaryFileName = qualifiedTypeName + ".class"; //$NON-NLS-1$
+ String qualifiedPackageName =
+ qualifiedTypeName.length() == typeName.length
+ ? "" //$NON-NLS-1$
+ : qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);
+ String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
+ if (qualifiedPackageName == qp2) {
+ for (int i = 0, length = classpaths.length; i < length; i++) {
+ NameEnvironmentAnswer answer = classpaths[i].findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName);
+ if (answer != null) return answer;
+ }
+ } else {
+ String qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar);
+ for (int i = 0, length = classpaths.length; i < length; i++) {
+ Classpath p = classpaths[i];
+ NameEnvironmentAnswer answer = (p instanceof ClasspathJar)
+ ? p.findClass(typeName, qualifiedPackageName, qualifiedBinaryFileName)
+ : p.findClass(typeName, qp2, qb2);
+ if (answer != null) return answer;
+ }
+ }
+ return null;
+}
+public NameEnvironmentAnswer findType(char[][] compoundName) {
+ if (compoundName != null)
+ return findClass(
+ new String(CharOperation.concatWith(compoundName, '/')),
+ compoundName[compoundName.length - 1]);
+ return null;
+}
+public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
+ if (typeName != null)
+ return findClass(
+ new String(CharOperation.concatWith(packageName, typeName, '/')),
+ typeName);
+ return null;
+}
+public ClasspathJar getClasspathJar(File file) throws IOException {
+ return new ClasspathJar(new ZipFile(file), true);
+}
+public boolean isPackage(char[][] compoundName, char[] packageName) {
+ String qualifiedPackageName = new String(CharOperation.concatWith(compoundName, packageName, '/'));
+ String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
+ if (qualifiedPackageName == qp2) {
+ for (int i = 0, length = classpaths.length; i < length; i++)
+ if (classpaths[i].isPackage(qualifiedPackageName))
+ return true;
+ } else {
+ for (int i = 0, length = classpaths.length; i < length; i++) {
+ Classpath p = classpaths[i];
+ if ((p instanceof ClasspathJar) ? p.isPackage(qualifiedPackageName) : p.isPackage(qp2))
+ return true;
+ }
+ }
+ return false;
+}
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.batch;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.StringTokenizer;
+
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.compiler.ClassFile;
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.Compiler;
+import net.sourceforge.phpdt.internal.compiler.ICompilerRequestor;
+import net.sourceforge.phpdt.internal.compiler.IErrorHandlingPolicy;
+import net.sourceforge.phpdt.internal.compiler.IProblemFactory;
+import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
+import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblem;
+import net.sourceforge.phpdt.internal.compiler.problem.DefaultProblemFactory;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
+
+public class Main implements ProblemSeverities {
+
+ public boolean noWarn = false;
+
+ public PrintWriter out;
+ public boolean systemExitWhenFinished = true;
+ public boolean proceedOnError = false;
+
+ public boolean verbose = false;
+ public boolean produceRefInfo = false;
+ public boolean timer = false;
+ public boolean showProgress = false;
+ public long time = 0;
+ public long lineCount;
+ public boolean generatePackagesStructure;
+
+ public Hashtable options;
+ public String[] filenames;
+ public String[] encodings;
+ public String[] classpaths;
+ public String destinationPath;
+ public String log;
+ public int repetitions;
+ public int globalProblemsCount;
+ public int globalErrorsCount;
+ public int globalWarningsCount;
+ public int exportedClassFilesCounter;
+
+ public static final char[] CLASS_FILE_EXTENSION = ".class".toCharArray(); //$NON-NLS-1$
+ public final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+ public final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+
+ /* Bundle containing messages */
+ public static ResourceBundle bundle;
+ public final static String bundleName =
+ "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$
+
+ static {
+ relocalize();
+ }
+
+ public boolean proceed = true;
+
+ public Main(PrintWriter writer, boolean systemExitWhenFinished) {
+
+ this.out = writer;
+ this.systemExitWhenFinished = systemExitWhenFinished;
+ exportedClassFilesCounter = 0;
+ options = new Hashtable();
+ options.put(
+ CompilerOptions.OPTION_LocalVariableAttribute,
+ CompilerOptions.DO_NOT_GENERATE);
+ options.put(
+ CompilerOptions.OPTION_LineNumberAttribute,
+ CompilerOptions.DO_NOT_GENERATE);
+ options.put(
+ CompilerOptions.OPTION_SourceFileAttribute,
+ CompilerOptions.DO_NOT_GENERATE);
+ options.put(
+ CompilerOptions.OPTION_PreserveUnusedLocal,
+ CompilerOptions.OPTIMIZE_OUT);
+ options.put(
+ CompilerOptions.OPTION_ReportUnreachableCode,
+ CompilerOptions.ERROR);
+ options.put(CompilerOptions.OPTION_ReportInvalidImport, CompilerOptions.ERROR);
+ options.put(
+ CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
+ CompilerOptions.WARNING);
+ options.put(
+ CompilerOptions.OPTION_ReportMethodWithConstructorName,
+ CompilerOptions.WARNING);
+ options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+ options.put(
+ CompilerOptions.OPTION_ReportHiddenCatchBlock,
+ CompilerOptions.WARNING);
+ options.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportUnusedParameter,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportAssertIdentifier,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_Compliance,
+ CompilerOptions.VERSION_1_3);
+ options.put(
+ CompilerOptions.OPTION_Source,
+ CompilerOptions.VERSION_1_3);
+ options.put(
+ CompilerOptions.OPTION_TargetPlatform,
+ CompilerOptions.VERSION_1_1);
+ }
+
+ /*
+ * Low-level API performing the actual compilation
+ */
+ public boolean compile(String[] argv) {
+
+ // decode command line arguments
+ try {
+ configure(argv);
+ if (proceed) {
+ if (showProgress)
+ out.print(Main.bind("progress.compiling")); //$NON-NLS-1$
+ for (int i = 0; i < repetitions; i++) {
+ globalProblemsCount = 0;
+ globalErrorsCount = 0;
+ globalWarningsCount = 0;
+ lineCount = 0;
+
+ if (repetitions > 1) {
+ out.flush();
+ out.println(
+ Main.bind(
+ "compile.repetition", //$NON-NLS-1$
+ String.valueOf(i + 1),
+ String.valueOf(repetitions)));
+ }
+ long startTime = System.currentTimeMillis();
+ // request compilation
+ performCompilation();
+ if (timer) {
+
+ time = System.currentTimeMillis() - startTime;
+ if (lineCount != 0) {
+ out.println(
+ Main.bind(
+ "compile.instantTime", //$NON-NLS-1$
+ new String[] {
+ String.valueOf(lineCount),
+ String.valueOf(time),
+ String.valueOf((((int) ((lineCount * 10000.0) / time)) / 10.0))}));
+ } else {
+ out.println(Main.bind("compile.totalTime", String.valueOf(time))); //$NON-NLS-1$
+ }
+ }
+ if (globalProblemsCount > 0) {
+ if (globalProblemsCount == 1) {
+ out.print(Main.bind("compile.oneProblem")); //$NON-NLS-1$
+ } else {
+ out.print(
+ Main.bind("compile.severalProblems", String.valueOf(globalProblemsCount))); //$NON-NLS-1$
+ }
+ out.print(" ("); //$NON-NLS-1$
+ if (globalErrorsCount > 0) {
+ if (globalErrorsCount == 1) {
+ out.print(Main.bind("compile.oneError")); //$NON-NLS-1$
+ } else {
+ out.print(
+ Main.bind("compile.severalErrors", String.valueOf(globalErrorsCount))); //$NON-NLS-1$
+ }
+ }
+ if (globalWarningsCount > 0) {
+ if (globalErrorsCount > 0) {
+ out.print(", "); //$NON-NLS-1$
+ }
+ if (globalWarningsCount == 1) {
+ out.print(Main.bind("compile.oneWarning")); //$NON-NLS-1$
+ } else {
+ out.print(
+ Main.bind("compile.severalWarnings", String.valueOf(globalWarningsCount))); //$NON-NLS-1$
+ }
+ }
+ out.println(")"); //$NON-NLS-1$
+ }
+ if (exportedClassFilesCounter != 0
+ && (this.showProgress || this.timer || this.verbose)) {
+ if (exportedClassFilesCounter == 1) {
+ out.print(Main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
+ } else {
+ out.print(
+ Main.bind(
+ "compile.severalClassFilesGenerated", //$NON-NLS-1$
+ String.valueOf(exportedClassFilesCounter)));
+ }
+ }
+ }
+ if (showProgress)
+ System.out.println();
+ }
+ if (systemExitWhenFinished) {
+ out.flush();
+ System.exit(globalErrorsCount > 0 ? -1 : 0);
+ }
+ } catch (InvalidInputException e) {
+ out.println(e.getMessage());
+ out.println("------------------------"); //$NON-NLS-1$
+ printUsage();
+ if (systemExitWhenFinished) {
+ System.exit(-1);
+ }
+ } catch (ThreadDeath e) { // do not stop this one
+ throw e;
+ } catch (Throwable e) { // internal compiler error
+ if (systemExitWhenFinished) {
+ out.flush();
+ if (this.log != null) {
+ out.close();
+ }
+ System.exit(-1);
+ }
+ //e.printStackTrace();
+ } finally {
+ out.flush();
+ if (this.log != null) {
+ out.close();
+ }
+ }
+ if (globalErrorsCount == 0){
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /*
+ * Internal IDE API
+ */
+ public static boolean compile(String commandLine) {
+
+ return compile(commandLine, new PrintWriter(System.out));
+ }
+
+ /*
+ * Internal IDE API for test harness purpose
+ */
+ public static boolean compile(String commandLine, PrintWriter writer) {
+
+ return new Main(writer, false).compile(tokenize(commandLine));
+ }
+
+ public static String[] tokenize(String commandLine) {
+
+ int count = 0;
+ String[] arguments = new String[10];
+ StringTokenizer tokenizer = new StringTokenizer(commandLine, " \"", true); //$NON-NLS-1$
+ String token = "", lastToken; //$NON-NLS-1$
+ boolean insideQuotes = false;
+ boolean startNewToken = true;
+
+ // take care to quotes on the command line
+ // 'xxx "aaa bbb";ccc yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
+ // 'xxx "aaa bbb;ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
+ // 'xxx "aaa bbb";"ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
+ // 'xxx/"aaa bbb";"ccc" yyy' ---> {"xxx/aaa bbb;ccc", "yyy" }
+ while (tokenizer.hasMoreTokens()) {
+ lastToken = token;
+ token = tokenizer.nextToken();
+
+ if (token.equals(" ")) { //$NON-NLS-1$
+ if (insideQuotes) {
+ arguments[count - 1] += token;
+ startNewToken = false;
+ } else {
+ startNewToken = true;
+ }
+ } else if (token.equals("\"")) { //$NON-NLS-1$
+ if (!insideQuotes && startNewToken) { //$NON-NLS-1$
+ if (count == arguments.length)
+ System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
+ arguments[count++] = ""; //$NON-NLS-1$
+ }
+ insideQuotes = !insideQuotes;
+ startNewToken = false;
+ } else {
+ if (insideQuotes) {
+ arguments[count - 1] += token;
+ } else {
+ if (token.length() > 0 && !startNewToken) {
+ arguments[count - 1] += token;
+ } else {
+ if (count == arguments.length)
+ System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
+ arguments[count++] = token;
+ }
+ }
+ startNewToken = false;
+ }
+ }
+ System.arraycopy(arguments, 0, arguments = new String[count], 0, count);
+ return arguments;
+ }
+
+ /*
+ Decode the command line arguments
+ */
+ public void configure(String[] argv) throws InvalidInputException {
+
+ if ((argv == null) || (argv.length == 0))
+ throw new InvalidInputException(Main.bind("configure.noSourceFile")); //$NON-NLS-1$
+ final int InsideClasspath = 1;
+ final int InsideDestinationPath = 2;
+ final int TargetSetting = 4;
+ final int InsideLog = 8;
+ final int InsideRepetition = 16;
+ final int InsideSource = 32;
+ final int InsideDefaultEncoding = 64;
+ final int Default = 0;
+ int DEFAULT_SIZE_CLASSPATH = 4;
+ boolean warnOptionInUse = false;
+ boolean noWarnOptionInUse = false;
+ int pathCount = 0;
+ int index = -1, filesCount = 0, argCount = argv.length;
+ int mode = Default;
+ repetitions = 0;
+ boolean versionIDRequired = false;
+ boolean printUsageRequired = false;
+
+ boolean didSpecifyCompliance = false;
+ boolean didSpecifySourceLevel = false;
+ boolean didSpecifyDefaultEncoding = false;
+ boolean didSpecifyTarget = false;
+
+ String customEncoding = null;
+ String currentArg = ""; //$NON-NLS-1$
+
+ while (++index < argCount) {
+
+ if (customEncoding != null) {
+ throw new InvalidInputException(
+ Main.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
+ }
+
+ currentArg = argv[index].trim();
+
+ customEncoding = null;
+ if (currentArg.endsWith("]")) { //$NON-NLS-1$
+ // look for encoding specification
+ int encodingStart = currentArg.indexOf('[') + 1;
+ int encodingEnd = currentArg.length() - 1;
+ if (encodingStart >= 1) {
+ if (encodingStart < encodingEnd) {
+ customEncoding = currentArg.substring(encodingStart, encodingEnd);
+ try { // ensure encoding is supported
+ new InputStreamReader(new ByteArrayInputStream(new byte[0]), customEncoding);
+ } catch (UnsupportedEncodingException e) {
+ throw new InvalidInputException(
+ Main.bind("configure.unsupportedEncoding", customEncoding)); //$NON-NLS-1$
+ }
+ }
+ currentArg = currentArg.substring(0, encodingStart - 1);
+ }
+ }
+
+ if (currentArg.endsWith(".java")) { //$NON-NLS-1$
+ if (filenames == null) {
+ filenames = new String[argCount - index];
+ encodings = new String[argCount - index];
+ } else if (filesCount == filenames.length) {
+ int length = filenames.length;
+ System.arraycopy(
+ filenames,
+ 0,
+ (filenames = new String[length + argCount - index]),
+ 0,
+ length);
+ System.arraycopy(
+ encodings,
+ 0,
+ (encodings = new String[length + argCount - index]),
+ 0,
+ length);
+ }
+ filenames[filesCount] = currentArg;
+ encodings[filesCount++] = customEncoding;
+ customEncoding = null;
+ mode = Default;
+ continue;
+ }
+ if (currentArg.equals("-log")) { //$NON-NLS-1$
+ if (log != null)
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
+ mode = InsideLog;
+ continue;
+ }
+ if (currentArg.equals("-repeat")) { //$NON-NLS-1$
+ if (repetitions > 0)
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
+ mode = InsideRepetition;
+ continue;
+ }
+ if (currentArg.equals("-source")) { //$NON-NLS-1$
+ mode = InsideSource;
+ didSpecifySourceLevel = true;
+ continue;
+ }
+ if (currentArg.equals("-encoding")) { //$NON-NLS-1$
+ mode = InsideDefaultEncoding;
+ continue;
+ }
+ if (currentArg.equals("-1.3")) { //$NON-NLS-1$
+ if (didSpecifyCompliance) {
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$
+ }
+ didSpecifyCompliance = true;
+ options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
+ mode = Default;
+ continue;
+ }
+ if (currentArg.equals("-1.4")) { //$NON-NLS-1$
+ if (didSpecifyCompliance) {
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateCompliance", currentArg)); //$NON-NLS-1$
+ }
+ didSpecifyCompliance = true;
+ options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+ mode = Default;
+ continue;
+ }
+ if (currentArg.equals("-d")) { //$NON-NLS-1$
+ if (destinationPath != null)
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateOutputPath", currentArg)); //$NON-NLS-1$
+ mode = InsideDestinationPath;
+ generatePackagesStructure = true;
+ continue;
+ }
+ if (currentArg.equals("-classpath") //$NON-NLS-1$
+ || currentArg.equals("-cp")) { //$NON-NLS-1$ //$NON-NLS-2$
+ if (pathCount > 0)
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateClasspath", currentArg)); //$NON-NLS-1$
+ classpaths = new String[DEFAULT_SIZE_CLASSPATH];
+ mode = InsideClasspath;
+ continue;
+ }
+ if (currentArg.equals("-progress")) { //$NON-NLS-1$
+ mode = Default;
+ showProgress = true;
+ continue;
+ }
+ if (currentArg.equals("-proceedOnError")) { //$NON-NLS-1$
+ mode = Default;
+ proceedOnError = true;
+ continue;
+ }
+ if (currentArg.equals("-time")) { //$NON-NLS-1$
+ mode = Default;
+ timer = true;
+ continue;
+ }
+ if (currentArg.equals("-version") //$NON-NLS-1$
+ || currentArg.equals("-v")) { //$NON-NLS-1$ //$NON-NLS-2$
+ versionIDRequired = true;
+ continue;
+ }
+ if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
+ warnOptionInUse = true;
+ if (noWarnOptionInUse)
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateWarningConfiguration")); //$NON-NLS-1$
+ options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
+ continue;
+ }
+ if (currentArg.equals("-help")) { //$NON-NLS-1$
+ printUsageRequired = true;
+ continue;
+ }
+ if (currentArg.equals("-noImportError")) { //$NON-NLS-1$
+ mode = Default;
+ options.put(
+ CompilerOptions.OPTION_ReportInvalidImport,
+ CompilerOptions.WARNING);
+ continue;
+ }
+ if (currentArg.equals("-noExit")) { //$NON-NLS-1$
+ mode = Default;
+ systemExitWhenFinished = false;
+ continue;
+ }
+ if (currentArg.equals("-verbose")) { //$NON-NLS-1$
+ mode = Default;
+ verbose = true;
+ continue;
+ }
+ if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
+ mode = Default;
+ produceRefInfo = true;
+ continue;
+ }
+ if (currentArg.startsWith("-g")) { //$NON-NLS-1$
+ mode = Default;
+ String debugOption = currentArg;
+ int length = currentArg.length();
+ if (length == 2) {
+ options.put(
+ CompilerOptions.OPTION_LocalVariableAttribute,
+ CompilerOptions.GENERATE);
+ options.put(
+ CompilerOptions.OPTION_LineNumberAttribute,
+ CompilerOptions.GENERATE);
+ options.put(
+ CompilerOptions.OPTION_SourceFileAttribute,
+ CompilerOptions.GENERATE);
+ continue;
+ }
+ if (length > 3) {
+ options.put(
+ CompilerOptions.OPTION_LocalVariableAttribute,
+ CompilerOptions.DO_NOT_GENERATE);
+ options.put(
+ CompilerOptions.OPTION_LineNumberAttribute,
+ CompilerOptions.DO_NOT_GENERATE);
+ options.put(
+ CompilerOptions.OPTION_SourceFileAttribute,
+ CompilerOptions.DO_NOT_GENERATE);
+ if (length == 7 && debugOption.equals("-g:none")) //$NON-NLS-1$
+ continue;
+ StringTokenizer tokenizer =
+ new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (token.equals("vars")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_LocalVariableAttribute,
+ CompilerOptions.GENERATE);
+ } else if (token.equals("lines")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_LineNumberAttribute,
+ CompilerOptions.GENERATE);
+ } else if (token.equals("source")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_SourceFileAttribute,
+ CompilerOptions.GENERATE);
+ } else {
+ throw new InvalidInputException(
+ Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
+ //$NON-NLS-1$
+ }
+ }
+ continue;
+ }
+ throw new InvalidInputException(
+ Main.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
+ }
+ if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
+ noWarnOptionInUse = true;
+ noWarn = true;
+ if (warnOptionInUse)
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateWarningConfiguration")); //$NON-NLS-1$
+ mode = Default;
+ continue;
+ }
+ if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
+ warnOptionInUse = true;
+ if (noWarnOptionInUse)
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateWarningConfiguration")); //$NON-NLS-1$
+ mode = Default;
+ String warningOption = currentArg;
+ int length = currentArg.length();
+ if (length == 10 && warningOption.equals("-warn:none")) { //$NON-NLS-1$
+ noWarn = true;
+ continue;
+ }
+ if (length < 6)
+ throw new InvalidInputException(
+ Main.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
+ StringTokenizer tokenizer =
+ new StringTokenizer(warningOption.substring(6, warningOption.length()), ","); //$NON-NLS-1$
+ int tokenCounter = 0;
+
+ options.put(
+ CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportMethodWithConstructorName,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportDeprecation,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportHiddenCatchBlock,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportUnusedLocal,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportUnusedParameter,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportAssertIdentifier,
+ CompilerOptions.IGNORE);
+ options.put(
+ CompilerOptions.OPTION_ReportUnusedImport,
+ CompilerOptions.IGNORE);
+
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ tokenCounter++;
+ if (token.equals("constructorName")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportMethodWithConstructorName,
+ CompilerOptions.WARNING);
+ } else if (token.equals("packageDefaultMethod")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod,
+ CompilerOptions.WARNING);
+ } else if (token.equals("maskedCatchBlocks")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportHiddenCatchBlock,
+ CompilerOptions.WARNING);
+ } else if (token.equals("deprecation")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportDeprecation,
+ CompilerOptions.WARNING);
+ } else if (token.equals("unusedLocals")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportUnusedLocal,
+ CompilerOptions.WARNING);
+ } else if (token.equals("unusedArguments")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportUnusedParameter,
+ CompilerOptions.WARNING);
+ } else if (token.equals("unusedImports")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportUnusedImport,
+ CompilerOptions.WARNING);
+ } else if (token.equals("syntheticAccess")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportSyntheticAccessEmulation,
+ CompilerOptions.WARNING);
+ } else if (token.equals("nls")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportNonExternalizedStringLiteral,
+ CompilerOptions.WARNING);
+ } else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_ReportAssertIdentifier,
+ CompilerOptions.WARNING);
+ } else {
+ throw new InvalidInputException(Main.bind("configure.invalidWarning", token)); //$NON-NLS-1$
+ }
+ }
+ if (tokenCounter == 0)
+ throw new InvalidInputException(
+ Main.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
+ continue;
+ }
+ if (currentArg.equals("-target")) { //$NON-NLS-1$
+ didSpecifyTarget = true;
+ mode = TargetSetting;
+ continue;
+ }
+ if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
+ options.put(
+ CompilerOptions.OPTION_PreserveUnusedLocal,
+ CompilerOptions.PRESERVE);
+ continue;
+ }
+ if (mode == TargetSetting) {
+ if (currentArg.equals("1.1")) { //$NON-NLS-1$
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+ } else if (currentArg.equals("1.2")) { //$NON-NLS-1$
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
+ } else if (currentArg.equals("1.3")) { //$NON-NLS-1$
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_3);
+ } else if (currentArg.equals("1.4")) { //$NON-NLS-1$
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+ } else {
+ throw new InvalidInputException(Main.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
+ }
+ mode = Default;
+ continue;
+ }
+ if (mode == InsideLog) {
+ log = currentArg;
+ mode = Default;
+ continue;
+ }
+ if (mode == InsideRepetition) {
+ try {
+ repetitions = Integer.parseInt(currentArg);
+ if (repetitions <= 0) {
+ throw new InvalidInputException(Main.bind("configure.repetition", currentArg)); //$NON-NLS-1$
+ }
+ } catch (NumberFormatException e) {
+ throw new InvalidInputException(Main.bind("configure.repetition", currentArg)); //$NON-NLS-1$
+ }
+ mode = Default;
+ continue;
+ }
+ if (mode == InsideSource) {
+ if (currentArg.equals("1.3")) { //$NON-NLS-1$
+ options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+ } else if (currentArg.equals("1.4")) { //$NON-NLS-1$
+ options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
+ } else {
+ throw new InvalidInputException(Main.bind("configure.source", currentArg)); //$NON-NLS-1$
+ }
+ mode = Default;
+ continue;
+ }
+ if (mode == InsideDefaultEncoding) {
+ if (didSpecifyDefaultEncoding) {
+ throw new InvalidInputException(
+ Main.bind("configure.duplicateDefaultEncoding", currentArg)); //$NON-NLS-1$
+ }
+ try { // ensure encoding is supported
+ new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg);
+ } catch (UnsupportedEncodingException e) {
+ throw new InvalidInputException(
+ Main.bind("configure.unsupportedEncoding", currentArg)); //$NON-NLS-1$
+ }
+ options.put(CompilerOptions.OPTION_Encoding, currentArg);
+ didSpecifyDefaultEncoding = true;
+ mode = Default;
+ continue;
+ }
+ if (mode == InsideDestinationPath) {
+ destinationPath = currentArg;
+ mode = Default;
+ continue;
+ }
+ if (mode == InsideClasspath) {
+ StringTokenizer tokenizer = new StringTokenizer(currentArg, File.pathSeparator);
+ while (tokenizer.hasMoreTokens()) {
+ int length;
+ if ((length = classpaths.length) <= pathCount) {
+ System.arraycopy(
+ classpaths,
+ 0,
+ (classpaths = new String[length * 2]),
+ 0,
+ length);
+ }
+ classpaths[pathCount++] = tokenizer.nextToken();
+ }
+ mode = Default;
+ continue;
+ }
+ //default is input directory
+ currentArg = currentArg.replace('/', File.separatorChar);
+ if (currentArg.endsWith(File.separator))
+ currentArg =
+ currentArg.substring(0, currentArg.length() - File.separator.length());
+ File dir = new File(currentArg);
+ if (!dir.isDirectory())
+ throw new InvalidInputException(
+ Main.bind("configure.directoryNotExist", currentArg)); //$NON-NLS-1$
+ FileFinder finder = new FileFinder();
+ try {
+ finder.find(dir, ".JAVA", verbose); //$NON-NLS-1$
+ } catch (Exception e) {
+ throw new InvalidInputException(Main.bind("configure.IOError", currentArg)); //$NON-NLS-1$
+ }
+ if (filenames != null) {
+ // some source files were specified explicitly
+ String results[] = finder.resultFiles;
+ int length = results.length;
+ System.arraycopy(
+ filenames,
+ 0,
+ (filenames = new String[length + filesCount]),
+ 0,
+ filesCount);
+ System.arraycopy(
+ encodings,
+ 0,
+ (encodings = new String[length + filesCount]),
+ 0,
+ filesCount);
+ System.arraycopy(results, 0, filenames, filesCount, length);
+ for (int i = 0; i < length; i++) {
+ encodings[filesCount + i] = customEncoding;
+ }
+ filesCount += length;
+ customEncoding = null;
+ } else {
+ filenames = finder.resultFiles;
+ filesCount = filenames.length;
+ encodings = new String[filesCount];
+ for (int i = 0; i < filesCount; i++) {
+ encodings[i] = customEncoding;
+ }
+ customEncoding = null;
+ }
+ mode = Default;
+ continue;
+ }
+
+ if (noWarn) {
+ // filter options which are related to the assist component
+ Object[] entries = options.entrySet().toArray();
+ for (int i = 0, max = entries.length; i < max; i++) {
+ Map.Entry entry = (Map.Entry) entries[i];
+ if (!(entry.getKey() instanceof String))
+ continue;
+ if (!(entry.getValue() instanceof String))
+ continue;
+ if (((String) entry.getValue()).equals(CompilerOptions.WARNING)) {
+ options.put((String) entry.getKey(), CompilerOptions.IGNORE);
+ }
+ }
+ }
+ /*
+ * Standalone options
+ */
+ if (versionIDRequired) {
+ out.println(Main.bind("configure.version", Main.bind("compiler.version"))); //$NON-NLS-1$ //$NON-NLS-2$
+ out.println();
+ proceed = false;
+ return;
+ }
+
+ if (printUsageRequired) {
+ printUsage();
+ proceed = false;
+ return;
+ }
+
+ if (filesCount != 0)
+ System.arraycopy(
+ filenames,
+ 0,
+ (filenames = new String[filesCount]),
+ 0,
+ filesCount);
+ if (pathCount == 0) {
+ String classProp = System.getProperty("DEFAULT_CLASSPATH"); //$NON-NLS-1$
+ if ((classProp == null) || (classProp.length() == 0)) {
+ out.println(Main.bind("configure.noClasspath")); //$NON-NLS-1$
+ classProp = "."; //$NON-NLS-1$
+ }
+ StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
+ classpaths = new String[tokenizer.countTokens()];
+ while (tokenizer.hasMoreTokens()) {
+ classpaths[pathCount++] = tokenizer.nextToken();
+ }
+ }
+
+ if (classpaths == null)
+ classpaths = new String[0];
+ System.arraycopy(
+ classpaths,
+ 0,
+ (classpaths = new String[pathCount]),
+ 0,
+ pathCount);
+ for (int i = 0, max = classpaths.length; i < max; i++) {
+ File file = new File(classpaths[i]);
+ if (!file.exists()) // signal missing classpath entry file
+ out.println(Main.bind("configure.incorrectClasspath", classpaths[i])); //$NON-NLS-1$
+ }
+ if (destinationPath == null) {
+ generatePackagesStructure = false;
+ } else if ("none".equals(destinationPath)) { //$NON-NLS-1$
+ destinationPath = null;
+ }
+
+ if (filenames == null)
+ throw new InvalidInputException(Main.bind("configure.noSource")); //$NON-NLS-1$
+
+ // check and set compliance/source/target compatibilities
+ if (!didSpecifyCompliance){
+ if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)){
+ options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
+ } else {
+ options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
+ }
+ }
+ String compliance = (String)options.get(CompilerOptions.OPTION_Compliance);
+ if (CompilerOptions.VERSION_1_4.equals(compliance)){
+
+ // default 1.4 settings
+ if (!didSpecifySourceLevel){
+ options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
+ }
+ if (!didSpecifyTarget){
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
+ }
+ } else if (CompilerOptions.VERSION_1_3.equals(compliance)){
+
+ // default 1.4 settings
+ if (!didSpecifySourceLevel){
+ options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
+ }
+ if (!didSpecifyTarget){
+ options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
+ }
+ }
+ // compliance must be 1.4 if source is 1.4
+ if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
+ && !options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){
+ throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForSource14", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
+ }
+
+ // target must be 1.4 if source is 1.4
+ if (options.get(CompilerOptions.OPTION_Source).equals(CompilerOptions.VERSION_1_4)
+ && !options.get(CompilerOptions.OPTION_TargetPlatform).equals(CompilerOptions.VERSION_1_4)){
+ throw new InvalidInputException(Main.bind("configure.incompatibleTargetForSource14", (String)options.get(CompilerOptions.OPTION_TargetPlatform))); //$NON-NLS-1$
+ }
+
+ // target cannot be 1.4 if compliance is 1.3
+ if (options.get(CompilerOptions.OPTION_TargetPlatform).equals(CompilerOptions.VERSION_1_4)
+ && !options.get(CompilerOptions.OPTION_Compliance).equals(CompilerOptions.VERSION_1_4)){
+ throw new InvalidInputException(Main.bind("configure.incompatibleComplianceForTarget14", (String)options.get(CompilerOptions.OPTION_Compliance))); //$NON-NLS-1$
+ }
+
+ if (log != null) {
+ try {
+ out = new PrintWriter(new FileOutputStream(log, false));
+ } catch (IOException e) {
+ throw new InvalidInputException(Main.bind("configure.cannotOpenLog")); //$NON-NLS-1$
+ }
+ } else {
+ showProgress = false;
+ }
+
+ if (repetitions == 0) {
+ repetitions = 1;
+ }
+ }
+ public Map getOptions() {
+ return this.options;
+ }
+ /*
+ * Answer the component to which will be handed back compilation results from the compiler
+ */
+ public ICompilerRequestor getBatchRequestor() {
+ return new ICompilerRequestor() {
+ int lineDelta = 0;
+ public void acceptResult(CompilationResult compilationResult) {
+ if (compilationResult.lineSeparatorPositions != null) {
+ int unitLineCount = compilationResult.lineSeparatorPositions.length;
+ lineCount += unitLineCount;
+ lineDelta += unitLineCount;
+ if (showProgress
+ && lineDelta > 2000) { // in -log mode, dump a dot every 2000 lines compiled
+ System.out.print('.');
+ lineDelta = 0;
+ }
+ }
+ if (compilationResult.hasProblems()) {
+ IProblem[] problems = compilationResult.getProblems();
+ int count = problems.length;
+ int localErrorCount = 0;
+ for (int i = 0; i < count; i++) {
+ if (problems[i] != null) {
+ globalProblemsCount++;
+ if (localErrorCount == 0)
+ out.println("----------"); //$NON-NLS-1$
+ out.print(
+ globalProblemsCount
+ + ". " //$NON-NLS-1$
+ + (problems[i].isError()
+ ? Main.bind("requestor.error") //$NON-NLS-1$
+ : Main.bind("requestor.warning"))); //$NON-NLS-1$
+ if (problems[i].isError()) {
+ globalErrorsCount++;
+ } else {
+ globalWarningsCount++;
+ }
+ out.print(" "); //$NON-NLS-1$
+ out.print(
+ Main.bind("requestor.in", new String(problems[i].getOriginatingFileName()))); //$NON-NLS-1$
+ try {
+ out.println(
+ ((DefaultProblem) problems[i]).errorReportSource(
+ compilationResult.compilationUnit));
+ out.println(problems[i].getMessage());
+ } catch (Exception e) {
+ out.println(
+ Main.bind("requestor.notRetrieveErrorMessage", problems[i].toString())); //$NON-NLS-1$
+ }
+ out.println("----------"); //$NON-NLS-1$
+ if (problems[i].isError())
+ localErrorCount++;
+ }
+ };
+ // exit?
+ if (systemExitWhenFinished && !proceedOnError && (localErrorCount > 0)) {
+ out.flush();
+ System.exit(-1);
+ }
+ }
+ outputClassFiles(compilationResult);
+ }
+ };
+ }
+ /*
+ * Build the set of compilation source units
+ */
+ public CompilationUnit[] getCompilationUnits()
+ throws InvalidInputException {
+ int fileCount = filenames.length;
+ CompilationUnit[] units = new CompilationUnit[fileCount];
+ HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
+
+ String defaultEncoding = (String) options.get(CompilerOptions.OPTION_Encoding);
+ if ("".equals(defaultEncoding)) //$NON-NLS-1$
+ defaultEncoding = null; //$NON-NLS-1$
+
+ for (int i = 0; i < fileCount; i++) {
+ char[] charName = filenames[i].toCharArray();
+ if (knownFileNames.get(charName) != null) {
+ throw new InvalidInputException(Main.bind("unit.more", filenames[i])); //$NON-NLS-1$
+ } else {
+ knownFileNames.put(charName, charName);
+ }
+ File file = new File(filenames[i]);
+ if (!file.exists())
+ throw new InvalidInputException(Main.bind("unit.missing", filenames[i])); //$NON-NLS-1$
+ String encoding = encodings[i];
+ if (encoding == null)
+ encoding = defaultEncoding;
+ units[i] = new CompilationUnit(null, filenames[i], encoding);
+ }
+ return units;
+ }
+ /*
+ * Low-level API performing the actual compilation
+ */
+ public IErrorHandlingPolicy getHandlingPolicy() {
+
+ // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
+ return new IErrorHandlingPolicy() {
+ public boolean stopOnFirstError() {
+ return false;
+ }
+ public boolean proceedOnErrors() {
+ return proceedOnError; // stop if there are some errors
+ }
+ };
+ }
+ /*
+ * Low-level API performing the actual compilation
+ */
+ public FileSystem getLibraryAccess() {
+
+ String defaultEncoding = (String) options.get(CompilerOptions.OPTION_Encoding);
+ if ("".equals(defaultEncoding)) //$NON-NLS-1$
+ defaultEncoding = null; //$NON-NLS-1$
+ return new FileSystem(classpaths, filenames, defaultEncoding);
+ }
+ /*
+ * Low-level API performing the actual compilation
+ */
+ public IProblemFactory getProblemFactory() {
+ return new DefaultProblemFactory(Locale.getDefault());
+ }
+ /*
+ * External API
+ */
+
+ public static void main(String[] argv) {
+ new Main(new PrintWriter(System.out), true).compile(argv);
+ }
+ // Dump classfiles onto disk for all compilation units that where successfull.
+
+ public void outputClassFiles(CompilationResult unitResult) {
+
+ if (!((unitResult == null) || (unitResult.hasErrors() && !proceedOnError))) {
+ Enumeration classFiles = unitResult.compiledTypes.elements();
+ if (!this.generatePackagesStructure) {
+ while (classFiles.hasMoreElements()) {
+ this.destinationPath = extractDestinationPathFromSourceFile(unitResult);
+ // retrieve the key and the corresponding classfile
+ ClassFile classFile = (ClassFile) classFiles.nextElement();
+ char[] filename = classFile.fileName();
+ int length = filename.length;
+ char[] relativeName = new char[length + 6];
+ System.arraycopy(filename, 0, relativeName, 0, length);
+ System.arraycopy(CLASS_FILE_EXTENSION, 0, relativeName, length, 6);
+ CharOperation.replace(relativeName, '/', File.separatorChar);
+ try {
+ ClassFile.writeToDisk(
+ generatePackagesStructure,
+ destinationPath,
+ new String(relativeName),
+ classFile.getBytes());
+ } catch (IOException e) {
+ String fileName = destinationPath + new String(relativeName);
+ e.printStackTrace();
+ System.out.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
+ }
+ exportedClassFilesCounter++;
+ }
+ } else if (destinationPath != null) {
+ while (classFiles.hasMoreElements()) {
+ // retrieve the key and the corresponding classfile
+ ClassFile classFile = (ClassFile) classFiles.nextElement();
+ char[] filename = classFile.fileName();
+ int length = filename.length;
+ char[] relativeName = new char[length + 6];
+ System.arraycopy(filename, 0, relativeName, 0, length);
+ System.arraycopy(CLASS_FILE_EXTENSION, 0, relativeName, length, 6);
+ CharOperation.replace(relativeName, '/', File.separatorChar);
+ try {
+ ClassFile.writeToDisk(
+ generatePackagesStructure,
+ destinationPath,
+ new String(relativeName),
+ classFile.getBytes());
+ } catch (IOException e) {
+ String fileName = destinationPath + new String(relativeName);
+ e.printStackTrace();
+ System.out.println(Main.bind("output.noClassFileCreated", fileName)); //$NON-NLS-1$
+ }
+ exportedClassFilesCounter++;
+ }
+ }
+ }
+ }
+ /*
+ * Low-level API performing the actual compilation
+ */
+ public void performCompilation() throws InvalidInputException {
+
+ INameEnvironment environment = getLibraryAccess();
+ Compiler batchCompiler =
+ new Compiler(
+ environment,
+ getHandlingPolicy(),
+ getOptions(),
+ getBatchRequestor(),
+ getProblemFactory());
+ CompilerOptions options = batchCompiler.options;
+
+ // set the non-externally configurable options.
+ options.setVerboseMode(verbose);
+ options.produceReferenceInfo(produceRefInfo);
+ batchCompiler.compile(getCompilationUnits());
+
+ // cleanup
+ environment.cleanup();
+ }
+ public void printUsage() {
+ out.println(Main.bind("misc.usage", Main.bind("compiler.version"))); //$NON-NLS-1$ //$NON-NLS-2$
+ out.flush();
+ }
+
+ /**
+ * Creates a NLS catalog for the given locale.
+ */
+ public static void relocalize() {
+ bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog
+ */
+ public static String bind(String id) {
+ return bind(id, (String[]) null);
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string values.
+ */
+ public static String bind(String id, String[] bindings) {
+ if (id == null)
+ return "No message available"; //$NON-NLS-1$
+ String message = null;
+ try {
+ message = bundle.getString(id);
+ } catch (MissingResourceException e) {
+ // If we got an exception looking for the message, fail gracefully by just returning
+ // the id we were looking for. In most cases this is semi-informative so is not too bad.
+ return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ // for compatibility with MessageFormat which eliminates double quotes in original message
+ char[] messageWithNoDoubleQuotes =
+ CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+ message = new String(messageWithNoDoubleQuotes);
+
+ if (bindings == null)
+ return message;
+
+ int length = message.length();
+ int start = -1;
+ int end = length;
+ StringBuffer output = new StringBuffer(80);
+ while (true) {
+ if ((end = message.indexOf('{', start)) > -1) {
+ output.append(message.substring(start + 1, end));
+ if ((start = message.indexOf('}', end)) > -1) {
+ int index = -1;
+ try {
+ index = Integer.parseInt(message.substring(end + 1, start));
+ output.append(bindings[index]);
+ } catch (NumberFormatException nfe) {
+ output.append(message.substring(end + 1, start + 1));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ } else {
+ output.append(message.substring(end, length));
+ break;
+ }
+ } else {
+ output.append(message.substring(start + 1, length));
+ break;
+ }
+ }
+ return output.toString();
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string.
+ */
+ public static String bind(String id, String binding) {
+ return bind(id, new String[] { binding });
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given strings.
+ */
+ public static String bind(String id, String binding1, String binding2) {
+ return bind(id, new String[] { binding1, binding2 });
+ }
+
+ public String extractDestinationPathFromSourceFile(CompilationResult result) {
+ ICompilationUnit compilationUnit = result.compilationUnit;
+ if (compilationUnit != null) {
+ char[] fileName = compilationUnit.getFileName();
+ int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
+ if (lastIndex == -1) {
+ return System.getProperty("user.dir"); //$NON-NLS-1$
+ }
+ return new String(CharOperation.subarray(fileName, 0, lastIndex));
+ }
+ return System.getProperty("user.dir"); //$NON-NLS-1$
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.classfmt;
+
+import net.sourceforge.phpdt.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;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.classfmt;
+
+import net.sourceforge.phpdt.internal.compiler.codegen.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.impl.NullConstant;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+import java.io.*;
+import java.util.Arrays;
+
+public class ClassFileReader extends ClassFileStruct implements AttributeNamesConstants, IBinaryType {
+ private int constantPoolCount;
+ private int[] constantPoolOffsets;
+ 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 {
+ 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) {
+ 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 + 2);
+ 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 (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 int constantPoolIndex
+ * @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.
+ */
+ if (outerClassNameIdx != 0 && innerNameIndex != 0 && outerClassNameIdx == this.classNameIndex) {
+ 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) {
+ 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 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() {
+ return
+ this.innerInfo != null
+ && this.innerInfo.getEnclosingTypeName() == null
+ && this.innerInfo.getSourceName() != null;
+}
+/**
+ * Answer true if the receiver is a member type, false otherwise
+ *
+ * @return <CODE>boolean</CODE>
+ */
+public boolean isMember() {
+ return this.innerInfo != null && this.innerInfo.getEnclosingTypeName() != null;
+}
+/**
+ * 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 excludesSynthetics 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 = (IBinaryNestedType[]) this.getMemberTypes();
+ IBinaryNestedType[] otherMemberTypes = (IBinaryNestedType[]) 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_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());
+ case TypeIds.T_null :
+ return otherConstant != NullConstant.Default;
+ }
+ }
+ 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() {
+ 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();
+}
+protected void reset() {
+ this.constantPoolOffsets = null;
+ super.reset();
+}
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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) + ((long) (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 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) {
+ y = this.reference[readOffset++] & 0xFF;
+ length--;
+ if ((x & 0x20) != 0) {
+ z = this.reference[readOffset++] & 0xFF;
+ length--;
+ x = ((x & 0x1F) << 12) + ((y & 0x3F) << 6) + (z & 0x3F);
+ } else {
+ x = ((x & 0x1F) << 6) + (y & 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);
+ }
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.classfmt;
+
+public class ClassFormatException extends Exception {
+ private int errorCode;
+ private int bufferPosition;
+
+ 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;
+
+public ClassFormatException(int code) {
+ errorCode = code;
+}
+public ClassFormatException(int code, int bufPos) {
+ errorCode = code;
+ bufferPosition = bufPos;
+}
+/**
+ * @return int
+ */
+public int getErrorCode() {
+ return errorCode;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.classfmt;
+
+import net.sourceforge.phpdt.internal.compiler.codegen.AttributeNamesConstants;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryField;
+import net.sourceforge.phpdt.internal.compiler.impl.BooleanConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.ByteConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.CharConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.impl.DoubleConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.FloatConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.IntConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.LongConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.ShortConstant;
+import net.sourceforge.phpdt.internal.compiler.impl.StringConstant;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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 attributesCount;
+ private int attributeBytes;
+ private Object wrappedConstantValue;
+/**
+ * @param classFileBytes byte[]
+ * @param offsets int[]
+ * @param offset int
+ */
+public FieldInfo (byte classFileBytes[], int offsets[], int offset) throws ClassFormatException {
+ 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.
+ * Throws a java.ibm.compiler.java.classfmt.ClassFormatException in case the signature is
+ * incompatible with the constant tag.
+ *
+ * @exception java.ibm.compiler.java.classfmt.ClassFormatException
+ * @return java.lang.Object
+ */
+public Object getWrappedConstantValue() throws ClassFormatException {
+
+ if (this.wrappedConstantValue == null) {
+ if (hasConstant()) {
+ Constant constant = getConstant();
+ switch (constant.typeID()) {
+ case T_int :
+ this.wrappedConstantValue = new Integer(constant.intValue());
+ break;
+ case T_byte :
+ this.wrappedConstantValue = new Byte(constant.byteValue());
+ break;
+ case T_short :
+ this.wrappedConstantValue = new Short(constant.shortValue());
+ break;
+ case T_char :
+ this.wrappedConstantValue = new Character(constant.charValue());
+ break;
+ case T_float :
+ this.wrappedConstantValue = new Float(constant.floatValue());
+ break;
+ case T_double :
+ this.wrappedConstantValue = new Double(constant.doubleValue());
+ break;
+ case T_boolean :
+ this.wrappedConstantValue = new Boolean(constant.booleanValue());
+ break;
+ case T_long :
+ this.wrappedConstantValue = new Long(constant.longValue());
+ break;
+ case T_String :
+ this.wrappedConstantValue = constant.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();
+}
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.classfmt;
+
+import net.sourceforge.phpdt.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)
+ throws ClassFormatException {
+ 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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.classfmt;
+
+import net.sourceforge.phpdt.internal.compiler.codegen.AttributeNamesConstants;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryMethod;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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 attributesCount;
+ private int attributeBytes;
+ static private final char[][] noException = new char[0][0];
+ private int decodeIndex;
+/**
+ * @param classFileBytes byte[]
+ * @param offsets int[]
+ * @param offset int
+ */
+public MethodInfo (byte classFileBytes[], int offsets[], int offset) throws ClassFormatException {
+ 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 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();
+}
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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'};
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+ }
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.util.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 char[] key 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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.*;
+
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.classfmt.*;
+import net.sourceforge.phpdt.internal.compiler.flow.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+
+public class CodeStream implements OperatorIds, ClassFileConstants, Opcodes, BaseTypes, TypeConstants, TypeIds {
+ // It will be responsible for the following items.
+
+ // -> Tracking Max Stack.
+
+ public int stackMax; // Use Ints to keep from using extra bc when adding
+ public int stackDepth; // Use Ints to keep from using extra bc when adding
+ public int maxLocals;
+ public static final int max = 100; // Maximum size of the code array
+ public static final int growFactor = 400;
+ 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() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aaload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aaload);
+ }
+}
+final public void aastore() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aastore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aastore);
+ }
+}
+final public void aconst_null() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aconst_null;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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) {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals <= iArg) {
+ maxLocals = iArg + 1;
+ }
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aload);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ // Don't need to use the wide bytecode
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aload);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) (iArg);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void aload_0() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals == 0) {
+ maxLocals = 1;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aload_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aload_0);
+ }
+}
+final public void aload_1() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals <= 1) {
+ maxLocals = 2;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aload_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aload_1);
+ }
+}
+final public void aload_2() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals <= 2) {
+ maxLocals = 3;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aload_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aload_2);
+ }
+}
+final public void aload_3() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals <= 3) {
+ maxLocals = 4;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_aload_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_aload_3);
+ }
+}
+public final void anewarray(TypeBinding typeBinding) {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_anewarray;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_anewarray);
+ }
+ writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+public void anewarrayJavaLangClass() {
+ // anewarray: java.lang.Class
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_anewarray;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_anewarray);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangClass());
+}
+public void anewarrayJavaLangObject() {
+ // anewarray: java.lang.Object
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_anewarray;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_anewarray);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangObject());
+}
+final public void areturn() {
+ countLabels = 0;
+ stackDepth--;
+ // the stackDepth should be equal to 0
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_areturn;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_arraylength;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_arraylength);
+ }
+}
+final public void astore(int iArg) {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= iArg) {
+ maxLocals = iArg + 1;
+ }
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_astore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_astore);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_astore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_astore);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void astore_0() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals == 0) {
+ maxLocals = 1;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_astore_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_astore_0);
+ }
+}
+final public void astore_1() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 1) {
+ maxLocals = 2;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_astore_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_astore_1);
+ }
+}
+final public void astore_2() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 2) {
+ maxLocals = 3;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_astore_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_astore_2);
+ }
+}
+final public void astore_3() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 3) {
+ maxLocals = 4;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_astore_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_astore_3);
+ }
+}
+final public void athrow() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_athrow;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_athrow);
+ }
+}
+final public void baload() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_baload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_baload);
+ }
+}
+final public void bastore() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_bastore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_bastore);
+ }
+}
+final public void bipush(byte b) {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_bipush;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_bipush);
+ }
+ writeSignedByte(b);
+}
+final public void caload() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_caload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_caload);
+ }
+}
+final public void castore() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_castore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_castore);
+ }
+}
+public final void checkcast(TypeBinding typeBinding) {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_checkcast;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_checkcast);
+ }
+ writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+public final void checkcastJavaLangError() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_checkcast;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_checkcast);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangError());
+}
+final public void d2f() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_d2f;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_d2f);
+ }
+}
+final public void d2i() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_d2i;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_d2i);
+ }
+}
+final public void d2l() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_d2l;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_d2l);
+ }
+}
+final public void dadd() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dadd;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dadd);
+ }
+}
+final public void daload() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_daload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_daload);
+ }
+}
+final public void dastore() {
+ countLabels = 0;
+ stackDepth -= 4;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dastore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dastore);
+ }
+}
+final public void dcmpg() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dcmpg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dcmpg);
+ }
+}
+final public void dcmpl() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dcmpl;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dcmpl);
+ }
+}
+final public void dconst_0() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dconst_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dconst_0);
+ }
+}
+final public void dconst_1() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dconst_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dconst_1);
+ }
+}
+final public void ddiv() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ddiv;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ddiv);
+ }
+}
+public void decrStackSize(int offset) {
+ stackDepth -= offset;
+}
+final public void dload(int iArg) {
+ 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
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dload);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ // Don't need to use the wide bytecode
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dload);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void dload_0() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals < 2) {
+ maxLocals = 2;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dload_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dload_0);
+ }
+}
+final public void dload_1() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals < 3) {
+ maxLocals = 3;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dload_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dload_1);
+ }
+}
+final public void dload_2() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals < 4) {
+ maxLocals = 4;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dload_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dload_2);
+ }
+}
+final public void dload_3() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (maxLocals < 5) {
+ maxLocals = 5;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dload_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dload_3);
+ }
+}
+final public void dmul() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dmul;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dmul);
+ }
+}
+final public void dneg() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dneg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dneg);
+ }
+}
+final public void drem() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_drem;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_drem);
+ }
+}
+final public void dreturn() {
+ countLabels = 0;
+ stackDepth -= 2;
+ // the stackDepth should be equal to 0
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dreturn;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dreturn);
+ }
+}
+final public void dstore(int iArg) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals <= iArg + 1) {
+ maxLocals = iArg + 2;
+ }
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dstore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dstore);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dstore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dstore);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void dstore_0() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 2) {
+ maxLocals = 2;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dstore_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dstore_0);
+ }
+}
+final public void dstore_1() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 3) {
+ maxLocals = 3;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dstore_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dstore_1);
+ }
+}
+final public void dstore_2() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 4) {
+ maxLocals = 4;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dstore_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dstore_2);
+ }
+}
+final public void dstore_3() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 5) {
+ maxLocals = 5;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dstore_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dstore_3);
+ }
+}
+final public void dsub() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dsub;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dsub);
+ }
+}
+final public void dup() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dup;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dup);
+ }
+}
+final public void dup_x1() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dup_x1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dup_x1);
+ }
+}
+final public void dup_x2() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dup_x2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dup_x2);
+ }
+}
+final public void dup2() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dup2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dup2);
+ }
+}
+final public void dup2_x1() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dup2_x1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_dup2_x1);
+ }
+}
+final public void dup2_x2() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_dup2_x2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_f2d;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_f2d);
+ }
+}
+final public void f2i() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_f2i;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_f2i);
+ }
+}
+final public void f2l() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_f2l;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_f2l);
+ }
+}
+final public void fadd() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fadd;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fadd);
+ }
+}
+final public void faload() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_faload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_faload);
+ }
+}
+final public void fastore() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fastore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fastore);
+ }
+}
+final public void fcmpg() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fcmpg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fcmpg);
+ }
+}
+final public void fcmpl() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fcmpl;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fcmpl);
+ }
+}
+final public void fconst_0() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fconst_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fconst_0);
+ }
+}
+final public void fconst_1() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fconst_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fconst_1);
+ }
+}
+final public void fconst_2() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fconst_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fconst_2);
+ }
+}
+final public void fdiv() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fdiv;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fdiv);
+ }
+}
+final public void fload(int iArg) {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= iArg) {
+ maxLocals = iArg + 1;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fload);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fload);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void fload_0() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals == 0) {
+ maxLocals = 1;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fload_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fload_0);
+ }
+}
+final public void fload_1() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= 1) {
+ maxLocals = 2;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fload_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fload_1);
+ }
+}
+final public void fload_2() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= 2) {
+ maxLocals = 3;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fload_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fload_2);
+ }
+}
+final public void fload_3() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= 3) {
+ maxLocals = 4;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fload_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fload_3);
+ }
+}
+final public void fmul() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fmul;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fmul);
+ }
+}
+final public void fneg() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fneg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fneg);
+ }
+}
+final public void frem() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_frem;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_frem);
+ }
+}
+final public void freturn() {
+ countLabels = 0;
+ stackDepth--;
+ // the stackDepth should be equal to 0
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_freturn;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_freturn);
+ }
+}
+final public void fstore(int iArg) {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= iArg) {
+ maxLocals = iArg + 1;
+ }
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fstore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fstore);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fstore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fstore);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void fstore_0() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals == 0) {
+ maxLocals = 1;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fstore_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fstore_0);
+ }
+}
+final public void fstore_1() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 1) {
+ maxLocals = 2;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fstore_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fstore_1);
+ }
+}
+final public void fstore_2() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 2) {
+ maxLocals = 3;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fstore_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fstore_2);
+ }
+}
+final public void fstore_3() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 3) {
+ maxLocals = 4;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fstore_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_fstore_3);
+ }
+}
+final public void fsub() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_fsub;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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, TypeBinding.NullBinding /* represents ClassNotFoundException*/);
+ this.ldc(accessedType == TypeBinding.NullBinding ? "java.lang.Object" : String.valueOf(accessedType.constantPoolName()).replace('/', '.')); //$NON-NLS-1$
+ this.invokeClassForName();
+
+ /* 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 returns the exception handler to be able to generate the exception handler
+ * attribute.
+ */
+final public int[] generateCodeAttributeForProblemMethod(String errorName, String problemMessage) {
+ /**
+ * Equivalent code:
+ * try {
+ * throw ((Error) (Class.forName(errorName).getConstructor(new Class[] {Class.forName("java.lang.String")})).newInstance(new Object[] {problemMessage}));
+ * } catch (Exception e) {
+ * throw (NullPointerException) null;
+ * }
+ */
+ int endPC, handlerPC;
+ ldc(errorName);
+ invokeClassForName();
+ iconst_1();
+ anewarrayJavaLangClass();
+ dup();
+ iconst_0();
+ ldc("java.lang.String"); //$NON-NLS-1$
+ invokeClassForName();
+ aastore();
+ invokeConstructorGetConstructor();
+ iconst_1();
+ anewarrayJavaLangObject();
+ dup();
+ iconst_0();
+ ldc(problemMessage);
+ aastore();
+ invokeObjectNewInstance();
+ checkcastJavaLangError();
+ athrow();
+ endPC = handlerPC = position;
+ pop();
+ aconst_null();
+ athrow();
+ return_();
+ return new int[] {0, endPC, handlerPC};
+}
+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;
+ case T_String :
+ this.ldc(constant.stringValue());
+ break;
+ default : //reference object (constant can be from T_null or T_String)
+ if (constant.typeID() == T_String)
+ ldc(constant.stringValue());
+ else
+ aconst_null();
+ }
+}
+/**
+ * @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((byte) 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, Scope scope) {
+ if (mappingSequence == null)
+ return;
+ if (mappingSequence == BlockScope.EmulationPathToImplicitThis) {
+ if (scope.methodScope().isConstructorCall){
+ scope.problemReporter().errorThisSuperInStatic(invocationSite);
+ }
+ this.aload_0();
+ return;
+ }
+ if (mappingSequence[0] instanceof FieldBinding) {
+ FieldBinding fieldBinding = (FieldBinding) mappingSequence[0];
+ if (scope.methodScope().isConstructorCall){
+ scope.problemReporter().errorThisSuperInStatic(invocationSite);
+ }
+ 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 oper1 org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param oper1 org.eclipse.jdt.internal.compiler.ast.Expression
+ * @param oper2 org.eclipse.jdt.internal.compiler.ast.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 arguments of
+ * a constructor invocation of a nested type.
+ */
+public void generateSyntheticArgumentValues(BlockScope currentScope, ReferenceBinding targetType, Expression enclosingInstance, AstNode invocationSite) {
+
+ // perform some emulation work in case there is some and we are inside a local type only
+ ReferenceBinding[] syntheticArgumentTypes;
+
+ // generate the enclosing instance first
+ if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes()) != null) {
+
+ ReferenceBinding targetEnclosingType = targetType.isAnonymousType() ?
+ targetType.superclass().enclosingType() // supplying enclosing instance for the anonymous type's superclass
+ : targetType.enclosingType();
+
+ for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) {
+ ReferenceBinding syntheticArgType = syntheticArgumentTypes[i];
+ if (enclosingInstance != null && i == 0) {
+ if (syntheticArgType != targetEnclosingType) {
+ currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, targetType);
+ }
+ //if (currentScope.environment().options.complianceLevel >= CompilerOptions.JDK1_4){
+ enclosingInstance.generateCode(currentScope, this, true);
+ if (syntheticArgType == targetEnclosingType){
+ this.dup();
+ }
+ this.invokeObjectGetClass(); // causes null check for all explicit enclosing instances
+ this.pop();
+ //} else {
+ // enclosingInstance.generateCode(currentScope, this, syntheticArgType == targetEnclosingType);
+ //}
+ } else {
+ Object[] emulationPath = currentScope.getCompatibleEmulationPath(syntheticArgType);
+ if (emulationPath == null) {
+ currentScope.problemReporter().missingEnclosingInstanceSpecification(syntheticArgType, invocationSite);
+ } else {
+ this.generateOuterAccess(emulationPath, invocationSite, currentScope);
+ }
+ }
+ }
+ } else { // we may still have an enclosing instance to consider
+ if (enclosingInstance != null) {
+ currentScope.problemReporter().unnecessaryEnclosingInstanceSpecification(enclosingInstance, targetType);
+ //if (currentScope.environment().options.complianceLevel >= CompilerOptions.JDK1_4){
+ enclosingInstance.generateCode(currentScope, this, true);
+ this.invokeObjectGetClass(); // causes null check for all explicit enclosing instances
+ this.pop();
+ //} else {
+ // enclosingInstance.generateCode(currentScope, this, false); // do not want the value
+ //}
+ }
+ }
+ // generate the synthetic outer arguments then
+ SyntheticArgumentBinding syntheticArguments[];
+ if ((syntheticArguments = targetType.syntheticOuterLocalVariables()) != null) {
+ for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+ VariableBinding[] emulationPath = currentScope.getEmulationPath(syntheticArguments[i].actualOuterLocalVariable);
+ if (emulationPath == null) {
+ // could not emulate a path to a given outer local variable (internal error)
+ currentScope.problemReporter().needImplementation();
+ } else {
+ this.generateOuterAccess(emulationPath, invocationSite, currentScope);
+ }
+ }
+ }
+}
+/**
+ * @param parameters org.eclipse.jdt.internal.compiler.lookup.TypeBinding[]
+ * @param constructorBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+ */
+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++;
+ }
+ 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++;
+ }
+ }
+ for (int i = 0; i < length; i++) {
+ load(parameters[i], resolvedPosition);
+ if ((parameters[i] == DoubleBinding) || (parameters[i] == 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
+ || (methodBinding.declaringClass != methodDeclaration.binding.declaringClass)){
+ 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) {
+ countLabels = 0;
+ if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long)) {
+ if (++stackDepth > stackMax)
+ stackMax = stackDepth;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_getfield;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_getfield);
+ }
+ writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+}
+final public void getstatic(FieldBinding fieldBinding) {
+ countLabels = 0;
+ if ((fieldBinding.type.id == T_double) || (fieldBinding.type.id == T_long))
+ stackDepth += 2;
+ else
+ stackDepth += 1;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_getstatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_getstatic);
+ }
+ writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+}
+public void getSystemOut() {
+ countLabels = 0;
+ if (++stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_getstatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_getstatic);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangSystemOut());
+}
+public void getTYPE(int baseTypeID) {
+ countLabels = 0;
+ if (++stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_getstatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_getstatic);
+ }
+ switch (baseTypeID) {
+ // getstatic: java.lang.Byte.TYPE
+ case T_byte :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangByteTYPE());
+ break;
+ // getstatic: java.lang.Short.TYPE
+ case T_short :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangShortTYPE());
+ break;
+ // getstatic: java.lang.Character.TYPE
+ case T_char :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangCharacterTYPE());
+ break;
+ // getstatic: java.lang.Integer.TYPE
+ case T_int :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangIntegerTYPE());
+ break;
+ // getstatic: java.lang.Long.TYPE
+ case T_long :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangLongTYPE());
+ break;
+ // getstatic: java.lang.Float.TYPE
+ case T_float :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangFloatTYPE());
+ break;
+ // getstatic: java.lang.Double.TYPE
+ case T_double :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangDoubleTYPE());
+ break;
+ // getstatic: java.lang.Boolean.TYPE
+ case T_boolean :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangBooleanTYPE());
+ break;
+ // getstatic: java.lang.Void.TYPE
+ case T_void :
+ writeUnsignedShort(constantPool.literalIndexForJavaLangVoidTYPE());
+ break;
+ }
+}
+/**
+ * We didn't call it goto, because there is a conflit with the goto keyword
+ */
+final public void goto_(Label lbl) {
+ if (this.wideMode) {
+ this.goto_w(lbl);
+ return;
+ }
+ try {
+ lbl.inlineForwardReferencesFromLabelsTargeting(position);
+ /*
+ Possible optimization for code such as:
+ public Object foo() {
+ boolean b = true;
+ if (b) {
+ if (b)
+ return null;
+ } else {
+ if (b) {
+ return null;
+ }
+ }
+ return null;
+ }
+ The goto around the else block for the first if will
+ be unreachable, because the thenClause of the second if
+ returns.
+ See inlineForwardReferencesFromLabelsTargeting defined
+ on the Label class for the remaining part of this
+ optimization.
+ if (!lbl.isBranchTarget(position)) {
+ switch(bCodeStream[classFileOffset-1]) {
+ case OPC_return :
+ case OPC_areturn:
+ return;
+ }
+ }*/
+ position++;
+ bCodeStream[classFileOffset++] = OPC_goto;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_goto);
+ }
+ lbl.branch();
+}
+
+/**
+ * We didn't call it goto, because there is a conflit with the goto keyword
+ */
+final public void internal_goto_(Label lbl) {
+ try {
+ lbl.inlineForwardReferencesFromLabelsTargeting(position);
+ /*
+ Possible optimization for code such as:
+ public Object foo() {
+ boolean b = true;
+ if (b) {
+ if (b)
+ return null;
+ } else {
+ if (b) {
+ return null;
+ }
+ }
+ return null;
+ }
+ The goto around the else block for the first if will
+ be unreachable, because the thenClause of the second if
+ returns.
+ See inlineForwardReferencesFromLabelsTargeting defined
+ on the Label class for the remaining part of this
+ optimization.
+ if (!lbl.isBranchTarget(position)) {
+ switch(bCodeStream[classFileOffset-1]) {
+ case OPC_return :
+ case OPC_areturn:
+ return;
+ }
+ }*/
+ position++;
+ bCodeStream[classFileOffset++] = OPC_goto;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_goto);
+ }
+ lbl.branch();
+}
+final public void goto_w(Label lbl) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_goto_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_goto_w);
+ }
+ lbl.branchWide();
+}
+final public void i2b() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_i2b;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_i2b);
+ }
+}
+final public void i2c() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_i2c;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_i2c);
+ }
+}
+final public void i2d() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_i2d;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_i2d);
+ }
+}
+final public void i2f() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_i2f;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_i2f);
+ }
+}
+final public void i2l() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_i2l;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_i2l);
+ }
+}
+final public void i2s() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_i2s;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_i2s);
+ }
+}
+final public void iadd() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iadd;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iadd);
+ }
+}
+final public void iaload() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iaload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iaload);
+ }
+}
+final public void iand() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iand;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iand);
+ }
+}
+final public void iastore() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iastore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iastore);
+ }
+}
+final public void iconst_0() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iconst_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iconst_0);
+ }
+}
+final public void iconst_1() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iconst_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iconst_1);
+ }
+}
+final public void iconst_2() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iconst_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iconst_2);
+ }
+}
+final public void iconst_3() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iconst_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iconst_3);
+ }
+}
+final public void iconst_4() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iconst_4;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iconst_4);
+ }
+}
+final public void iconst_5() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iconst_5;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iconst_5);
+ }
+}
+final public void iconst_m1() {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iconst_m1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iconst_m1);
+ }
+}
+final public void idiv() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_idiv;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_idiv);
+ }
+}
+final public void if_acmpeq(Label lbl) {
+ countLabels = 0;
+ stackDepth-=2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_acmpeq, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_acmpeq;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_acmpeq);
+ }
+ lbl.branch();
+ }
+}
+final public void if_acmpne(Label lbl) {
+ countLabels = 0;
+ stackDepth-=2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_acmpne, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_acmpne;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_acmpne);
+ }
+ lbl.branch();
+ }
+}
+final public void if_icmpeq(Label lbl) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_icmpeq, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_icmpeq;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_icmpeq);
+ }
+ lbl.branch();
+ }
+}
+final public void if_icmpge(Label lbl) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_icmpge, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_icmpge;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_icmpge);
+ }
+ lbl.branch();
+ }
+}
+final public void if_icmpgt(Label lbl) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_icmpgt, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_icmpgt;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_icmpgt);
+ }
+ lbl.branch();
+ }
+}
+final public void if_icmple(Label lbl) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_icmple, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_icmple;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_icmple);
+ }
+ lbl.branch();
+ }
+}
+final public void if_icmplt(Label lbl) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_icmplt, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_icmplt;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_icmplt);
+ }
+ lbl.branch();
+ }
+}
+final public void if_icmpne(Label lbl) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_if_icmpne, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_if_icmpne;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_if_icmpne);
+ }
+ lbl.branch();
+ }
+}
+final public void ifeq(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_ifeq, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ifeq;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ifeq);
+ }
+ lbl.branch();
+ }
+}
+final public void ifge(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_ifge, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ifge;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ifge);
+ }
+ lbl.branch();
+ }
+}
+final public void ifgt(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_ifgt, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ifgt;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ifgt);
+ }
+ lbl.branch();
+ }
+}
+final public void ifle(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_ifle, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ifle;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ifle);
+ }
+ lbl.branch();
+ }
+}
+final public void iflt(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_iflt, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iflt;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iflt);
+ }
+ lbl.branch();
+ }
+}
+final public void ifne(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_ifne, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ifne;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ifne);
+ }
+ lbl.branch();
+ }
+}
+final public void ifnonnull(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_ifnonnull, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ifnonnull;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ifnonnull);
+ }
+ lbl.branch();
+ }
+}
+final public void ifnull(Label lbl) {
+ countLabels = 0;
+ stackDepth--;
+ if (this.wideMode) {
+ generateWideConditionalBranch(OPC_ifnull, lbl);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ifnull;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ifnull);
+ }
+ lbl.branch();
+ }
+}
+final public void iinc(int index, int value) {
+ countLabels = 0;
+ if ((index > 255) || (value < -128 || value > 127)) { // have to widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iinc;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iinc);
+ }
+ writeUnsignedShort(index);
+ writeSignedShort(value);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iinc;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iinc);
+ }
+ writeUnsignedByte(index);
+ writeSignedByte(value);
+ }
+}
+final public void iload(int iArg) {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= iArg) {
+ maxLocals = iArg + 1;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iload);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iload);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void iload_0() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= 0) {
+ maxLocals = 1;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iload_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iload_0);
+ }
+}
+final public void iload_1() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= 1) {
+ maxLocals = 2;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iload_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iload_1);
+ }
+}
+final public void iload_2() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= 2) {
+ maxLocals = 3;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iload_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iload_2);
+ }
+}
+final public void iload_3() {
+ countLabels = 0;
+ stackDepth++;
+ if (maxLocals <= 3) {
+ maxLocals = 4;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iload_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iload_3);
+ }
+}
+final public void imul() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_imul;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ineg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ineg);
+ }
+}
+public void init(ClassFile classFile) {
+ this.classFile = classFile;
+ this.constantPool = classFile.constantPool;
+ this.bCodeStream = classFile.contents;
+ this.classFileOffset = classFile.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 methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+ */
+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 int 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) {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_instanceof;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_instanceof);
+ }
+ writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+public void invokeClassForName() {
+ // invokestatic: java.lang.Class.forName(Ljava.lang.String;)Ljava.lang.Class;
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokestatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokestatic);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangClassForName());
+}
+
+public void invokeJavaLangClassDesiredAssertionStatus() {
+ // invokevirtual: java.lang.Class.desiredAssertionStatus()Z;
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokevirtual);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangClassDesiredAssertionStatus());
+}
+
+public void invokeConstructorGetConstructor() {
+ // invokevirtual: java.lang.Class.getConstructor(java.lang.Class[])Ljava.lang.reflect.Constructor;
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokevirtual);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangClassGetConstructor());
+}
+final public void invokeinterface(MethodBinding methodBinding) {
+ // initialized to 1 to take into account this immediately
+ countLabels = 0;
+ int argCount = 1;
+ int id;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokeinterface;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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;
+ writeUnsignedByte(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.
+ position++;
+ classFileOffset++;
+ 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
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokespecial;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokespecial);
+ }
+ stackDepth -= 2;
+ writeUnsignedShort(constantPool.literalIndexForJavaLangErrorConstructor());
+}
+public void invokeNoClassDefFoundErrorStringConstructor() {
+ // invokespecial: java.lang.NoClassDefFoundError.<init>(Ljava.lang.String;)V
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokespecial;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokespecial);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundErrorStringConstructor());
+ stackDepth -= 2;
+}
+public void invokeObjectNewInstance() {
+ // invokevirtual: java.lang.reflect.Constructor.newInstance(java.lang.Object[])Ljava.lang.Object;
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokevirtual);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangReflectConstructorNewInstance());
+}
+
+public void invokeObjectGetClass() {
+ // invokevirtual: java.lang.Object.getClass()Ljava.lang.Class;
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokevirtual);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangObjectGetClass());
+}
+
+final public void invokespecial(MethodBinding methodBinding) {
+ // initialized to 1 to take into account this immediately
+ countLabels = 0;
+ int argCount = 1;
+ int id;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokespecial;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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) {
+ // initialized to 0 to take into account that there is no this for
+ // a static method
+ countLabels = 0;
+ int argCount = 0;
+ int id;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokestatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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) {
+ countLabels = 0;
+ int usedTypeID;
+ if (typeID == T_null)
+ usedTypeID = T_String;
+ else
+ usedTypeID = typeID;
+ // invokevirtual
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokespecial;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokespecial);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorConstructor(typeBindingID));
+ stackDepth -= 2;
+}
+
+public void invokeJavaLangAssertionErrorDefaultConstructor() {
+ // invokespecial: java.lang.AssertionError.<init>()V
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokespecial;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokespecial);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionErrorDefaultConstructor());
+ stackDepth --;
+}
+
+public void invokeStringBufferDefaultConstructor() {
+ // invokespecial: java.lang.StringBuffer.<init>()V
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokespecial;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokespecial);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferDefaultConstructor());
+ stackDepth--;
+}
+public void invokeStringBufferStringConstructor() {
+ // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokespecial;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokespecial);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferConstructor());
+ stackDepth -= 2;
+}
+
+public void invokeStringBufferToString() {
+ // invokevirtual: StringBuffer.toString()Ljava.lang.String;
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokevirtual);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangStringBufferToString());
+}
+public void invokeStringIntern() {
+ // invokevirtual: java.lang.String.intern()
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokevirtual);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangStringIntern());
+}
+public void invokeStringValueOf(int typeID) {
+ // invokestatic: java.lang.String.valueOf(argumentType)
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokestatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokestatic);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangStringValueOf(typeID));
+}
+public void invokeSystemExit() {
+ // invokestatic: java.lang.System.exit(I)
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokestatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokestatic);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangSystemExitInt());
+ stackDepth--; // int argument
+}
+public void invokeThrowableGetMessage() {
+ // invokevirtual: java.lang.Throwable.getMessage()Ljava.lang.String;
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_invokevirtual);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangThrowableGetMessage());
+}
+final public void invokevirtual(MethodBinding methodBinding) {
+ // initialized to 1 to take into account this immediately
+ countLabels = 0;
+ int argCount = 1;
+ int id;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_invokevirtual;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ior;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ior);
+ }
+}
+final public void irem() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_irem;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_irem);
+ }
+}
+final public void ireturn() {
+ countLabels = 0;
+ stackDepth--;
+ // the stackDepth should be equal to 0
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ireturn;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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 position = local.id + maxFieldCount;
+ MethodScope methodScope = scope.methodScope();
+ // id is zero-based
+ if (position < UnconditionalFlowInfo.BitCacheSize) {
+ return (methodScope.definiteInits[initStateIndex] & (1L << position)) != 0; // use bits
+ }
+ // use extra vector
+ long[] extraInits = methodScope.extraDefiniteInits[initStateIndex];
+ if (extraInits == null)
+ return false; // if vector not yet allocated, then not initialized
+ int vectorIndex;
+ if ((vectorIndex = (position / UnconditionalFlowInfo.BitCacheSize) - 1) >= extraInits.length)
+ return false; // if not enough room in vector, then not initialized
+ return ((extraInits[vectorIndex]) & (1L << (position % UnconditionalFlowInfo.BitCacheSize))) != 0;
+}
+final public void ishl() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ishl;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ishl);
+ }
+}
+final public void ishr() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ishr;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ishr);
+ }
+}
+final public void istore(int iArg) {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= iArg) {
+ maxLocals = iArg + 1;
+ }
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_istore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_istore);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_istore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_istore);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void istore_0() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals == 0) {
+ maxLocals = 1;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_istore_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_istore_0);
+ }
+}
+final public void istore_1() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 1) {
+ maxLocals = 2;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_istore_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_istore_1);
+ }
+}
+final public void istore_2() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 2) {
+ maxLocals = 3;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_istore_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_istore_2);
+ }
+}
+final public void istore_3() {
+ countLabels = 0;
+ stackDepth--;
+ if (maxLocals <= 3) {
+ maxLocals = 4;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_istore_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_istore_3);
+ }
+}
+final public void isub() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_isub;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_isub);
+ }
+}
+final public void iushr() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_iushr;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_iushr);
+ }
+}
+final public void ixor() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ixor;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ixor);
+ }
+}
+final public void jsr(Label lbl) {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_jsr;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_jsr);
+ }
+ lbl.branch();
+}
+final public void jsr_w(Label lbl) {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_jsr_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_jsr_w);
+ }
+ lbl.branchWide();
+}
+final public void l2d() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_l2d;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_l2d);
+ }
+}
+final public void l2f() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_l2f;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_l2f);
+ }
+}
+final public void l2i() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_l2i;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_l2i);
+ }
+}
+final public void ladd() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ladd;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ladd);
+ }
+}
+final public void laload() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_laload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_laload);
+ }
+}
+final public void land() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_land;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_land);
+ }
+}
+final public void lastore() {
+ countLabels = 0;
+ stackDepth -= 4;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lastore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lastore);
+ }
+}
+final public void lcmp() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lcmp;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lcmp);
+ }
+}
+final public void lconst_0() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lconst_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lconst_0);
+ }
+}
+final public void lconst_1() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lconst_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lconst_1);
+ }
+}
+final public void ldc(float constant) {
+ countLabels = 0;
+ int index = constantPool.literalIndex(constant);
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (index > 255) {
+ // Generate a ldc_w
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc_w);
+ }
+ writeUnsignedShort(index);
+ } else {
+ // Generate a ldc
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc);
+ }
+ writeUnsignedByte(index);
+ }
+}
+final public void ldc(int constant) {
+ countLabels = 0;
+ int index = constantPool.literalIndex(constant);
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (index > 255) {
+ // Generate a ldc_w
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc_w);
+ }
+ writeUnsignedShort(index);
+ } else {
+ // Generate a ldc
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc);
+ }
+ writeUnsignedByte(index);
+ }
+}
+final public void ldc(String constant) {
+ 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
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc_w);
+ }
+ writeUnsignedShort(index);
+ } else {
+ // Generate a ldc
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc);
+ }
+ writeUnsignedByte(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
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc_w);
+ }
+ writeUnsignedShort(index);
+ } else {
+ // Generate a ldc
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc);
+ }
+ writeUnsignedByte(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
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc_w);
+ }
+ writeUnsignedShort(index);
+ } else {
+ // Generate a ldc
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc);
+ }
+ writeUnsignedByte(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) {
+ countLabels = 0;
+ int index = constantPool.literalIndex(constant);
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ // Generate a ldc2_w
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc2_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc2_w);
+ }
+ writeUnsignedShort(index);
+}
+final public void ldc2_w(long constant) {
+ countLabels = 0;
+ int index = constantPool.literalIndex(constant);
+ stackDepth += 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ // Generate a ldc2_w
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldc2_w;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldc2_w);
+ }
+ writeUnsignedShort(index);
+}
+final public void ldiv() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ldiv;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ldiv);
+ }
+}
+final public void lload(int iArg) {
+ countLabels = 0;
+ stackDepth += 2;
+ if (maxLocals <= iArg + 1) {
+ maxLocals = iArg + 2;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lload);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lload);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void lload_0() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (maxLocals < 2) {
+ maxLocals = 2;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lload_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lload_0);
+ }
+}
+final public void lload_1() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (maxLocals < 3) {
+ maxLocals = 3;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lload_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lload_1);
+ }
+}
+final public void lload_2() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (maxLocals < 4) {
+ maxLocals = 4;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lload_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lload_2);
+ }
+}
+final public void lload_3() {
+ countLabels = 0;
+ stackDepth += 2;
+ if (maxLocals < 5) {
+ maxLocals = 5;
+ }
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lload_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lload_3);
+ }
+}
+final public void lmul() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lmul;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lmul);
+ }
+}
+final public void lneg() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lneg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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;
+ 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) {
+ countLabels = 0;
+ stackDepth--;
+ int length = keys.length;
+ int pos = position;
+ defaultLabel.placeInstruction();
+ for (int i = 0; i < length; i++) {
+ casesLabel[i].placeInstruction();
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lookupswitch;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lookupswitch);
+ }
+ for (int i = (3 - (pos % 4)); i > 0; i--) {
+ position++; // Padding
+ classFileOffset++;
+ }
+ defaultLabel.branch();
+ writeSignedWord(length);
+ for (int i = 0; i < length; i++) {
+ writeSignedWord(keys[sortedIndexes[i]]);
+ casesLabel[sortedIndexes[i]].branch();
+ }
+}
+final public void lor() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lor;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lor);
+ }
+}
+final public void lrem() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lrem;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lrem);
+ }
+}
+final public void lreturn() {
+ countLabels = 0;
+ stackDepth -= 2;
+ // the stackDepth should be equal to 0
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lreturn;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lreturn);
+ }
+}
+final public void lshl() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lshl;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lshl);
+ }
+}
+final public void lshr() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lshr;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lshr);
+ }
+}
+final public void lstore(int iArg) {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals <= iArg + 1) {
+ maxLocals = iArg + 2;
+ }
+ if (iArg > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lstore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lstore);
+ }
+ writeUnsignedShort(iArg);
+ } else {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lstore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lstore);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) iArg;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) iArg);
+ }
+ }
+}
+final public void lstore_0() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 2) {
+ maxLocals = 2;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lstore_0;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lstore_0);
+ }
+}
+final public void lstore_1() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 3) {
+ maxLocals = 3;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lstore_1;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lstore_1);
+ }
+}
+final public void lstore_2() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 4) {
+ maxLocals = 4;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lstore_2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lstore_2);
+ }
+}
+final public void lstore_3() {
+ countLabels = 0;
+ stackDepth -= 2;
+ if (maxLocals < 5) {
+ maxLocals = 5;
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lstore_3;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lstore_3);
+ }
+}
+final public void lsub() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lsub;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lsub);
+ }
+}
+final public void lushr() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lushr;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lushr);
+ }
+}
+final public void lxor() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_lxor;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_lxor);
+ }
+}
+final public void monitorenter() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_monitorenter;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_monitorenter);
+ }
+}
+final public void monitorexit() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_monitorexit;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_monitorexit);
+ }
+}
+final public void multianewarray(TypeBinding typeBinding, int dimensions) {
+ countLabels = 0;
+ stackDepth += (1 - dimensions);
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_multianewarray;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_multianewarray);
+ }
+ writeUnsignedShort(constantPool.literalIndex(typeBinding));
+ writeUnsignedByte(dimensions);
+}
+public static void needImplementation() {
+}
+/**
+ * We didn't call it new, because there is a conflit with the new keyword
+ */
+final public void new_(TypeBinding typeBinding) {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_new;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_new);
+ }
+ writeUnsignedShort(constantPool.literalIndex(typeBinding));
+}
+final public void newarray(int array_Type) {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_newarray;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_newarray);
+ }
+ writeUnsignedByte(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
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_new;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_new);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangError());
+}
+
+public void newJavaLangAssertionError() {
+ // new: java.lang.AssertionError
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_new;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_new);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangAssertionError());
+}
+
+public void newNoClassDefFoundError() { // new: java.lang.NoClassDefFoundError
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_new;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_new);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangNoClassDefFoundError());
+}
+public void newStringBuffer() { // new: java.lang.StringBuffer
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_new;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_new);
+ }
+ writeUnsignedShort(constantPool.literalIndexForJavaLangStringBuffer());
+}
+public void newWrapperFor(int typeID) {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_new;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_new);
+ }
+ switch (typeID) {
+ case T_int : // new: java.lang.Integer
+ writeUnsignedShort(constantPool.literalIndexForJavaLangInteger());
+ break;
+ case T_boolean : // new: java.lang.Boolean
+ writeUnsignedShort(constantPool.literalIndexForJavaLangBoolean());
+ break;
+ case T_byte : // new: java.lang.Byte
+ writeUnsignedShort(constantPool.literalIndexForJavaLangByte());
+ break;
+ case T_char : // new: java.lang.Character
+ writeUnsignedShort(constantPool.literalIndexForJavaLangCharacter());
+ break;
+ case T_float : // new: java.lang.Float
+ writeUnsignedShort(constantPool.literalIndexForJavaLangFloat());
+ break;
+ case T_double : // new: java.lang.Double
+ writeUnsignedShort(constantPool.literalIndexForJavaLangDouble());
+ break;
+ case T_short : // new: java.lang.Short
+ writeUnsignedShort(constantPool.literalIndexForJavaLangShort());
+ break;
+ case T_long : // new: java.lang.Long
+ writeUnsignedShort(constantPool.literalIndexForJavaLangLong());
+ break;
+ case T_void : // new: java.lang.Void
+ writeUnsignedShort(constantPool.literalIndexForJavaLangVoid());
+ }
+}
+final public void nop() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_nop;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_nop);
+ }
+}
+final public void pop() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_pop;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_pop);
+ }
+}
+final public void pop2() {
+ countLabels = 0;
+ stackDepth -= 2;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_pop2;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_pop2);
+ }
+}
+final public void putfield(FieldBinding fieldBinding) {
+ countLabels = 0;
+ int id;
+ if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
+ stackDepth -= 3;
+ else
+ stackDepth -= 2;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_putfield;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_putfield);
+ }
+ writeUnsignedShort(constantPool.literalIndex(fieldBinding));
+}
+final public void putstatic(FieldBinding fieldBinding) {
+ countLabels = 0;
+ int id;
+ if (((id = fieldBinding.type.id) == T_double) || (id == T_long))
+ stackDepth -= 2;
+ else
+ stackDepth -= 1;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_putstatic;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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
+ 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 methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+ */
+public void reset(AbstractMethodDeclaration methodDeclaration, ClassFile classFile) {
+ init(classFile);
+ this.methodDeclaration = methodDeclaration;
+ preserveUnusedLocals = methodDeclaration.scope.problemReporter().options.preserveAllLocalVariables;
+ initializeMaxLocals(methodDeclaration.binding);
+}
+/**
+ * @param methodDeclaration org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+ * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
+ */
+public void resetForProblemClinit(ClassFile classFile) {
+ init(classFile);
+ maxLocals = 0;
+}
+protected final void resizeByteArray() {
+ int actualLength = bCodeStream.length;
+ int requiredSize = actualLength + growFactor;
+ if (classFileOffset > requiredSize) {
+ requiredSize = classFileOffset + growFactor;
+ }
+ System.arraycopy(bCodeStream, 0, (bCodeStream = new byte[requiredSize]), 0, actualLength);
+}
+/**
+ * This method is used to resize the internal byte array in
+ * case of a ArrayOutOfBoundsException when adding the value b.
+ * Resize and add the new byte b inside the array.
+ * @param b byte
+ */
+protected final void resizeByteArray(byte b) {
+ resizeByteArray();
+ bCodeStream[classFileOffset - 1] = b;
+}
+final public void ret(int index) {
+ countLabels = 0;
+ if (index > 255) { // Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ret;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ret);
+ }
+ writeUnsignedShort(index);
+ } else { // Don't Widen
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_ret;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_ret);
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) index;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) index);
+ }
+ }
+}
+final public void return_() {
+ countLabels = 0;
+ // the stackDepth should be equal to 0
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_return;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_return);
+ }
+}
+final public void saload() {
+ countLabels = 0;
+ stackDepth--;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_saload;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_saload);
+ }
+}
+final public void sastore() {
+ countLabels = 0;
+ stackDepth -= 3;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_sastore;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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) {
+ countLabels = 0;
+ stackDepth++;
+ if (stackDepth > stackMax)
+ stackMax = stackDepth;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_sipush;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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) {
+ TypeBinding type = localBinding.type;
+ int position = localBinding.resolvedPosition;
+ // Using dedicated int bytecode
+ if ((type == IntBinding) || (type == CharBinding) || (type == ByteBinding) || (type == ShortBinding) || (type == BooleanBinding)) {
+ if (valueRequired)
+ this.dup();
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Using dedicated float bytecode
+ if (type == FloatBinding) {
+ if (valueRequired)
+ this.dup();
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Using dedicated long bytecode
+ if (type == LongBinding) {
+ if (valueRequired)
+ this.dup2();
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Using dedicated double bytecode
+ if (type == DoubleBinding) {
+ if (valueRequired)
+ this.dup2();
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Reference object
+ if (valueRequired)
+ this.dup();
+ switch (position) {
+ 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(position);
+ }
+}
+public final void store(TypeBinding type, int position) {
+ // Using dedicated int bytecode
+ if ((type == IntBinding) || (type == CharBinding) || (type == ByteBinding) || (type == ShortBinding) || (type == BooleanBinding)) {
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Using dedicated float bytecode
+ if (type == FloatBinding) {
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Using dedicated long bytecode
+ if (type == LongBinding) {
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Using dedicated double bytecode
+ if (type == DoubleBinding) {
+ switch (position) {
+ 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(position);
+ }
+ return;
+ }
+ // Reference object
+ switch (position) {
+ 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(position);
+ }
+}
+public final void storeInt(int position) {
+ switch (position) {
+ 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(position);
+ }
+}
+public final void storeObject(int position) {
+ switch (position) {
+ 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(position);
+ }
+}
+final public void swap() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_swap;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(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) {
+ countLabels = 0;
+ stackDepth--;
+ int length = casesLabel.length;
+ int pos = position;
+ defaultLabel.placeInstruction();
+ for (int i = 0; i < length; i++)
+ casesLabel[i].placeInstruction();
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_tableswitch;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_tableswitch);
+ }
+ for (int i = (3 - (pos % 4)); i > 0; i--) {
+ position++; // Padding
+ classFileOffset++;
+ }
+ 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;
+ // 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;
+ }
+ }
+ }
+ }
+}
+final public void wide() {
+ countLabels = 0;
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = OPC_wide;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(OPC_wide);
+ }
+}
+public final void writeByte(byte b) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = b;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(b);
+ }
+}
+public final void writeByteAtPos(int pos, byte b) {
+ try {
+ bCodeStream[pos] = b;
+ } catch (IndexOutOfBoundsException ex) {
+ resizeByteArray();
+ bCodeStream[pos] = b;
+ }
+}
+/**
+ * Write a unsigned 8 bits value into the byte array
+ * @param b the signed byte
+ */
+public final void writeSignedByte(int b) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) b;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) b);
+ }
+}
+/**
+ * Write a signed 16 bits value into the byte array
+ * @param b the signed short
+ */
+public final void writeSignedShort(int b) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) (b >> 8);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) (b >> 8));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) b;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) b);
+ }
+}
+public final void writeSignedShort(int pos, int b) {
+ int currentOffset = startingClassFileOffset + pos;
+ try {
+ bCodeStream[currentOffset] = (byte) (b >> 8);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray();
+ bCodeStream[currentOffset] = (byte) (b >> 8);
+ }
+ try {
+ bCodeStream[currentOffset + 1] = (byte) b;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray();
+ bCodeStream[currentOffset + 1] = (byte) b;
+ }
+}
+public final void writeSignedWord(int value) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) ((value & 0xFF000000) >> 24);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) ((value & 0xFF000000) >> 24));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) ((value & 0xFF0000) >> 16);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) ((value & 0xFF0000) >> 16));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) ((value & 0xFF00) >> 8);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) ((value & 0xFF00) >> 8));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) (value & 0xFF);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) (value & 0xFF));
+ }
+}
+public final void writeSignedWord(int pos, int value) {
+ int currentOffset = startingClassFileOffset + pos;
+ try {
+ bCodeStream[currentOffset++] = (byte) ((value & 0xFF000000) >> 24);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray();
+ bCodeStream[currentOffset-1] = (byte) ((value & 0xFF000000) >> 24);
+ }
+ try {
+ bCodeStream[currentOffset++] = (byte) ((value & 0xFF0000) >> 16);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray();
+ bCodeStream[currentOffset-1] = (byte) ((value & 0xFF0000) >> 16);
+ }
+ try {
+ bCodeStream[currentOffset++] = (byte) ((value & 0xFF00) >> 8);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray();
+ bCodeStream[currentOffset-1] = (byte) ((value & 0xFF00) >> 8);
+ }
+ try {
+ bCodeStream[currentOffset++] = (byte) (value & 0xFF);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray();
+ bCodeStream[currentOffset-1] = (byte) (value & 0xFF);
+ }
+}
+/**
+ * Write a unsigned 8 bits value into the byte array
+ * @param b the unsigned byte
+ */
+public final void writeUnsignedByte(int b) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) b;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) b);
+ }
+}
+/**
+ * Write a unsigned 16 bits value into the byte array
+ * @param b the unsigned short
+ */
+public final void writeUnsignedShort(int b) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) (b >>> 8);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) (b >>> 8));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) b;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) b);
+ }
+}
+/**
+ * Write a unsigned 32 bits value into the byte array
+ * @param value the unsigned word
+ */
+public final void writeUnsignedWord(int value) {
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) (value >>> 24);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) (value >>> 24));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) (value >>> 16);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) (value >>> 16));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) (value >>> 8);
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) (value >>> 8));
+ }
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = (byte) value;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray((byte) value);
+ }
+}
+
+public void generateWideConditionalBranch(byte opcode, Label lbl) {
+ /* we handle the goto_w problem inside an if.... with some macro expansion
+ * at the bytecode level
+ * instead of:
+ * if_...... lbl
+ * we have:
+ * ifne <l1>
+ * goto <l2>
+ * l1 gotow <l3> // l3 is a wide target
+ * l2 ....
+ */
+ Label l1 = new Label(this);
+ try {
+ position++;
+ bCodeStream[classFileOffset++] = opcode;
+ } catch (IndexOutOfBoundsException e) {
+ resizeByteArray(opcode);
+ }
+ l1.branch();
+ Label l2 = new Label(this);
+ this.internal_goto_(l2);
+ l1.place();
+ this.goto_w(lbl);
+ l2.place();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.ClassFile;
+
+import net.sourceforge.phpdt.internal.compiler.classfmt.ClassFileConstants;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+/**
+ * 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 GETCONSTRUCTOR_CLASS_METHOD = 16;
+ final static int NEWINSTANCE_CONSTRUCTOR_METHOD = 17;
+ final static int STRING_INTERN_METHOD = 18;
+ final static int VALUEOF_INT_METHOD = 19;
+ final static int VALUEOF_FLOAT_METHOD = 20;
+ final static int VALUEOF_LONG_METHOD = 21;
+ final static int VALUEOF_OBJECT_METHOD = 22;
+ final static int VALUEOF_CHAR_METHOD = 23;
+ final static int VALUEOF_BOOLEAN_METHOD = 24;
+ final static int VALUEOF_DOUBLE_METHOD = 25;
+ final static int ASSERTIONERROR_CONSTR_OBJECT_METHOD = 26;
+ final static int ASSERTIONERROR_CONSTR_INT_METHOD = 27;
+ final static int ASSERTIONERROR_CONSTR_LONG_METHOD = 28;
+ final static int ASSERTIONERROR_CONSTR_FLOAT_METHOD = 29;
+ final static int ASSERTIONERROR_CONSTR_DOUBLE_METHOD = 30;
+ final static int ASSERTIONERROR_CONSTR_BOOLEAN_METHOD = 31;
+ final static int ASSERTIONERROR_CONSTR_CHAR_METHOD = 32;
+ final static int ASSERTIONERROR_DEFAULT_CONSTR_METHOD = 33;
+ final static int DESIREDASSERTIONSTATUS_CLASS_METHOD = 34;
+ final static int GETCLASS_OBJECT_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 GETCONSTRUCTOR_METHOD_NAME_AND_TYPE = 14;
+ final static int NEWINSTANCE_METHOD_NAME_AND_TYPE = 15;
+ final static int INTERN_METHOD_NAME_AND_TYPE = 16;
+ final static int VALUEOF_INT_METHOD_NAME_AND_TYPE = 17;
+ final static int VALUEOF_FLOAT_METHOD_NAME_AND_TYPE = 18;
+ final static int VALUEOF_LONG_METHOD_NAME_AND_TYPE = 19;
+ final static int VALUEOF_OBJECT_METHOD_NAME_AND_TYPE = 20;
+ final static int VALUEOF_CHAR_METHOD_NAME_AND_TYPE = 21;
+ final static int VALUEOF_BOOLEAN_METHOD_NAME_AND_TYPE = 22;
+ final static int VALUEOF_DOUBLE_METHOD_NAME_AND_TYPE = 23;
+ final static int CONSTR_INT_METHOD_NAME_AND_TYPE = 24;
+ final static int CONSTR_LONG_METHOD_NAME_AND_TYPE = 25;
+ final static int CONSTR_FLOAT_METHOD_NAME_AND_TYPE = 26;
+ final static int CONSTR_DOUBLE_METHOD_NAME_AND_TYPE = 27;
+ final static int CONSTR_OBJECT_METHOD_NAME_AND_TYPE = 28;
+ final static int CONSTR_CHAR_METHOD_NAME_AND_TYPE = 29;
+ final static int CONSTR_BOOLEAN_METHOD_NAME_AND_TYPE = 30;
+ final static int DESIREDASSERTIONSTATUS_METHOD_NAME_AND_TYPE = 31;
+ final static int GETCLASS_OBJECT_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;
+ }
+ 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 == 'g') && (methodBinding.parameters.length == 1) && (methodBinding.returnType.id == T_JavaLangReflectConstructor) && CharOperation.equals(methodBinding.selector, QualifiedNamesConstants.GetConstructor) && CharOperation.equals(methodBinding.parameters[0].constantPoolName(), QualifiedNamesConstants.ArrayJavaLangClassConstantPoolName)) {
+ return GETCONSTRUCTOR_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;
+ }
+ 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;
+ if (currentOffset + 2 >= poolContent.length) {
+ // we need to resize the poolContent array because we won't have
+ // enough space to write the length
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length + CONSTANTPOOL_GROW_SIZE]), 0, length);
+ }
+ currentOffset += 2;
+ // add in once the whole byte array
+ int length = poolContent.length;
+ int utf8encodingLength = utf8encoding.length;
+ if (currentOffset + utf8encodingLength >= length) {
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length + utf8encodingLength + CONSTANTPOOL_GROW_SIZE]), 0, length);
+ }
+ 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 char[] stringName
+ * @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
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length + CONSTANTPOOL_GROW_SIZE]), 0, length);
+ }
+ 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;
+ return -1;
+ }
+ 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 <CODE>double</CODE> key
+ * @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);
+ for (int i = 0; i < 8; i++) {
+ try {
+ poolContent[currentOffset++] = (byte) (temp >>> (56 - (i << 3)));
+ } catch (IndexOutOfBoundsException e) { //currentOffset has been ++ already (see the -1)
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[(length << 1) + CONSTANTPOOL_INITIAL_SIZE]), 0, length);
+ poolContent[currentOffset - 1] = (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 <CODE>float</CODE> key
+ * @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);
+ for (int i = 0; i < 4; i++) {
+ try {
+ poolContent[currentOffset++] = (byte) (temp >>> (24 - i * 8));
+ } catch (IndexOutOfBoundsException e) { //currentOffset has been ++ already (see the -1)
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length * 2 + CONSTANTPOOL_INITIAL_SIZE]), 0, length);
+ poolContent[currentOffset - 1] = (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 <CODE>int</CODE> key
+ * @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
+ for (int i = 0; i < 4; i++) {
+ try {
+ poolContent[currentOffset++] = (byte) (key >>> (24 - i * 8));
+ } catch (IndexOutOfBoundsException e) { //currentOffset has been ++ already (see the -1)
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length * 2 + CONSTANTPOOL_INITIAL_SIZE]), 0, length);
+ poolContent[currentOffset - 1] = (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 <CODE>long</CODE> key
+ * @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
+ for (int i = 0; i < 8; i++) {
+ try {
+ poolContent[currentOffset++] = (byte) (key >>> (56 - (i << 3)));
+ } catch (IndexOutOfBoundsException e) { //currentOffset has been ++ already (see the -1)
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[(length << 1) + CONSTANTPOOL_INITIAL_SIZE]), 0, length);
+ poolContent[currentOffset - 1] = (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 FieldBinding aFieldBinding
+ * @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.
+ *
+ * @param MethodBinding aMethodBinding
+ * @return <CODE>int</CODE>
+ */
+public int literalIndex(MethodBinding aMethodBinding) {
+ int index;
+ int nameAndTypeIndex;
+ int classIndex;
+ int indexWellKnownMethod;
+ if ((indexWellKnownMethod = indexOfWellKnownMethods(aMethodBinding)) == -1) {
+ if (aMethodBinding.declaringClass.isInterface()) {
+ // Lookinf into the interface method ref table
+ if ((index = interfaceMethodCache.get(aMethodBinding)) < 0) {
+ classIndex = literalIndex(aMethodBinding.declaringClass);
+ 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.declaringClass);
+ 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.declaringClass.isInterface()) {
+ // Lookinf into the interface method ref table
+ classIndex = literalIndex(aMethodBinding.declaringClass);
+ 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.declaringClass);
+ 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 TypeBinding aTypeBinding
+ * @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 int nameIndex
+ * @param int nameIndex
+ * @param org.eclipse.jdt.internal.compiler.lookup.FieldBinding a 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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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 literalIndexForJavaLangClassGetConstructor() {
+ int index;
+ int nameAndTypeIndex;
+ int classIndex;
+ // Looking into the method ref table
+ if ((index = wellKnownMethods[GETCONSTRUCTOR_CLASS_METHOD]) == 0) {
+ classIndex = literalIndexForJavaLangClass();
+ if ((nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCONSTRUCTOR_METHOD_NAME_AND_TYPE]) == 0) {
+ int nameIndex = literalIndex(QualifiedNamesConstants.GetConstructor);
+ int typeIndex = literalIndex(QualifiedNamesConstants.GetConstructorSignature);
+ nameAndTypeIndex = wellKnownMethodNameAndTypes[GETCONSTRUCTOR_METHOD_NAME_AND_TYPE] = currentIndex++;
+ writeU1(NameAndTypeTag);
+ writeU2(nameIndex);
+ writeU2(typeIndex);
+ }
+ index = wellKnownMethods[GETCONSTRUCTOR_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 type descriptor.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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 TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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.
+ *
+ * @param TypeBinding aTypeBinding
+ * @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 char[] stringName
+ * @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
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length + CONSTANTPOOL_GROW_SIZE]), 0, length);
+ }
+ 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 int nameIndex
+ * @param int nameIndex
+ * @param org.eclipse.jdt.internal.compiler.lookup.MethodBinding a 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);
+ }
+}
+/**
+ * Write a unsigned byte into the byte array
+ *
+ * @param <CODE>int</CODE> The value to write into the byte array
+ */
+protected final void writeU1(int value) {
+ try {
+ poolContent[currentOffset++] = (byte) value;
+ } catch (IndexOutOfBoundsException e) {
+ //currentOffset has been ++ already (see the -1)
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length + CONSTANTPOOL_GROW_SIZE]), 0, length);
+ poolContent[currentOffset - 1] = (byte) value;
+ }
+}
+/**
+ * Write a unsigned byte into the byte array
+ *
+ * @param <CODE>int</CODE> The value to write into the byte array
+ */
+protected final void writeU2(int value) {
+ //first byte
+ try {
+ poolContent[currentOffset++] = (byte) (value >> 8);
+ } catch (IndexOutOfBoundsException e) {
+ //currentOffset has been ++ already (see the -1)
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length + CONSTANTPOOL_GROW_SIZE]), 0, length);
+ poolContent[currentOffset - 1] = (byte) (value >> 8);
+ }
+ try {
+ poolContent[currentOffset++] = (byte) value;
+ } catch (IndexOutOfBoundsException e) {
+ //currentOffset has been ++ already (see the -1)
+ int length = poolContent.length;
+ System.arraycopy(poolContent, 0, (poolContent = new byte[length + CONSTANTPOOL_GROW_SIZE]), 0, length);
+ poolContent[currentOffset - 1] = (byte) value;
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+public class ExceptionLabel extends Label {
+ public int start = POS_NOT_SET;
+ public int end = POS_NOT_SET;
+ public TypeBinding exceptionType;
+public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) {
+ super(codeStream);
+ this.exceptionType = exceptionType;
+ this.start = codeStream.position;
+}
+public boolean isStandardLabel(){
+ return false;
+}
+public void place() {
+ // register the handler inside the codeStream then normal place
+ codeStream.registerExceptionHandler(this);
+ super.place();
+
+}
+public void placeEnd() {
+ end = codeStream.position;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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 char[] key 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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
+import net.sourceforge.phpdt.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() {
+}
+/**
+ * @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 refernece 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!
+ codeStream.writeSignedShort((short) (position - codeStream.position + 1));
+ }
+}
+/*
+* 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 boolean isStandardLabel(){
+ return true;
+}
+/*
+* Place the label. If we have forward references resolve them.
+*/
+public void place() { // Currently lacking wide support.
+ if (position == POS_NOT_SET) {
+ position = codeStream.position;
+ codeStream.addLabel(this);
+ int oldPosition = position;
+ boolean optimizedBranch = false;
+ // TURNED OFF since fail on 1F4IRD9
+ if (forwardReferenceCount != 0) {
+ if (optimizedBranch = (forwardReferences[forwardReferenceCount - 1] + 2 == position) && (codeStream.bCodeStream[codeStream.classFileOffset - 3] == CodeStream.OPC_goto)) {
+ 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 (offset > 0x7FFF && !this.codeStream.wideMode) {
+ throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
+ }
+ if (this.codeStream.wideMode) {
+ if (this.isWide) {
+ codeStream.writeSignedWord(forwardReferences[i], offset);
+ } else {
+ codeStream.writeSignedShort(forwardReferences[i], (short) offset);
+ }
+ } else {
+ codeStream.writeSignedShort(forwardReferences[i], (short) offset);
+ }
+ }
+ // For all labels placed at that position we check if we need to rewrite the jump
+ // offset. It is the case each time a label had a forward reference to the current position.
+ // Like we change the current position, we have to change the jump offset. See 1F4IRD9 for more details.
+ if (optimizedBranch) {
+ 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 (offset > 0x7FFF && !this.codeStream.wideMode) {
+ throw new AbortMethod(CodeStream.RESTART_IN_WIDE_MODE);
+ }
+ if (this.codeStream.wideMode) {
+ if (this.isWide) {
+ codeStream.writeSignedWord(forwardPosition, offset);
+ } else {
+ codeStream.writeSignedShort(forwardPosition, (short) offset);
+ }
+ } else {
+ codeStream.writeSignedShort(forwardPosition, (short) offset);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+/**
+ * Print out the receiver
+ */
+public String toString() {
+ StringBuffer buffer = new StringBuffer("(position="); //$NON-NLS-1$
+ buffer.append(position);
+ 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();
+}
+
+public void resetStateForCodeGeneration() {
+ this.position = POS_NOT_SET;
+ this.forwardReferenceCount = 0;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.MethodBinding;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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 char[] key 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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 char[] key 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();
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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$
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.codegen;
+
+import net.sourceforge.phpdt.internal.compiler.AbstractSyntaxTreeVisitorAdapter;
+import net.sourceforge.phpdt.internal.compiler.ast.BranchStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.DoStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.ForStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.LabeledStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.SwitchStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.WhileStatement;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+
+public class ResetStateForCodeGenerationVisitor
+ extends AbstractSyntaxTreeVisitorAdapter {
+
+ public boolean visit(SwitchStatement statement, BlockScope scope) {
+ statement.resetStateForCodeGeneration();
+ return true;
+ }
+
+ public boolean visit(ForStatement forStatement, BlockScope scope) {
+ forStatement.resetStateForCodeGeneration();
+ return true;
+ }
+
+ public boolean visit(WhileStatement whileStatement, BlockScope scope) {
+ whileStatement.resetStateForCodeGeneration();
+ return true;
+ }
+
+ public boolean visit(LabeledStatement labeledStatement, BlockScope scope) {
+ labeledStatement.resetStateForCodeGeneration();
+ return true;
+ }
+
+ public boolean visit(DoStatement doStatement, BlockScope scope) {
+ doStatement.resetStateForCodeGeneration();
+ return true;
+ }
+
+ public boolean visit(BranchStatement branchStatement, BlockScope scope) {
+ branchStatement.resetStateForCodeGeneration();
+ return true;
+ }
+
+}
+
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.env;
+
+import net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.env;
+
+public interface IBinaryType extends IGenericType {
+
+ char[][] NoInterface = new char[0][];
+ 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();
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.env;
+
+/**
+ * This interface defines constants for use by the builder / compiler interface.
+ */
+public interface IConstants {
+
+ /*
+ * Modifiers
+ */
+ int AccPublic = 0x0001;
+ int AccPrivate = 0x0002;
+ int AccProtected = 0x0004;
+ int AccStatic = 0x0008;
+ int AccFinal = 0x0010;
+ int AccSynchronized = 0x0020;
+ int AccVolatile = 0x0040;
+ int AccTransient = 0x0080;
+ int AccNative = 0x0100;
+ int AccInterface = 0x0200;
+ int AccAbstract = 0x0400;
+ int AccStrictfp = 0x0800;
+
+ /*
+ * Other VM flags.
+ */
+ int AccSuper = 0x0020;
+
+ /**
+ * Extra flags for types and members.
+ */
+ int AccSynthetic = 0x20000;
+ int AccDeprecated = 0x100000;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.env;
+
+/**
+ * This represents the target (i.e. the 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. ".java")
+ *
+ * e.g. "c:/com/ibm/compiler/java/api/Compiler.java"
+ */
+
+char[] getFileName();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 & AccSynthetic.
+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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.env;
+
+public interface ISourceType extends IGenericType {
+/**
+ * Answer the source end position of the type's declaration.
+ */
+
+int getDeclarationSourceEnd();
+/**
+ * Answer the source start position of the type's declaration.
+ */
+
+int getDeclarationSourceStart();
+/**
+ * Answer the enclosing type
+ * or null if the receiver is a top level type.
+ */
+
+ISourceType getEnclosingType();
+/**
+ * Answer the receiver's fields or null if the array is empty.
+ *
+ * NOTE: Multiple fields with the same name can exist in the result.
+ */
+
+ISourceField[] getFields();
+/**
+ * Answer the unresolved names of the receiver's imports
+ * or null if the array is empty.
+ *
+ * An import is a qualified, dot separated name.
+ * For example, java.util.Hashtable or java.lang.*.
+ */
+
+char[][] 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 qualified name of the receiver.
+ *
+ * The name is a qualified, dot separated name.
+ * For example, java.util.Hashtable.
+ */
+
+char[] getQualifiedName();
+/**
+ * Answer the unresolved name of the receiver's superclass
+ * or null if it does not have one.
+ *
+ * The name is a simple name or a qualified, dot separated name.
+ * For example, Hashtable or java.util.Hashtable.
+ */
+
+char[] getSuperclassName();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 binaryType;
+ }
+
+ /**
+ * Answer the compilation unit or null if the
+ * receiver represents a binary or source type.
+ */
+ public ICompilationUnit getCompilationUnit() {
+ return 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 sourceTypes;
+ }
+
+ /**
+ * Answer whether the receiver contains the resolved binary form of the type.
+ */
+ public boolean isBinaryType() {
+ return binaryType != null;
+ }
+
+ /**
+ * Answer whether the receiver contains the compilation unit which defines the type.
+ */
+ public boolean isCompilationUnit() {
+ return compilationUnit != null;
+ }
+
+ /**
+ * Answer whether the receiver contains the unresolved source form of the type.
+ */
+ public boolean isSourceType() {
+ return sourceTypes != null;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.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 UnconditionalFlowInfo addInitializationsFrom(UnconditionalFlowInfo otherInits) {
+ return unconditionalInits().addInitializationsFrom(otherInits);
+}
+public UnconditionalFlowInfo addPotentialInitializationsFrom(UnconditionalFlowInfo otherInits) {
+ return unconditionalInits().addPotentialInitializationsFrom(otherInits);
+}
+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 boolean isFakeReachable(){
+ return unconditionalInits().isFakeReachable();
+ //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 markAsFakeReachable(boolean isFakeReachable) {
+ initsWhenTrue.markAsFakeReachable(isFakeReachable);
+ initsWhenFalse.markAsFakeReachable(isFakeReachable);
+ return this;
+}
+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());
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import java.util.ArrayList;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.TryStatement;
+import net.sourceforge.phpdt.internal.compiler.codegen.ObjectCache;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+
+/**
+ * Reflects the context of code analysis, keeping track of enclosing
+ * try statements, exception handlers, etc...
+ */
+public class ExceptionHandlingFlowContext extends FlowContext {
+
+ 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.DeadEnd;
+ }
+ }
+ System.arraycopy(this.isReached, 0, this.isNeeded, 0, cacheSize);
+ this.initsOnReturn = FlowInfo.DeadEnd;
+ }
+
+ public void complainIfUnusedExceptionHandlers(
+ AstNode[] exceptionHandlers,
+ 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().unreachableExceptionHandler(
+ handledExceptions[index],
+ exceptionHandlers[index]);
+ } else {
+ if ((isNeeded[cacheIndex] & bitMask) == 0) {
+ scope.problemReporter().maskedExceptionHandler(
+ handledExceptions[index],
+ exceptionHandlers[index]);
+ }
+ }
+ }
+ // will optimized out unnecessary catch block during code gen
+ tryStatement.preserveExceptionHandler = isNeeded;
+ }
+
+ 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(']');
+ }
+ return buffer.toString();
+ }
+
+ public UnconditionalFlowInfo initsOnException(ReferenceBinding exceptionType) {
+
+ int index;
+ if ((index = indexes.get(exceptionType)) < 0) {
+ return FlowInfo.DeadEnd;
+ }
+ return initsOnExceptions[index];
+ }
+
+ 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.DeadEnd
+ ? flowInfo.copy().unconditionalInits()
+ : initsOnExceptions[index].mergedWith(flowInfo);
+ }
+
+ public void recordReturnFrom(UnconditionalFlowInfo flowInfo) {
+
+ // record initializations which were performed at the return point
+ initsOnReturn = initsOnReturn.mergedWith(flowInfo);
+ }
+
+ /*
+ * 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);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.NameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.Reference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BindingIds;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
+import net.sourceforge.phpdt.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[];
+ 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++) {
+ Reference ref;
+ if (((ref = finalAssignments[i]).bits & BindingIds.FIELD) != 0) {
+ // final field
+ if (flowInfo.isPotentiallyAssigned(ref.fieldBinding())) {
+ scope.problemReporter().duplicateInitializationOfBlankFinalField(ref.fieldBinding(), ref);
+ }
+ } else {
+ // final local variable
+ if (flowInfo
+ .isPotentiallyAssigned((LocalVariableBinding) ((NameReference) ref).binding)) {
+ scope.problemReporter().duplicateInitializationOfFinalLocal(
+ (LocalVariableBinding) ((NameReference) ref).binding,
+ (NameReference) ref);
+ }
+ }
+ // any reference reported at this level is removed from the parent context
+ // where it could also be reported again
+ FlowContext currentContext = parent;
+ while (currentContext != null) {
+ if (currentContext.isSubRoutine()) {
+ currentContext.removeFinalAssignmentIfAny(ref);
+ }
+ currentContext = currentContext.parent;
+ }
+ }
+ }
+
+ public boolean isSubRoutine() {
+ return true;
+ }
+
+ boolean recordFinalAssignment(
+ VariableBinding binding,
+ Reference finalAssignment) {
+ if (assignCount == 0) {
+ finalAssignments = new Reference[5];
+ } else {
+ if (assignCount == finalAssignments.length)
+ System.arraycopy(
+ finalAssignments,
+ 0,
+ (finalAssignments = new Reference[assignCount * 2]),
+ 0,
+ assignCount);
+ };
+ finalAssignments[assignCount++] = finalAssignment;
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Reference;
+import net.sourceforge.phpdt.internal.compiler.codegen.Label;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
+import net.sourceforge.phpdt.internal.compiler.lookup.VariableBinding;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+/**
+ * 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) {
+ AstNode sub;
+ if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) {
+ // traversing a non-returning subroutine means that all unhandled
+ // exceptions will actually never get sent...
+ return;
+ }
+ // filter exceptions that are locally caught from the most enclosing
+ // try statement to the outer 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) {
+ switch (Scope.compareTypes(raisedException, caughtException)) {
+ 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 (scope
+ .areTypesCompatible(raisedException, scope.getJavaLangRuntimeException())
+ || scope.areTypesCompatible(raisedException, 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 = traversedContext.parent;
+ }
+ // if reaches this point, then there are some remaining unhandled exception types.
+ for (int i = 0; i < raisedCount; i++) {
+ TypeBinding exception;
+ if ((exception = raisedExceptions[i]) != null) {
+ 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) {
+ AstNode sub;
+ if (((sub = traversedContext.subRoutine()) != null) && sub.cannotReturn()) {
+ // traversing a non-returning subroutine means that all unhandled
+ // exceptions will actually never get sent...
+ return;
+ }
+ // filter exceptions that are locally caught from the most enclosing
+ // try statement to the outer 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];
+ switch (Scope.compareTypes(raisedException, caughtException)) {
+ 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 (scope
+ .areTypesCompatible(raisedException, scope.getJavaLangRuntimeException())
+ || scope.areTypesCompatible(raisedException, 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 = 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;
+ } else {
+ return lastNonReturningSubRoutine;
+ }
+ }
+ current = current.parent;
+ }
+ // not found
+ return null;
+ }
+
+ /*
+ * lookup through continue labels
+ */
+ public FlowContext getTargetContextForContinueLabel(char[] labelName) {
+ FlowContext current = this,
+ lastContinuable = null,
+ 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)) {
+ if ((lastContinuable != null)
+ && (current.associatedNode.concreteStatement()
+ == lastContinuable.associatedNode)) {
+ if (lastNonReturningSubRoutine == null) {
+ return lastContinuable;
+ } else {
+ return lastNonReturningSubRoutine;
+ }
+ } else {
+ // 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()) {
+ if (lastNonReturningSubRoutine == null) {
+ return current;
+ } else {
+ 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;
+ } else {
+ return lastNonReturningSubRoutine;
+ }
+ }
+ current = current.parent;
+ }
+ // not found
+ return null;
+ }
+
+ public String individualToString() {
+ return "Flow context"; //$NON-NLS-1$
+ }
+
+ public FlowInfo initsOnBreak() {
+ return FlowInfo.DeadEnd;
+ }
+
+ 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) {
+ }
+
+ public void recordContinueFrom(FlowInfo flowInfo) {
+ }
+
+ boolean recordFinalAssignment(
+ VariableBinding variable,
+ Reference finalReference) {
+ return true; // keep going
+ }
+
+ public void recordReturnFrom(UnconditionalFlowInfo flowInfo) {
+ }
+
+ public void recordSettingFinal(
+ VariableBinding variable,
+ Reference finalReference) {
+ // 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) {
+ }
+
+ public AstNode 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();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
+
+public abstract class FlowInfo {
+ public static final UnconditionalFlowInfo DeadEnd = new UnconditionalFlowInfo(); // Represents a dead branch status of initialization
+abstract public UnconditionalFlowInfo addInitializationsFrom(UnconditionalFlowInfo otherInits);
+abstract public UnconditionalFlowInfo addPotentialInitializationsFrom(UnconditionalFlowInfo otherInits);
+public FlowInfo asNegatedCondition() {
+ return this;
+}
+public boolean complainIfUnreachable(Statement statement, BlockScope scope) {
+ // Report an error if necessary
+
+ return false;
+}
+public static FlowInfo conditional(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){
+ // if (initsWhenTrue.equals(initsWhenFalse)) return initsWhenTrue; -- could optimize if #equals is defined
+ 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();
+final public boolean isDeadEnd() {
+ return this == DeadEnd;
+}
+/**
+ * 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 boolean isFakeReachable();
+/**
+ * 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);
+/**
+ * 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);
+abstract public FlowInfo markAsFakeReachable(boolean isFakeReachable);
+abstract public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits);
+public String toString(){
+ if (this == DeadEnd){
+ return "FlowInfo.DeadEnd"; //$NON-NLS-1$
+ }
+ return super.toString();
+}
+abstract public UnconditionalFlowInfo unconditionalInits();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+import net.sourceforge.phpdt.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,
+ new ReferenceBinding[] { scope.getJavaLangThrowable()},
+ // tolerate any kind of exception, but record them
+ scope, FlowInfo.DeadEnd);
+ }
+
+ 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 void recordHandlingException(
+ ReferenceBinding exceptionType,
+ UnconditionalFlowInfo flowInfo,
+ TypeBinding raisedException,
+ AstNode invocationSite,
+ boolean wasMasked) {
+
+ 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();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+
+/**
+ * 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.DeadEnd;
+ }
+
+ public boolean isNonReturningContext() {
+ return associatedNode.cannotReturn();
+ }
+
+ public AstNode subRoutine() {
+ return associatedNode;
+ }
+
+ public void recordReturnFrom(UnconditionalFlowInfo flowInfo) {
+ // record initializations which were performed at the return point
+ initsOnReturn = initsOnReturn.mergedWith(flowInfo);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.codegen.Label;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+/**
+ * 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;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.NameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.Reference;
+import net.sourceforge.phpdt.internal.compiler.codegen.Label;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.Scope;
+import net.sourceforge.phpdt.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.DeadEnd;
+ 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;
+ if ((variable = finalVariables[i]) != null) {
+ boolean complained; // remember if have complained on this final assignment
+ if (variable instanceof FieldBinding) {
+ if (complained = flowInfo.isPotentiallyAssigned((FieldBinding) variable)) {
+ scope.problemReporter().duplicateInitializationOfBlankFinalField(
+ (FieldBinding) variable,
+ (NameReference) finalAssignments[i]);
+ }
+ } else {
+ if (complained =
+ flowInfo.isPotentiallyAssigned((LocalVariableBinding) variable)) {
+ scope.problemReporter().duplicateInitializationOfFinalLocal(
+ (LocalVariableBinding) variable,
+ (NameReference) 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() {
+ return "Looping flow context"; //$NON-NLS-1$
+ }
+
+ public boolean isContinuable() {
+ return true;
+ }
+
+ public boolean isContinuedTo() {
+ return initsOnContinue != FlowInfo.DeadEnd;
+ }
+
+ public void recordContinueFrom(FlowInfo flowInfo) {
+ if (initsOnContinue == FlowInfo.DeadEnd) {
+ initsOnContinue = flowInfo.copy().unconditionalInits();
+ } else {
+ // ignore if not really reachable (1FKEKRP)
+ if (flowInfo.isFakeReachable())
+ return;
+ initsOnContinue.mergedWith(flowInfo.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;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.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.DeadEnd;
+
+ public SwitchFlowContext(
+ FlowContext parent,
+ AstNode associatedNode,
+ Label breakLabel) {
+ super(parent, associatedNode);
+ this.breakLabel = breakLabel;
+ }
+
+ public Label breakLabel() {
+ return breakLabel;
+ }
+
+ public String individualToString() {
+ return "Switch flow context"; //$NON-NLS-1$
+ }
+
+ public boolean isBreakable() {
+ return true;
+ }
+
+ public void recordBreakFrom(FlowInfo flowInfo) {
+ if (initsOnBreak == FlowInfo.DeadEnd) {
+ initsOnBreak = flowInfo.copy().unconditionalInits();
+ } else {
+ // ignore if not really reachable (1FKEKRP)
+ if (flowInfo.isFakeReachable())
+ return;
+ initsOnBreak.mergedWith(flowInfo.unconditionalInits());
+ };
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.flow;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
+import net.sourceforge.phpdt.internal.compiler.lookup.FieldBinding;
+import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
+import net.sourceforge.phpdt.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;
+ long potentialInits;
+ public long extraDefiniteInits[];
+ long extraPotentialInits[];
+ public boolean isFakeReachable;
+ public int maxFieldCount;
+
+ // Constants
+ public static final int BitCacheSize = 64; // 64 bits in a long.
+UnconditionalFlowInfo() {
+}
+public UnconditionalFlowInfo addInitializationsFrom(UnconditionalFlowInfo otherInits) {
+
+ // unions of both sets of initialization - used for try/finally
+ if (this == DeadEnd)
+ return this;
+ if (otherInits == DeadEnd)
+ 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;
+}
+public UnconditionalFlowInfo addPotentialInitializationsFrom(UnconditionalFlowInfo otherInits) {
+
+ // unions of both sets of initialization - used for try/finally
+ if (this == DeadEnd){
+ return this;
+ }
+ if (otherInits == DeadEnd){
+ 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;
+}
+public boolean complainIfUnreachable(Statement statement, BlockScope scope) {
+ // Report an error if necessary
+
+ boolean isDeadEnd;
+ if ((isDeadEnd = (this == DeadEnd)) || isFakeReachable) {
+ statement.bits &= ~AstNode.IsReachableMASK;
+ /* EXTRA REFERENCE RECORDING
+ statement.recordUnreachableReferences(scope.referenceType()); // scopes cannot have an enclosingMethod slot since there are class scopes
+ */
+ if (isDeadEnd)
+ scope.problemReporter().unreachableCode(statement);
+ return isDeadEnd;
+ }
+ return false;
+}
+/**
+ * Answers a copy of the current instance
+ */
+public FlowInfo copy() {
+ // do not clone the DeadEnd
+ if (this == DeadEnd)
+ return this;
+
+ // look for an unused preallocated object
+ UnconditionalFlowInfo copy = new UnconditionalFlowInfo();
+
+ // copy slots
+ copy.definiteInits = definiteInits;
+ copy.potentialInits = potentialInits;
+ copy.isFakeReachable = isFakeReachable;
+ copy.maxFieldCount = maxFieldCount;
+
+ if (extraDefiniteInits != null) {
+ int length;
+ System.arraycopy(extraDefiniteInits, 0, (copy.extraDefiniteInits = new long[ (length = extraDefiniteInits.length)]), 0, length);
+ System.arraycopy(extraPotentialInits, 0, (copy.extraPotentialInits = new long[length]), 0, length);
+ };
+ return copy;
+}
+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 == DeadEnd) || (this.isFakeReachable))
+ 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 == DeadEnd) || (this.isFakeReachable))
+ return true;
+ if (local.isArgument) {
+ return true;
+ }
+ return isDefinitelyAssigned(local.id + maxFieldCount);
+}
+public boolean isFakeReachable() {
+ return isFakeReachable;
+}
+/**
+ * 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) {
+ // We do not want to complain in unreachable code
+ if ((this == DeadEnd) || (this.isFakeReachable))
+ return false;
+ return isPotentiallyAssigned(field.id);
+}
+/**
+ * Check status of potential assignment for a local.
+ */
+final public boolean isPotentiallyAssigned(LocalVariableBinding local) {
+ // We do not want to complain in unreachable code
+ if ((this == DeadEnd) || (this.isFakeReachable))
+ return false;
+ if (local.isArgument) {
+ 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 != DeadEnd) {
+
+ // 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 != DeadEnd)
+ markAsDefinitelyAssigned(field.id);
+}
+/**
+ * Record a local got definitely assigned.
+ */
+public void markAsDefinitelyAssigned(LocalVariableBinding local) {
+ if (this != DeadEnd)
+ 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 != DeadEnd) {
+
+ // 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
+ } else {
+ // 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 != DeadEnd)
+ markAsDefinitelyNotAssigned(field.id);
+}
+/**
+ * Clear the initialization info for a local variable
+ */
+
+public void markAsDefinitelyNotAssigned(LocalVariableBinding local) {
+ if (this != DeadEnd)
+ markAsDefinitelyNotAssigned(local.id + maxFieldCount);
+}
+public FlowInfo markAsFakeReachable(boolean isFakeReachable) {
+ this.isFakeReachable = isFakeReachable;
+ return this;
+}
+public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
+ // updates the receiver with:
+ // - intersection of definitely assigned variables,
+ // - union of potentially set ones
+
+ if (this == DeadEnd)
+ return otherInits;
+ if (otherInits == DeadEnd)
+ return this;
+
+ // if one branch is not fake reachable, then the merged one is reachable
+ if (!otherInits.isFakeReachable())
+ markAsFakeReachable(false);
+
+ // intersection 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
+ int i = 0, length = extraDefiniteInits.length;
+ while (i < length)
+ extraDefiniteInits[i++] = 0;
+ }
+ } 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;
+}
+/*
+ * 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 String toString(){
+ if (this == DeadEnd){
+ return "FlowInfo.DeadEnd"; //$NON-NLS-1$
+ }
+ return "FlowInfo<def: "+ definiteInits +", pot: " + potentialInits + ">"; //$NON-NLS-1$ //$NON-NLS-3$ //$NON-NLS-2$
+}
+public UnconditionalFlowInfo unconditionalInits() {
+ // also see conditional inits, where it requests them to merge
+ return this;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+
+public class BooleanConstant extends Constant {
+ boolean value;
+
+
+public BooleanConstant(boolean value) {
+ this.value = value;
+}
+public boolean booleanValue() {
+ return (boolean) value;
+}
+public String stringValue() {
+ //spec 15.17.11
+
+ String s = new Boolean(value).toString() ;
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ return s;
+}
+public String toString(){
+
+ return "(boolean)" + value ; } //$NON-NLS-1$
+public int typeID() {
+ return T_boolean;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+
+public class ByteConstant extends Constant {
+ byte value;
+public ByteConstant(byte value) {
+ this.value = value;
+}
+public byte byteValue() {
+ return (byte) value;
+}
+public char charValue() {
+ return (char) value;
+}
+public double doubleValue() {
+ return (double) value;
+}
+public float floatValue() {
+ return (float) value;
+}
+public int intValue() {
+ return (int) value;
+}
+public long longValue() {
+ return (long) value;
+}
+public short shortValue() {
+ return (short) value;
+}
+public String stringValue() {
+ //spec 15.17.11
+
+ String s = new Integer(value).toString() ;
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ return s;
+}
+public String toString(){
+
+ return "(byte)" + value ; } //$NON-NLS-1$
+public int typeID() {
+ return T_byte;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+
+public class CharConstant extends Constant {
+ char value;
+public CharConstant(char value) {
+ this.value = value;
+}
+public byte byteValue() {
+ return (byte) value;
+}
+public char charValue() {
+ return (char) value;
+}
+public double doubleValue() {
+ return (double) value;
+}
+public float floatValue() {
+ return (float) value;
+}
+public int intValue() {
+ return (int) value;
+}
+public long longValue() {
+ return (long) value;
+}
+public short shortValue() {
+ return (short) value;
+}
+public String stringValue() {
+ //spec 15.17.11
+
+ String s = new Character(value).toString() ;
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ return s;
+}
+public String toString(){
+
+ return "(char)" + value ; } //$NON-NLS-1$
+public int typeID() {
+ return T_char;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+
+import net.sourceforge.phpdt.internal.compiler.Compiler;
+import net.sourceforge.phpdt.internal.compiler.lookup.ProblemReasons;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemSeverities;
+
+
+public class CompilerOptions implements ProblemReasons, ProblemSeverities {
+
+ /**
+ * 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_ReportUnreachableCode = "org.eclipse.jdt.core.compiler.problem.unreachableCode"; //$NON-NLS-1$
+ public static final String OPTION_ReportInvalidImport = "org.eclipse.jdt.core.compiler.problem.invalidImport"; //$NON-NLS-1$
+ public static final String OPTION_ReportMethodWithConstructorName = "org.eclipse.jdt.core.compiler.problem.methodWithConstructorName"; //$NON-NLS-1$
+ public static final String OPTION_ReportOverridingPackageDefaultMethod = "org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod"; //$NON-NLS-1$
+ public static final String OPTION_ReportDeprecation = "org.eclipse.jdt.core.compiler.problem.deprecation"; //$NON-NLS-1$
+ public static final String OPTION_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_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_ReportNonExternalizedStringLiteral = "org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral"; //$NON-NLS-1$
+ public static final String OPTION_Source = "org.eclipse.jdt.core.compiler.source"; //$NON-NLS-1$
+ public static final String OPTION_TargetPlatform = "org.eclipse.jdt.core.compiler.codegen.targetPlatform"; //$NON-NLS-1$
+ public static final String OPTION_ReportAssertIdentifier = "org.eclipse.jdt.core.compiler.problem.assertIdentifier"; //$NON-NLS-1$
+ public static final String OPTION_Compliance = "org.eclipse.jdt.core.compiler.compliance"; //$NON-NLS-1$
+ public static final String OPTION_Encoding = "org.eclipse.jdt.core.encoding"; //$NON-NLS-1$
+ public static final String OPTION_MaxProblemPerUnit = "org.eclipse.jdt.core.compiler.maxProblemPerUnit"; //$NON-NLS-1$
+
+ /* 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 ERROR = "error"; //$NON-NLS-1$
+ public static final String WARNING = "warning"; //$NON-NLS-1$
+ public static final String IGNORE = "ignore"; //$NON-NLS-1$
+
+ /**
+ * Bit mask for configurable problems (error/warning threshold)
+ */
+ public static final int UnreachableCode = 0x100;
+ public static final int ImportProblem = 0x400;
+ public static final int MethodWithConstructorName = 0x1000;
+ public static final int OverriddenPackageDefaultMethod = 0x2000;
+ public static final int UsingDeprecatedAPI = 0x4000;
+ public static final int MaskedCatchBlock = 0x8000;
+ public static final int UnusedLocalVariable = 0x10000;
+ public static final int UnusedArgument = 0x20000;
+ public static final int NoImplicitStringConversion = 0x40000;
+ public static final int AccessEmulation = 0x80000;
+ public static final int NonExternalizedString = 0x100000;
+ public static final int AssertUsedAsAnIdentifier = 0x200000;
+ public static final int UnusedImport = 0x400000;
+
+ // Default severity level for handlers
+ public int errorThreshold = UnreachableCode | ImportProblem;
+ public int warningThreshold =
+ MethodWithConstructorName | OverriddenPackageDefaultMethod
+ | UsingDeprecatedAPI | MaskedCatchBlock
+ | AssertUsedAsAnIdentifier | NoImplicitStringConversion;
+
+ // 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;
+
+
+ // JDK 1.1, 1.2, 1.3 or 1.4
+ public static final int JDK1_1 = 0;
+ public static final int JDK1_2 = 1;
+ public static final int JDK1_3 = 2;
+ public static final int JDK1_4 = 3;
+
+ public int targetJDK = JDK1_1; // default generates for JVM1.1
+ public int complianceLevel = JDK1_3; // by default be compliant with 1.3
+
+ // toggle private access emulation for 1.2 (constr. accessor has extra arg on constructor) or 1.3 (make private constructor default access when access needed)
+ public boolean isPrivateConstructorAccessChangingVisibility = false; // by default, follows 1.2
+
+ // 1.4 feature
+ public boolean assertMode = false; //1.3 behavior by default
+
+ // 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 = true;
+
+ // 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;
+
+ // exception raised for unresolved compile errors
+ public String runtimeExceptionNameForCompileError = "java.lang.Error"; //$NON-NLS-1$
+
+ // max problems per compilation unit
+ public int maxProblemsPerUnit = 100; // no more than 100 problems per default
+
+ /**
+ * Initializing the compiler options with defaults
+ */
+ public CompilerOptions(){
+ }
+
+ /**
+ * Initializing the compiler options with external settings
+ */
+ public CompilerOptions(Map settings){
+
+ if (settings == null) return;
+
+ // filter options which are related to the compiler component
+ Object[] entries = settings.entrySet().toArray();
+ for (int i = 0, max = entries.length; i < max; i++){
+ Map.Entry entry = (Map.Entry)entries[i];
+ if (!(entry.getKey() instanceof String)) continue;
+ if (!(entry.getValue() instanceof String)) continue;
+ String optionID = (String) entry.getKey();
+ String optionValue = (String) entry.getValue();
+
+ // Local variable attribute
+ if(optionID.equals(OPTION_LocalVariableAttribute)){
+ if (optionValue.equals(GENERATE)) {
+ this.produceDebugAttributes |= Vars;
+ } else if (optionValue.equals(DO_NOT_GENERATE)){
+ this.produceDebugAttributes &= ~Vars;
+ }
+ continue;
+ }
+ // Line number attribute
+ if(optionID.equals(OPTION_LineNumberAttribute)) {
+ if (optionValue.equals(GENERATE)) {
+ this.produceDebugAttributes |= Lines;
+ } else if (optionValue.equals(DO_NOT_GENERATE)) {
+ this.produceDebugAttributes &= ~Lines;
+ }
+ continue;
+ }
+ // Source file attribute
+ if(optionID.equals(OPTION_SourceFileAttribute)) {
+ if (optionValue.equals(GENERATE)) {
+ this.produceDebugAttributes |= Source;
+ } else if (optionValue.equals(DO_NOT_GENERATE)) {
+ this.produceDebugAttributes &= ~Source;
+ }
+ continue;
+ }
+ // Preserve unused local
+ if(optionID.equals(OPTION_PreserveUnusedLocal)){
+ if (optionValue.equals(PRESERVE)) {
+ this.preserveAllLocalVariables = true;
+ } else if (optionValue.equals(OPTIMIZE_OUT)) {
+ this.preserveAllLocalVariables = false;
+ }
+ continue;
+ }
+ // Report unreachable code
+ if(optionID.equals(OPTION_ReportUnreachableCode)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= UnreachableCode;
+ this.warningThreshold &= ~UnreachableCode;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~UnreachableCode;
+ this.warningThreshold |= UnreachableCode;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~UnreachableCode;
+ this.warningThreshold &= ~UnreachableCode;
+ }
+ continue;
+ }
+ // Report invalid import
+ if(optionID.equals(OPTION_ReportInvalidImport)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= ImportProblem;
+ this.warningThreshold &= ~ImportProblem;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~ImportProblem;
+ this.warningThreshold |= ImportProblem;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~ImportProblem;
+ this.warningThreshold &= ~ImportProblem;
+ }
+ continue;
+ }
+ // Define the target JDK tag for .classfiles
+ if(optionID.equals(OPTION_TargetPlatform)){
+ if (optionValue.equals(VERSION_1_1)) {
+ this.targetJDK = JDK1_1;
+ } else if (optionValue.equals(VERSION_1_2)) {
+ this.targetJDK = JDK1_2;
+ } else if (optionValue.equals(VERSION_1_3)) {
+ this.targetJDK = JDK1_3;
+ } else if (optionValue.equals(VERSION_1_4)) {
+ this.targetJDK = JDK1_4;
+ }
+ continue;
+ }
+ // Define the JDK compliance level
+ if(optionID.equals(OPTION_Compliance)){
+ if (optionValue.equals(VERSION_1_1)) {
+ this.complianceLevel = JDK1_1;
+ } else if (optionValue.equals(VERSION_1_2)) {
+ this.complianceLevel = JDK1_2;
+ } else if (optionValue.equals(VERSION_1_3)) {
+ this.complianceLevel = JDK1_3;
+ } else if (optionValue.equals(VERSION_1_4)) {
+ this.complianceLevel = JDK1_4;
+ }
+ continue;
+ }
+ // Private constructor access emulation (extra arg vs. visibility change)
+ if(optionID.equals(OPTION_PrivateConstructorAccess)){
+ if (optionValue.equals(VERSION_1_1)) {
+ this.isPrivateConstructorAccessChangingVisibility = false;
+ } else if (optionValue.equals(VERSION_1_2)) {
+ this.isPrivateConstructorAccessChangingVisibility = false;
+ } else if (optionValue.equals(VERSION_1_3)) {
+ this.isPrivateConstructorAccessChangingVisibility = true;
+ } else if (optionValue.equals(VERSION_1_4)) {
+ this.isPrivateConstructorAccessChangingVisibility = true;
+ }
+ continue;
+ }
+ // Report method with constructor name
+ if(optionID.equals(OPTION_ReportMethodWithConstructorName)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= MethodWithConstructorName;
+ this.warningThreshold &= ~MethodWithConstructorName;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~MethodWithConstructorName;
+ this.warningThreshold |= MethodWithConstructorName;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~MethodWithConstructorName;
+ this.warningThreshold &= ~MethodWithConstructorName;
+ }
+ continue;
+ }
+ // Report overriding package default method
+ if(optionID.equals(OPTION_ReportOverridingPackageDefaultMethod)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= OverriddenPackageDefaultMethod;
+ this.warningThreshold &= ~OverriddenPackageDefaultMethod;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~OverriddenPackageDefaultMethod;
+ this.warningThreshold |= OverriddenPackageDefaultMethod;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~OverriddenPackageDefaultMethod;
+ this.warningThreshold &= ~OverriddenPackageDefaultMethod;
+ }
+ continue;
+ }
+ // Report deprecation
+ if(optionID.equals(OPTION_ReportDeprecation)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= UsingDeprecatedAPI;
+ this.warningThreshold &= ~UsingDeprecatedAPI;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~UsingDeprecatedAPI;
+ this.warningThreshold |= UsingDeprecatedAPI;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~UsingDeprecatedAPI;
+ this.warningThreshold &= ~UsingDeprecatedAPI;
+ }
+ continue;
+ }
+ // Report hidden catch block
+ if(optionID.equals(OPTION_ReportHiddenCatchBlock)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= MaskedCatchBlock;
+ this.warningThreshold &= ~MaskedCatchBlock;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~MaskedCatchBlock;
+ this.warningThreshold |= MaskedCatchBlock;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~MaskedCatchBlock;
+ this.warningThreshold &= ~MaskedCatchBlock;
+ }
+ continue;
+ }
+ // Report unused local variable
+ if(optionID.equals(OPTION_ReportUnusedLocal)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= UnusedLocalVariable;
+ this.warningThreshold &= ~UnusedLocalVariable;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~UnusedLocalVariable;
+ this.warningThreshold |= UnusedLocalVariable;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~UnusedLocalVariable;
+ this.warningThreshold &= ~UnusedLocalVariable;
+ }
+ continue;
+ }
+ // Report unused parameter
+ if(optionID.equals(OPTION_ReportUnusedParameter)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= UnusedArgument;
+ this.warningThreshold &= ~UnusedArgument;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~UnusedArgument;
+ this.warningThreshold |= UnusedArgument;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~UnusedArgument;
+ this.warningThreshold &= ~UnusedArgument;
+ }
+ continue;
+ }
+ // Report unused parameter
+ if(optionID.equals(OPTION_ReportUnusedImport)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= UnusedImport;
+ this.warningThreshold &= ~UnusedImport;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~UnusedImport;
+ this.warningThreshold |= UnusedImport;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~UnusedImport;
+ this.warningThreshold &= ~UnusedImport;
+ }
+ continue;
+ }
+ // Report synthetic access emulation
+ if(optionID.equals(OPTION_ReportSyntheticAccessEmulation)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= AccessEmulation;
+ this.warningThreshold &= ~AccessEmulation;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~AccessEmulation;
+ this.warningThreshold |= AccessEmulation;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~AccessEmulation;
+ this.warningThreshold &= ~AccessEmulation;
+ }
+ continue;
+ }
+ // Report non-externalized string literals
+ if(optionID.equals(OPTION_ReportNonExternalizedStringLiteral)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= NonExternalizedString;
+ this.warningThreshold &= ~NonExternalizedString;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~NonExternalizedString;
+ this.warningThreshold |= NonExternalizedString;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~NonExternalizedString;
+ this.warningThreshold &= ~NonExternalizedString;
+ }
+ continue;
+ }
+ // Report usage of 'assert' as an identifier
+ if(optionID.equals(OPTION_ReportAssertIdentifier)){
+ if (optionValue.equals(ERROR)) {
+ this.errorThreshold |= AssertUsedAsAnIdentifier;
+ this.warningThreshold &= ~AssertUsedAsAnIdentifier;
+ } else if (optionValue.equals(WARNING)) {
+ this.errorThreshold &= ~AssertUsedAsAnIdentifier;
+ this.warningThreshold |= AssertUsedAsAnIdentifier;
+ } else if (optionValue.equals(IGNORE)) {
+ this.errorThreshold &= ~AssertUsedAsAnIdentifier;
+ this.warningThreshold &= ~AssertUsedAsAnIdentifier;
+ }
+ continue;
+ }
+ // Set the source compatibility mode (assertions)
+ if(optionID.equals(OPTION_Source)){
+ if (optionValue.equals(VERSION_1_3)) {
+ this.assertMode = false;
+ } else if (optionValue.equals(VERSION_1_4)) {
+ this.assertMode = true;
+ }
+ continue;
+ }
+ // Set the default encoding format
+ if(optionID.equals(OPTION_Encoding)){
+ if (optionValue.length() == 0){
+ this.defaultEncoding = null;
+ } else {
+ try { // ignore unsupported encoding
+ new InputStreamReader(new ByteArrayInputStream(new byte[0]), optionValue);
+ this.defaultEncoding = optionValue;
+ } catch(UnsupportedEncodingException e){
+ }
+ }
+ continue;
+ }
+ // Set the threshold for problems per unit
+ if(optionID.equals(OPTION_MaxProblemPerUnit)){
+ try {
+ int val = Integer.parseInt(optionValue);
+ if (val >= 0) this.maxProblemsPerUnit = val;
+ } catch(NumberFormatException e){
+ }
+ continue;
+ }
+ }
+ }
+
+ public int getTargetJDK() {
+ return this.targetJDK;
+ }
+
+ public int getNonExternalizedStringLiteralSeverity() {
+ if((warningThreshold & NonExternalizedString) != 0)
+ return Warning;
+ if((errorThreshold & NonExternalizedString) != 0)
+ return Error;
+ return Ignore;
+ }
+
+ public void produceReferenceInfo(boolean flag) {
+ this.produceReferenceInfo = flag;
+ }
+
+ public void setVerboseMode(boolean flag) {
+ this.verbose = flag;
+ }
+
+ public String toString() {
+
+
+ StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$
+ if ((produceDebugAttributes & Vars) != 0){
+ buf.append("\n-local variables debug attributes: ON"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-local variables debug attributes: OFF"); //$NON-NLS-1$
+ }
+ if ((produceDebugAttributes & Lines) != 0){
+ buf.append("\n-line number debug attributes: ON"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-line number debug attributes: OFF"); //$NON-NLS-1$
+ }
+ if ((produceDebugAttributes & Source) != 0){
+ buf.append("\n-source debug attributes: ON"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-source debug attributes: OFF"); //$NON-NLS-1$
+ }
+ if (preserveAllLocalVariables){
+ buf.append("\n-preserve all local variables: ON"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-preserve all local variables: OFF"); //$NON-NLS-1$
+ }
+ if ((errorThreshold & UnreachableCode) != 0){
+ buf.append("\n-unreachable code: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & UnreachableCode) != 0){
+ buf.append("\n-unreachable code: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-unreachable code: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & ImportProblem) != 0){
+ buf.append("\n-import problem: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & ImportProblem) != 0){
+ buf.append("\n-import problem: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-import problem: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & MethodWithConstructorName) != 0){
+ buf.append("\n-method with constructor name: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & MethodWithConstructorName) != 0){
+ buf.append("\n-method with constructor name: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-method with constructor name: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & OverriddenPackageDefaultMethod) != 0){
+ buf.append("\n-overridden package default method: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & OverriddenPackageDefaultMethod) != 0){
+ buf.append("\n-overridden package default method: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-overridden package default method: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & UsingDeprecatedAPI) != 0){
+ buf.append("\n-deprecation: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & UsingDeprecatedAPI) != 0){
+ buf.append("\n-deprecation: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-deprecation: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & MaskedCatchBlock) != 0){
+ buf.append("\n-masked catch block: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & MaskedCatchBlock) != 0){
+ buf.append("\n-masked catch block: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-masked catch block: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & UnusedLocalVariable) != 0){
+ buf.append("\n-unused local variable: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & UnusedLocalVariable) != 0){
+ buf.append("\n-unused local variable: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-unused local variable: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & UnusedArgument) != 0){
+ buf.append("\n-unused parameter: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & UnusedArgument) != 0){
+ buf.append("\n-unused parameter: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-unused parameter: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & UnusedImport) != 0){
+ buf.append("\n-unused import: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & UnusedImport) != 0){
+ buf.append("\n-unused import: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-unused import: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & AccessEmulation) != 0){
+ buf.append("\n-synthetic access emulation: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & AccessEmulation) != 0){
+ buf.append("\n-synthetic access emulation: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-synthetic access emulation: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ if ((errorThreshold & NonExternalizedString) != 0){
+ buf.append("\n-non externalized string: ERROR"); //$NON-NLS-1$
+ } else {
+ if ((warningThreshold & NonExternalizedString) != 0){
+ buf.append("\n-non externalized string: WARNING"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-non externalized string: IGNORE"); //$NON-NLS-1$
+ }
+ }
+ switch(targetJDK){
+ case JDK1_1 :
+ buf.append("\n-target JDK: 1.1"); //$NON-NLS-1$
+ break;
+ case JDK1_2 :
+ buf.append("\n-target JDK: 1.2"); //$NON-NLS-1$
+ break;
+ case JDK1_3 :
+ buf.append("\n-target JDK: 1.3"); //$NON-NLS-1$
+ break;
+ case JDK1_4 :
+ buf.append("\n-target JDK: 1.4"); //$NON-NLS-1$
+ break;
+ }
+ switch(complianceLevel){
+ case JDK1_1 :
+ buf.append("\n-compliance JDK: 1.1"); //$NON-NLS-1$
+ break;
+ case JDK1_2 :
+ buf.append("\n-compliance JDK: 1.2"); //$NON-NLS-1$
+ break;
+ case JDK1_3 :
+ buf.append("\n-compliance JDK: 1.3"); //$NON-NLS-1$
+ break;
+ case JDK1_4 :
+ buf.append("\n-compliance JDK: 1.4"); //$NON-NLS-1$
+ break;
+ }
+ if (isPrivateConstructorAccessChangingVisibility){
+ buf.append("\n-private constructor access emulation: extra argument"); //$NON-NLS-1$
+ } else {
+ buf.append("\n-private constructor access emulation: make default access"); //$NON-NLS-1$
+ }
+ buf.append("\n-verbose : " + (verbose ? "ON" : "OFF")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ buf.append("\n-produce reference info : " + (produceReferenceInfo ? "ON" : "OFF")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ buf.append("\n-parse literal expressions as constants : " + (parseLiteralExpressionsAsConstants ? "ON" : "OFF")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ buf.append("\n-runtime exception name for compile error : " + runtimeExceptionNameForCompileError); //$NON-NLS-1$
+ buf.append("\n-encoding : " + (defaultEncoding == null ? "<default>" : defaultEncoding)); //$NON-NLS-1$ //$NON-NLS-2$
+ return buf.toString();
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+
+import net.sourceforge.phpdt.internal.compiler.ast.OperatorIds;
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeIds;
+import net.sourceforge.phpdt.internal.compiler.problem.ShouldNotImplement;
+import net.sourceforge.phpdt.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 ....
+ //This method assumes that the TC is done (correctly :-)
+
+ if (this == NotAConstant) return NotAConstant ;
+ switch(conversionToTargetType){
+ case T_undefined : return this;
+// 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_undefined<<4)+T_null : 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_byte<<4)+T_null : return NotAConstant ;
+
+// 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_long<<4)+T_null : return NotAConstant ;
+
+// 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_short<<4)+T_null : return NotAConstant ;
+
+// 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_void<<4)+T_null : 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_String<<4)+T_null : 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_Object<<4)+T_null : return this ;
+
+// 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_double<<4)+T_null : return NotAConstant ;
+
+// 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_float<<4)+T_null : return NotAConstant ;
+
+// 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_boolean<<4)+T_null : 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_char<<4)+T_null : return NotAConstant ;
+
+// 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 ;
+// case (T_int<<4)+T_null : return NotAConstant ;
+
+// case (T_null<<4)+T_undefined : return NotAConstant ;
+// case (T_null<<4)+T_byte : return NotAConstant ;
+// case (T_null<<4)+T_long : return NotAConstant ;
+// case (T_null<<4)+T_short : return NotAConstant ;
+// case (T_null<<4)+T_void : return NotAConstant ;
+// case (T_null<<4)+T_String : return NotAConstant ;
+// case (T_null<<4)+T_Object : return NotAConstant ;
+// case (T_null<<4)+T_double : return NotAConstant ;
+// case (T_null<<4)+T_float : return NotAConstant ;
+// case (T_null<<4)+T_boolean : return NotAConstant ;
+// case (T_null<<4)+T_char : return NotAConstant ;
+// case (T_null<<4)+T_int : return NotAConstant ;
+ case (T_null<<4)+T_null : 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) {
+ //this method assumes that the TC has been done .
+ //the result should be availbale with not runtime error
+
+ 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;} //should not occur.....(conservative code)
+ default : return NotAConstant ;}} //should not occur....(conservative code)
+public static final Constant computeConstantOperation(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done . So (except for divide by zero)
+ //the result should be availbale with not runtime error
+
+ 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 ;}} //should not occurs....(conservative code)
+public static final Constant computeConstantOperationAND(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} // should not get here
+public static final Constant computeConstantOperationAND_AND(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ return Constant.fromValue(left.booleanValue() && right.booleanValue()) ;}
+public static final Constant computeConstantOperationDIVIDE(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+ // the /0 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 ;} //should not get here
+public static final Constant computeConstantOperationEQUAL_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 intermed 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) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} //should not get here
+public static final Constant computeConstantOperationGREATER_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} //should not get here
+public static final Constant computeConstantOperationLEFT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} // should not get here
+public static final Constant computeConstantOperationLESS(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} //should not get here
+public static final Constant computeConstantOperationLESS_EQUAL(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} //should not get here
+public static final Constant computeConstantOperationMINUS(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} //should not get here
+public static final Constant computeConstantOperationMULTIPLY(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} //should not get here
+public static final Constant computeConstantOperationOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} // should not get here
+public static final Constant computeConstantOperationOR_OR(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ return Constant.fromValue(left.booleanValue() || right.booleanValue()) ;}
+public static final Constant computeConstantOperationPLUS(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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_null: 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()) ;
+ case T_null: return Constant.fromValue(left.stringValue() + right.stringValue()) ; }
+
+ }
+
+ return NotAConstant ;} //should not get here
+public static final Constant computeConstantOperationREMAINDER(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} //should not get here
+public static final Constant computeConstantOperationRIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} // should not get here
+public static final Constant computeConstantOperationUNSIGNED_RIGHT_SHIFT(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} // should not get here
+public static final Constant computeConstantOperationXOR(Constant left, int leftId, int operator, Constant right, int rightId) {
+ //this method assumes that the TC has been done .
+
+ 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 ;} // should not get here
+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) {
+ if (value == null) return NullConstant.Default;
+ 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$
+}
+/** Deprecated
+*/
+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$
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 (double) value;
+ }
+
+ public float floatValue() {
+ return (float) value;
+ }
+
+ public int intValue() {
+ return (int) value;
+ }
+
+ public long longValue() {
+ return (long) value;
+ }
+
+ public short shortValue() {
+ return (short) value;
+ }
+
+ public String stringValue() {
+ //spec 15.17.11
+ String s = new Double(value).toString();
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ 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;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 (double) value;
+ }
+
+ public float floatValue() {
+ return (float) value;
+ }
+
+ public int intValue() {
+ return (int) value;
+ }
+
+ public long longValue() {
+ return (long) value;
+ }
+
+ public short shortValue() {
+ return (short) value;
+ }
+
+ public String stringValue() {
+ //spec 15.17.11
+ String s = new Float(value).toString();
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ return s;
+ }
+
+ public String toString() {
+ return "(float)" + value; //$NON-NLS-1$
+ }
+
+ public int typeID() {
+ return T_float;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
+import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
+import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
+import net.sourceforge.phpdt.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);
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 (double) value;
+ }
+
+ public float floatValue() {
+ return (float) value;
+ }
+
+ public int intValue() {
+ return (int) value;
+ }
+
+ public long longValue() {
+ return (long) value;
+ }
+
+ public short shortValue() {
+ return (short) value;
+ }
+
+ public String stringValue() {
+ //spec 15.17.11
+ String s = new Integer(value).toString();
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ return s;
+ }
+
+ public String toString() {
+ return "(int)" + value; //$NON-NLS-1$
+ }
+
+ public int typeID() {
+ return T_int;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 (double) value;
+}
+public float floatValue() {
+ return (float) value;
+}
+public int intValue() {
+ return (int) value;
+}
+public long longValue() {
+ return (long) value;
+}
+public short shortValue() {
+ return (short) value;
+}
+public String stringValue() {
+ //spec 15.17.11
+
+ String s = new Long(value).toString() ;
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ return s;
+}
+public String toString(){
+
+ return "(long)" + value ; } //$NON-NLS-1$
+public int typeID() {
+ return T_long;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+
+public class NullConstant extends Constant {
+ public static final NullConstant Default = new NullConstant();
+
+ final static String NullString = new StringBuffer(4).append((String)null).toString();
+private NullConstant() {
+}
+public String stringValue() {
+
+ return NullString;
+}
+public String toString(){
+
+ return "(null)" + null ; } //$NON-NLS-1$
+public int typeID() {
+ return T_null;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.impl;
+/*
+ * Implementors are valid compilation contexts from which we can
+ * escape in case of error:
+ * i.e. method | type | compilation unit
+ */
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+
+public interface ReferenceContext {
+ void abort(int abortLevel);
+ CompilationResult compilationResult();
+ void tagAsHavingErrors();
+ boolean hasErrors();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 (double) value;
+}
+public float floatValue() {
+ return (float) value;
+}
+public int intValue() {
+ return (int) value;
+}
+public long longValue() {
+ return (long) value;
+}
+public short shortValue() {
+ return (short) value;
+}
+public String stringValue() {
+ //spec 15.17.11
+
+ String s = new Integer(value).toString() ;
+ if (s == null)
+ return "null"; //$NON-NLS-1$
+ else
+ return s;
+}
+public String toString(){
+
+ return "(short)" + value ; } //$NON-NLS-1$
+public int typeID() {
+ return T_short;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public final class ArrayBinding extends TypeBinding {
+ // creation and initialization of the length field
+ // the declaringClass of this field is intentionally set to null so it can be distinguished.
+ public static final FieldBinding LengthField = new FieldBinding(LENGTH, IntBinding, AccPublic | AccFinal, null, Constant.NotAConstant);
+
+ public 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.
+*/
+
+public char[] constantPoolName() /* [Ljava/lang/Object; */ {
+ 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();
+}
+/* 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;
+ else
+ 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)
+*/
+
+boolean isCompatibleWith(TypeBinding right) {
+ if (this == right)
+ return true;
+
+ char[][] rightName;
+ 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[]'
+ rightName = ((ReferenceBinding) rightArray.leafComponentType).compoundName;
+ } else {
+ if (right.isBaseType())
+ return false;
+ rightName = ((ReferenceBinding) right).compoundName;
+ }
+ //Check dimensions - Java does not support explicitly sized dimensions for types.
+ //However, if it did, the type checking support would go here.
+
+ if (CharOperation.equals(rightName, JAVA_LANG_OBJECT))
+ return true;
+ if (CharOperation.equals(rightName, JAVA_LANG_CLONEABLE))
+ return true;
+ if (CharOperation.equals(rightName, JAVA_IO_SERIALIZABLE))
+ 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[] 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$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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)
+*/
+
+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[] sourceName() {
+ return simpleName;
+}
+public String toString() {
+ return new String(constantPoolName) + " (id=" + id + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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$
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryField;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryMethod;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryNestedType;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+/*
+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;
+}
+
+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){
+ }
+ }
+
+ 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){
+ }
+ }
+ System.arraycopy(availableMethods, 0, availableMethods = new MethodBinding[count], 0, count);
+ return availableMethods;
+}
+
+void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
+ 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);
+ }
+ }
+
+ this.superInterfaces = NoSuperInterfaces;
+ char[][] interfaceNames = binaryType.getInterfaceNames();
+ if (interfaceNames != null) {
+ int size = interfaceNames.length;
+ if (size > 0) {
+ this.superInterfaces = new ReferenceBinding[size];
+ for (int i = 0; i < size; i++)
+ // attempt to find each superinterface if it exists in the cache (otherwise - resolve it when requested)
+ this.superInterfaces[i] = environment.getTypeFromConstantPoolName(interfaceNames[i], 0, -1);
+ }
+ }
+ if (needFieldsAndMethods){
+ createFields(binaryType.getFields());
+ createMethods(binaryType.getMethods());
+ }
+}
+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(),
+ this,
+ field.getConstant());
+ }
+ }
+ }
+}
+private MethodBinding createMethod(IBinaryMethod method) {
+ int modifiers = 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[] signature = method.getMethodDescriptor(); // of the form (I[Ljava/jang/String;)V
+ int numOfParams = 0;
+ char nextChar;
+ int index = 0; // first character is always '(' so skip it
+ while ((nextChar = signature[++index]) != ')') {
+ if (nextChar != '[') {
+ numOfParams++;
+ if (nextChar == 'L')
+ while ((nextChar = signature[++index]) != ';');
+ }
+ }
+
+ // 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 = signature[++end]) == '[');
+ if (nextChar == 'L')
+ while ((nextChar = signature[++end]) != ';');
+
+ if (i >= startIndex) // skip the synthetic arg if necessary
+ parameters[i - startIndex] = environment.getTypeFromSignature(signature, index, end);
+ index = end + 1;
+ }
+ }
+
+ MethodBinding binding = null;
+ if (method.isConstructor())
+ binding = new MethodBinding(modifiers, parameters, exceptions, this);
+ else
+ binding = new MethodBinding(
+ modifiers,
+ method.getSelector(),
+ environment.getTypeFromSignature(signature, index + 1, -1), // index is currently pointing at the ')'
+ parameters,
+ exceptions,
+ this);
+ return binding;
+}
+private void createMethods(IBinaryMethod[] iMethods) {
+ int total = 0;
+ int clinitIndex = -1;
+ if (iMethods != null) {
+ total = iMethods.length;
+ for (int i = total; --i >= 0;) {
+ char[] methodName = iMethods[i].getSelector();
+ if (methodName[0] == '<' && methodName.length == 8) { // Can only match <clinit>
+ total--;
+ clinitIndex = i;
+ break;
+ }
+ }
+ }
+ if (total == 0) {
+ this.methods = NoMethods;
+ return;
+ }
+
+ this.methods = new MethodBinding[total];
+ int next = 0;
+ for (int i = 0, length = iMethods.length; i < length; i++)
+ if (i != clinitIndex)
+ this.methods[next++] = 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.prefixEquals(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) {
+ int fieldLength = fieldName.length;
+ for (int f = fields.length; --f >= 0;) {
+ char[] name = fields[f].name;
+ if (name.length == fieldLength && CharOperation.prefixEquals(name, fieldName))
+ return resolveTypeFor(fields[f]);
+ }
+ return 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.prefixEquals(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.prefixEquals(method.selector, selector))
+ result[count++] = method;
+ }
+ return result;
+ }
+ return NoMethods;
+}
+// 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;
+}
+private 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) {
+ field.type = resolveType(field.type);
+ 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;
+}
+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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.codegen.CodeStream;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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 scope
+ public BlockScope[] shiftScopes;
+
+ public final static VariableBinding[] EmulationPathToImplicitThis = {};
+
+ public Scope[] subscopes = new Scope[1]; // need access from code assist
+ public int scopeIndex = 0; // need access from code assist
+
+ 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);
+ localTypeScope.buildLocalTypeBinding(enclosingSourceType());
+ addSubscope(localTypeScope);
+ }
+
+ /* 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 (scopeIndex == subscopes.length)
+ System.arraycopy(
+ subscopes,
+ 0,
+ (subscopes = new Scope[scopeIndex * 2]),
+ 0,
+ scopeIndex);
+ subscopes[scopeIndex++] = childScope;
+ }
+
+ /* Answer true if the receiver is suitable for assigning final blank fields.
+ *
+ * i.e. 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.
+ *
+ * Special treatment to have Try secret return address variables located at non
+ * colliding positions. Return addresses are not allocated initially, but gathered
+ * and allocated behind all other variables.
+ */
+ public void computeLocalVariablePositions(
+ int initOffset,
+ CodeStream codeStream) {
+
+ this.offset = initOffset;
+ this.maxOffset = initOffset;
+
+ // local variable init
+ int ilocal = 0, maxLocals = 0, localsLength = locals.length;
+ while ((maxLocals < localsLength) && (locals[maxLocals] != null))
+ maxLocals++;
+ boolean hasMoreVariables = maxLocals > 0;
+
+ // scope init
+ int iscope = 0, maxScopes = 0, subscopesLength = subscopes.length;
+ while ((maxScopes < subscopesLength) && (subscopes[maxScopes] != null))
+ maxScopes++;
+ 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(subOffset, codeStream);
+ if (subscope.maxOffset > this.maxOffset)
+ this.maxOffset = subscope.maxOffset;
+ }
+ hasMoreScopes = ++iscope < maxScopes;
+ } else {
+ // consider variable first
+ LocalVariableBinding local = locals[ilocal];
+
+ // check if variable is actually used, and may force it to be preserved
+ boolean generatesLocal =
+ (local.used && (local.constant == Constant.NotAConstant)) || local.isArgument;
+ if (!local.used
+ && (local.declaration != null) // unused (and non secret) local
+ && ((local.declaration.bits & AstNode.IsLocalDeclarationReachableMASK) != 0)) { // declaration is reachable
+ if (local.isArgument) // method argument
+ this.problemReporter().unusedArgument(local.declaration);
+ else if (!(local.declaration instanceof Argument)) // do not report unused catch arguments
+ this.problemReporter().unusedLocalVariable(local.declaration);
+ }
+ if (!generatesLocal) {
+ if (local.declaration != null
+ && environment().options.preserveAllLocalVariables) {
+ generatesLocal = true; // force it to be preserved in the generated code
+ local.used = true;
+ }
+ }
+ if (generatesLocal) {
+
+ if (local.declaration != null) {
+ codeStream.record(local);
+ // record user local variables for attribute generation
+ }
+ // allocate variable position
+ local.resolvedPosition = this.offset;
+
+ // check for too many arguments/local variables
+ if (local.isArgument) {
+ if (this.offset > 0xFF) { // no more than 255 words of arguments
+ this.problemReporter().noMoreAvailableSpaceForArgument(local, local.declaration);
+ }
+ } else {
+ if (this.offset > 0xFFFF) { // no more than 65535 words of locals
+ this.problemReporter().noMoreAvailableSpaceForLocal(
+ local, local.declaration == null ? (AstNode)this.methodScope().referenceContext : local.declaration);
+ }
+ }
+
+ // increment offset
+ if ((local.type == LongBinding) || (local.type == DoubleBinding)) {
+ this.offset += 2;
+ } else {
+ this.offset++;
+ }
+ } else {
+ local.resolvedPosition = -1; // not generated
+ }
+ hasMoreVariables = ++ilocal < maxLocals;
+ }
+ }
+ if (this.offset > this.maxOffset)
+ this.maxOffset = this.offset;
+ }
+
+ /* Answer true if the variable name already exists within the receiver's scope.
+ */
+ public final LocalVariableBinding duplicateName(char[] name) {
+ for (int i = 0; i < localIndex; i++)
+ if (CharOperation.equals(name, locals[i].name))
+ return locals[i];
+
+ if (this instanceof MethodScope)
+ return null;
+ else
+ return ((BlockScope) parent).duplicateName(name);
+ }
+
+ /*
+ * Record the suitable binding denoting a synthetic field or constructor argument,
+ * mapping to the actual outer local variable in the scope context.
+ * 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);
+ }
+ }
+ }
+
+ /*
+ * Record the suitable binding denoting a synthetic field or constructor argument,
+ * mapping to a given actual enclosing instance type in the scope context.
+ * Skip it if the enclosingType is actually the current scope's enclosing type.
+ */
+
+ public void emulateOuterAccess(
+ ReferenceBinding targetEnclosingType,
+ boolean useDirectReference) {
+
+ ReferenceBinding currentType = enclosingSourceType();
+ if (currentType.isNestedType()
+ && currentType != targetEnclosingType){
+ /*&& !targetEnclosingType.isSuperclassOf(currentType)*/
+
+ if (useDirectReference) {
+ // the target enclosing type is not in scope, we directly refer it
+ // must also add a synthetic field if we're not inside a constructor
+ NestedTypeBinding currentNestedType = (NestedTypeBinding) currentType;
+ if (methodScope().isInsideInitializerOrConstructor())
+ currentNestedType.addSyntheticArgument(targetEnclosingType);
+ else
+ currentNestedType.addSyntheticArgumentAndField(targetEnclosingType);
+
+ } else { // indirect reference sequence
+ int depth = 0;
+
+ // saturate all the way up until reaching compatible enclosing type
+ while (currentType.isLocalType()){
+ NestedTypeBinding currentNestedType = (NestedTypeBinding) currentType;
+ currentType = currentNestedType.enclosingType;
+
+ if (depth == 0){
+ if (methodScope().isInsideInitializerOrConstructor()) {
+ // must also add a synthetic field if we're not inside a constructor
+ currentNestedType.addSyntheticArgument(currentType);
+ } else {
+ currentNestedType.addSyntheticArgumentAndField(currentType);
+ }
+ } else if (currentNestedType == targetEnclosingType
+ || targetEnclosingType.isSuperclassOf(currentNestedType)) {
+ break;
+ } else {
+ currentNestedType.addSyntheticArgumentAndField(currentType);
+ }
+ depth++;
+ }
+ }
+ }
+ }
+
+ /* 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) {
+
+ for (int i = 0, length = scopeIndex; i < length; i++) {
+ if (subscopes[i] instanceof ClassScope) {
+ SourceTypeBinding sourceType =
+ ((ClassScope) subscopes[i]).referenceContext.binding;
+ if (CharOperation.equals(sourceType.sourceName(), name))
+ return sourceType;
+ }
+ }
+ return null;
+ }
+
+ public LocalVariableBinding findVariable(char[] variable) {
+
+ int variableLength = 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 == variableLength
+ && CharOperation.prefixEquals(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) {
+
+ Binding binding = getBinding(compoundName[0], mask | TYPE | PACKAGE, invocationSite);
+ 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);
+ else
+ 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),
+ 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 ((binding = findField(typeBinding, nextName, invocationSite)) != 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)
+ return new ProblemBinding(
+ 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);
+ 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);
+ else
+ 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),
+ 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)) != 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);
+ if (variableBinding == null)
+ return new ProblemFieldBinding(
+ null,
+ CharOperation.subarray(compoundName, 0, currentIndex),
+ NotFound);
+ if (!variableBinding.isValidBinding())
+ return variableBinding;
+ }
+ return variableBinding;
+ }
+
+ /* API
+ *
+ * Answer the binding that corresponds to the argument name.
+ * flag is a mask of the following values VARIABLE (= FIELD or LOCAL), TYPE, PACKAGE.
+ * Only bindings corresponding to the mask can be answered.
+ *
+ * For example, getBinding("foo", VARIABLE, site) will answer
+ * the binding for the field or local named "foo" (or an error binding if none exists).
+ * If a type named "foo" exists, it will not be detected (and an error binding will be answered)
+ *
+ * The VARIABLE mask has precedence over the TYPE mask.
+ *
+ * If the VARIABLE mask is not set, neither fields nor locals will be looked for.
+ *
+ * InvocationSite implements:
+ * isSuperAccess(); this is used to determine if the discovered field is visible.
+ *
+ * Limitations: cannot request FIELD independently of LOCAL, or vice versa
+ */
+ public Binding getBinding(char[] name, int mask, InvocationSite invocationSite) {
+
+ Binding binding = null;
+ FieldBinding problemField = null;
+ if ((mask & VARIABLE) != 0) {
+ if (this.kind == BLOCK_SCOPE || this.kind == METHOD_SCOPE) {
+ LocalVariableBinding variableBinding = findVariable(name);
+ // looks in this scope only
+ if (variableBinding != null) return variableBinding;
+ }
+
+ boolean insideStaticContext = false;
+ boolean insideConstructorCall = false;
+ if (this.kind == METHOD_SCOPE) {
+ MethodScope methodScope = (MethodScope) this;
+ insideStaticContext |= methodScope.isStatic;
+ insideConstructorCall |= methodScope.isConstructorCall;
+ }
+
+ FieldBinding foundField = null;
+ // can be a problem field which is answered if a valid field is not found
+ ProblemFieldBinding foundInsideProblem = null;
+ // inside Constructor call or inside static context
+ Scope scope = parent;
+ int depth = 0;
+ int foundDepth = 0;
+ ReferenceBinding foundActualReceiverType = null;
+ done : while (true) { // done when a COMPILATION_UNIT_SCOPE is found
+ switch (scope.kind) {
+ case METHOD_SCOPE :
+ MethodScope methodScope = (MethodScope) scope;
+ insideStaticContext |= methodScope.isStatic;
+ insideConstructorCall |= methodScope.isConstructorCall;
+ // Fall through... could duplicate the code below to save a cast - questionable optimization
+ case BLOCK_SCOPE :
+ LocalVariableBinding variableBinding = ((BlockScope) scope).findVariable(name);
+ // looks in this scope only
+ if (variableBinding != null) {
+ if (foundField != null && foundField.isValidBinding())
+ return new ProblemFieldBinding(
+ foundField.declaringClass,
+ name,
+ InheritedNameHidesEnclosingName);
+ if (depth > 0)
+ invocationSite.setDepth(depth);
+ return variableBinding;
+ }
+ break;
+ case CLASS_SCOPE :
+ ClassScope classScope = (ClassScope) scope;
+ SourceTypeBinding enclosingType = classScope.referenceContext.binding;
+ FieldBinding fieldBinding =
+ classScope.findField(enclosingType, name, invocationSite);
+ // Use next line instead if willing to enable protected access accross inner types
+ // FieldBinding fieldBinding = findField(enclosingType, name, invocationSite);
+ if (fieldBinding != null) { // skip it if we did not find anything
+ if (fieldBinding.problemId() == Ambiguous) {
+ if (foundField == null || foundField.problemId() == NotVisible)
+ // supercedes any potential InheritedNameHidesEnclosingName problem
+ return fieldBinding;
+ else
+ // make the user qualify the field, likely wants the first inherited field (javac generates an ambiguous error instead)
+ return new ProblemFieldBinding(
+ fieldBinding.declaringClass,
+ name,
+ InheritedNameHidesEnclosingName);
+ }
+
+ ProblemFieldBinding insideProblem = null;
+ if (fieldBinding.isValidBinding()) {
+ if (!fieldBinding.isStatic()) {
+ if (insideConstructorCall) {
+ insideProblem =
+ new ProblemFieldBinding(
+ fieldBinding.declaringClass,
+ name,
+ NonStaticReferenceInConstructorInvocation);
+ } else if (insideStaticContext) {
+ insideProblem =
+ new ProblemFieldBinding(
+ fieldBinding.declaringClass,
+ name,
+ NonStaticReferenceInStaticContext);
+ }
+ }
+ if (enclosingType == fieldBinding.declaringClass
+ || environment().options.complianceLevel >= CompilerOptions.JDK1_4){
+ // found a valid field in the 'immediate' scope (ie. not inherited)
+ // OR in 1.4 mode (inherited shadows enclosing)
+ if (foundField == null) {
+ if (depth > 0){
+ invocationSite.setDepth(depth);
+ invocationSite.setActualReceiverType(enclosingType);
+ }
+ // return the fieldBinding if it is not declared in a superclass of the scope's binding (i.e. "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 (ie. not inherited)
+ if (foundField.declaringClass != fieldBinding.declaringClass)
+ // ie. have we found the same field - do not trust field identity yet
+ return new ProblemFieldBinding(
+ fieldBinding.declaringClass,
+ name,
+ InheritedNameHidesEnclosingName);
+ }
+ }
+
+ if (foundField == null
+ || (foundField.problemId() == NotVisible
+ && fieldBinding.problemId() != NotVisible)) {
+ // only remember the fieldBinding if its the first one found or the previous one was not visible & fieldBinding is...
+ foundDepth = depth;
+ foundActualReceiverType = enclosingType;
+ foundInsideProblem = insideProblem;
+ foundField = fieldBinding;
+ }
+ }
+ depth++;
+ insideStaticContext |= enclosingType.isStatic();
+ // 1EX5I8Z - accessing outer fields within a constructor call is permitted
+ // in order to do so, we change the flag as we exit from the type, not the method
+ // itself, because the class scope is used to retrieve the fields.
+ MethodScope enclosingMethodScope = scope.methodScope();
+ insideConstructorCall =
+ enclosingMethodScope == null ? false : enclosingMethodScope.isConstructorCall;
+ break;
+ case COMPILATION_UNIT_SCOPE :
+ break done;
+ }
+ scope = scope.parent;
+ }
+
+ if (foundInsideProblem != null){
+ return foundInsideProblem;
+ }
+ if (foundField != null) {
+ if (foundField.isValidBinding()){
+ if (foundDepth > 0){
+ invocationSite.setDepth(foundDepth);
+ invocationSite.setActualReceiverType(foundActualReceiverType);
+ }
+ return foundField;
+ }
+ problemField = foundField;
+ }
+ }
+
+ // We did not find a local or instance variable.
+ if ((mask & TYPE) != 0) {
+ if ((binding = getBaseType(name)) != null)
+ return binding;
+ binding = getTypeOrPackage(name, (mask & PACKAGE) == 0 ? TYPE : TYPE | PACKAGE);
+ if (binding.isValidBinding() || mask == TYPE)
+ return binding;
+ // answer the problem type binding if we are only looking for a type
+ } else if ((mask & PACKAGE) != 0) {
+ compilationUnitScope().recordSimpleReference(name);
+ if ((binding = environment().getTopLevelPackage(name)) != null)
+ return binding;
+ }
+ if (problemField != null)
+ return problemField;
+ else
+ return new ProblemBinding(name, enclosingSourceType(), NotFound);
+ }
+
+ /*
+ * This retrieves the argument that maps to an enclosing instance of the suitable type,
+ * if not found then answers nil -- do not create one
+ *
+ * #implicitThis : the implicit this will be ok
+ * #((arg) this$n) : available as a constructor arg
+ * #((arg) this$n access$m... access$p) : available as as a constructor arg + a sequence of synthetic accessors to synthetic fields
+ * #((fieldDescr) this$n access#m... access$p) : available as a first synthetic field + a sequence of synthetic accessors to synthetic fields
+ * nil : not found
+ *
+ */
+ public Object[] getCompatibleEmulationPath(ReferenceBinding targetEnclosingType) {
+
+ MethodScope currentMethodScope = this.methodScope();
+ SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
+
+ // identity check
+ if (!currentMethodScope.isStatic
+ && !currentMethodScope.isConstructorCall
+ && (sourceType == targetEnclosingType
+ || targetEnclosingType.isSuperclassOf(sourceType))) {
+ return EmulationPathToImplicitThis; // implicit this is good enough
+ }
+ if (!sourceType.isNestedType()
+ || sourceType.isStatic()) { // no emulation from within non-inner types
+ return null;
+ }
+ boolean insideConstructor =
+ currentMethodScope.isInsideInitializerOrConstructor();
+ // use synthetic constructor arguments if possible
+ if (insideConstructor) {
+ SyntheticArgumentBinding syntheticArg;
+ if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, this, false)) != null) {
+ return new Object[] { syntheticArg };
+ }
+ }
+
+ // use a direct synthetic field then
+ if (!currentMethodScope.isStatic) {
+ FieldBinding syntheticField;
+ if ((syntheticField = sourceType.getSyntheticField(targetEnclosingType, this, false)) != null) {
+ 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((SourceTypeBinding) currentType, this, false);
+ } else {
+ path[0] =
+ sourceType.getSyntheticField((SourceTypeBinding) currentType, this, false);
+ }
+ if (path[0] != null) { // keep accumulating
+ int count = 1;
+ ReferenceBinding currentEnclosingType;
+ while ((currentEnclosingType = currentType.enclosingType()) != null) {
+ //done?
+ if (currentType == targetEnclosingType
+ || targetEnclosingType.isSuperclassOf(currentType))
+ break;
+ syntheticField = ((NestedTypeBinding) currentType).getSyntheticField((SourceTypeBinding) currentEnclosingType, this, false);
+ 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
+ || targetEnclosingType.isSuperclassOf(currentType)) {
+ return path;
+ }
+ }
+ }
+ return null;
+ }
+
+ /* API
+ *
+ * Answer the constructor binding that corresponds to receiverType, argumentTypes.
+ *
+ * InvocationSite implements
+ * isSuperAccess(); this is used to determine if the discovered constructor is visible.
+ *
+ * If no visible constructor is discovered, an error binding is answered.
+ */
+ public MethodBinding getConstructor(
+ ReferenceBinding receiverType,
+ TypeBinding[] argumentTypes,
+ InvocationSite invocationSite) {
+
+ compilationUnitScope().recordTypeReference(receiverType);
+ compilationUnitScope().recordTypeReferences(argumentTypes);
+ MethodBinding methodBinding = receiverType.getExactConstructor(argumentTypes);
+ if (methodBinding != null)
+ if (methodBinding.canBeSeenBy(invocationSite, this))
+ return methodBinding;
+
+ MethodBinding[] methods =
+ receiverType.getMethods(ConstructorDeclaration.ConstantPoolName);
+ if (methods == NoMethods)
+ return new ProblemMethodBinding(
+ ConstructorDeclaration.ConstantPoolName,
+ argumentTypes,
+ NotFound);
+
+ MethodBinding[] compatible = new MethodBinding[methods.length];
+ int compatibleIndex = 0;
+ for (int i = 0, length = methods.length; i < length; i++)
+ if (areParametersAssignable(methods[i].parameters, argumentTypes))
+ compatible[compatibleIndex++] = methods[i];
+ if (compatibleIndex == 0)
+ return new ProblemMethodBinding(
+ ConstructorDeclaration.ConstantPoolName,
+ argumentTypes,
+ NotFound);
+ // need a more descriptive error... cannot convert from X to Y
+
+ MethodBinding[] visible = new MethodBinding[compatibleIndex];
+ int visibleIndex = 0;
+ for (int i = 0; i < compatibleIndex; i++) {
+ MethodBinding method = compatible[i];
+ if (method.canBeSeenBy(invocationSite, this))
+ visible[visibleIndex++] = method;
+ }
+ if (visibleIndex == 1)
+ return visible[0];
+ if (visibleIndex == 0)
+ return new ProblemMethodBinding(
+ ConstructorDeclaration.ConstantPoolName,
+ argumentTypes,
+ NotVisible);
+ return mostSpecificClassMethodBinding(visible, visibleIndex);
+ }
+
+ /*
+ * This retrieves the argument that maps to an enclosing instance of the suitable type,
+ * if not found then answers nil -- do not create one
+ *
+ * #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
+ * nil : not found
+ *
+ * EXACT MATCH VERSION - no type compatibility is performed
+ */
+ public Object[] getExactEmulationPath(ReferenceBinding targetEnclosingType) {
+
+ MethodScope currentMethodScope = this.methodScope();
+ SourceTypeBinding sourceType = currentMethodScope.enclosingSourceType();
+
+ // identity check
+ if (!currentMethodScope.isStatic
+ && !currentMethodScope.isConstructorCall
+ && (sourceType == targetEnclosingType)) {
+ return EmulationPathToImplicitThis; // implicit this is good enough
+ }
+ if (!sourceType.isNestedType()
+ || sourceType.isStatic()) { // no emulation from within non-inner types
+ return null;
+ }
+
+ boolean insideConstructor =
+ currentMethodScope.isInsideInitializerOrConstructor();
+ // use synthetic constructor arguments if possible
+ if (insideConstructor) {
+ SyntheticArgumentBinding syntheticArg;
+ if ((syntheticArg = ((NestedTypeBinding) sourceType).getSyntheticArgument(targetEnclosingType, this, true)) != null) {
+ return new Object[] { syntheticArg };
+ }
+ }
+ // use a direct synthetic field then
+ if (!currentMethodScope.isStatic) {
+ FieldBinding syntheticField;
+ if ((syntheticField = sourceType.getSyntheticField(targetEnclosingType, this, true)) != null) {
+ 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((SourceTypeBinding) currentType, this, true);
+ } else {
+ path[0] =
+ sourceType.getSyntheticField((SourceTypeBinding) currentType, this, true);
+ }
+ if (path[0] != null) { // keep accumulating
+ int count = 1;
+ ReferenceBinding currentEnclosingType;
+ while ((currentEnclosingType = currentType.enclosingType()) != null) {
+ //done?
+ if (currentType == targetEnclosingType)
+ break;
+ syntheticField =
+ ((NestedTypeBinding) currentType).getSyntheticField(
+ (SourceTypeBinding) currentEnclosingType,
+ this,
+ true);
+ 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) {
+ return path;
+ }
+ }
+ }
+ return null;
+ }
+
+ /* API
+ *
+ * Answer the field binding that corresponds to fieldName.
+ * Start the lookup at the receiverType.
+ * InvocationSite implements
+ * isSuperAccess(); this is used to determine if the discovered field is visible.
+ * Only fields defined by the receiverType or its supertypes are answered;
+ * a field of an enclosing type will not be found using this API.
+ *
+ * If no visible field is discovered, an error binding is answered.
+ */
+ public FieldBinding getField(
+ TypeBinding receiverType,
+ char[] fieldName,
+ InvocationSite invocationSite) {
+
+ FieldBinding field = findField(receiverType, fieldName, invocationSite);
+ if (field == null)
+ return new ProblemFieldBinding(
+ receiverType instanceof ReferenceBinding
+ ? (ReferenceBinding) receiverType
+ : null,
+ fieldName,
+ NotFound);
+ else
+ return field;
+ }
+
+ /* API
+ *
+ * Answer the method binding that corresponds to selector, argumentTypes.
+ * Start the lookup at the enclosing type of the receiver.
+ * InvocationSite implements
+ * 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;
+ else
+ // make the user qualify the method, likely wants the first inherited method (javac generates an ambiguous error instead)
+ return new ProblemMethodBinding(
+ 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, argumentTypes, 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(
+ selector,
+ argumentTypes,
+ methodBinding.declaringClass,
+ NotVisible);
+ }
+ }
+ if (fuzzyProblem == null && !methodBinding.isStatic()) {
+ if (insideConstructorCall) {
+ insideProblem =
+ new ProblemMethodBinding(
+ methodBinding.selector,
+ methodBinding.parameters,
+ NonStaticReferenceInConstructorInvocation);
+ } else if (insideStaticContext) {
+ insideProblem =
+ new ProblemMethodBinding(
+ methodBinding.selector,
+ methodBinding.parameters,
+ NonStaticReferenceInStaticContext);
+ }
+ }
+
+ if (receiverType == methodBinding.declaringClass
+ || (receiverType.getMethods(selector)) != NoMethods
+ || ((fuzzyProblem == null || fuzzyProblem.problemId() != NotVisible) && environment().options.complianceLevel >= CompilerOptions.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 (i.e. "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 (ie. not inherited)
+ // NOTE: Unlike fields, a non visible method hides a visible method
+ if (foundMethod.declaringClass != methodBinding.declaringClass)
+ // ie. have we found the same method - do not trust field identity yet
+ return new ProblemMethodBinding(
+ methodBinding.selector,
+ methodBinding.parameters,
+ InheritedNameHidesEnclosingName);
+ }
+ }
+
+ 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);
+ }
+
+ /* API
+ *
+ * Answer the method binding that corresponds to selector, argumentTypes.
+ * Start the lookup at the receiverType.
+ * InvocationSite implements
+ * isSuperAccess(); this is used to determine if the discovered method is visible.
+ *
+ * Only methods defined by the receiverType or its supertypes are answered;
+ * use getImplicitMethod() to discover methods of enclosing types.
+ *
+ * If no visible method is discovered, an error binding is answered.
+ */
+ public MethodBinding getMethod(
+ TypeBinding receiverType,
+ char[] selector,
+ TypeBinding[] argumentTypes,
+ InvocationSite invocationSite) {
+
+ if (receiverType.isArrayType())
+ return findMethodForArray(
+ (ArrayBinding) receiverType,
+ selector,
+ argumentTypes,
+ invocationSite);
+ if (receiverType.isBaseType())
+ return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+
+ ReferenceBinding currentType = (ReferenceBinding) receiverType;
+ if (!currentType.canBeSeenBy(this))
+ return new ProblemMethodBinding(selector, argumentTypes, NotVisible);
+ // *** Need a new problem id - TypeNotVisible?
+
+ // 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(
+ selector,
+ argumentTypes,
+ methodBinding.declaringClass,
+ NotVisible);
+ }
+ return methodBinding;
+ }
+
+ 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,
+ boolean useDirectReference) {
+
+ // perform some emulation work in case there is some and we are inside a local type only
+ // propage emulation of the enclosing instances
+ ReferenceBinding[] syntheticArgumentTypes;
+ if ((syntheticArgumentTypes = targetType.syntheticEnclosingInstanceTypes())
+ != null) {
+ for (int i = 0, max = syntheticArgumentTypes.length; i < max; i++) {
+ ReferenceBinding syntheticArgType = syntheticArgumentTypes[i];
+ // need to filter out the one that could match a supplied enclosing instance
+ if (!(isEnclosingInstanceSupplied
+ && (syntheticArgType == targetType.enclosingType()))) {
+ this.emulateOuterAccess(syntheticArgType, useDirectReference);
+ }
+ }
+ }
+ 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.
+ *
+ * i.e. the nearest enclosing type of this scope.
+ */
+ public TypeDeclaration referenceType() {
+
+ return methodScope().referenceType();
+ }
+
+ // 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 < scopeIndex; i++)
+ if (subscopes[i] instanceof BlockScope)
+ s += ((BlockScope) subscopes[i]).toString(tab + 1) + "\n"; //$NON-NLS-1$
+ return s;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Clinit;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
+
+public class ClassScope extends Scope {
+ public TypeDeclaration referenceContext;
+
+ 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 = TypeBinding.NoSuperInterfaces;
+ }
+ connectMemberTypes();
+ buildFieldsAndMethods();
+ anonymousType.faultInTypesForFieldsAndMethods();
+ sourceType.verifyMethods(environment().methodVerifier());
+ }
+
+ private void buildFields() {
+ if (referenceContext.fields == null) {
+ 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++;
+
+ // 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, 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 (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);
+ 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.isDeprecated())
+ modifiers |= AccDeprecatedImplicitly;
+ if (enclosingType.isInterface())
+ modifiers |= AccPublic;
+ } else if (sourceType.isLocalType()) {
+ if (sourceType.isAnonymousType())
+ modifiers |= AccFinal;
+ ReferenceContext refContext = methodScope().referenceContext;
+ if (refContext instanceof TypeDeclaration) {
+ ReferenceBinding type = ((TypeDeclaration) refContext).binding;
+ if (type.isStrictfp())
+ modifiers |= AccStrictfp;
+ if (type.isDeprecated())
+ modifiers |= AccDeprecatedImplicitly;
+ } else {
+ MethodBinding method = ((AbstractMethodDeclaration) refContext).binding;
+ if (method != null){
+ if (method.isStrictfp())
+ modifiers |= AccStrictfp;
+ if (method.isDeprecated())
+ modifiers |= AccDeprecatedImplicitly;
+ }
+ }
+ }
+ // 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);
+
+ 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.memberTypes() != NoMemberTypes)
+ 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 (referenceContext.superclass == null) {
+ if (isJavaLangObject(sourceType))
+ return true;
+ sourceType.superclass = getJavaLangObject();
+ return !detectCycle(sourceType, sourceType.superclass, null);
+ // ensure Object is initialized if it comes from a source file
+ }
+ ReferenceBinding superclass = findSupertype(referenceContext.superclass);
+ if (superclass != null) { // is null if a cycle was detected cycle
+ 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 if (isJavaLangObject(sourceType)) {
+ // can only happen if Object extends another type... will never happen unless we're testing for it.
+ sourceType.tagBits |= HierarchyHasProblems;
+ sourceType.superclass = null;
+ return true;
+ } else {
+ // only want to reach here when no errors are reported
+ referenceContext.superclass.binding = superclass;
+ sourceType.superclass = superclass;
+ return true;
+ }
+ }
+ sourceType.tagBits |= HierarchyHasProblems;
+ if (!isJavaLangObject(sourceType)) {
+ sourceType.superclass = getJavaLangObject();
+ if ((sourceType.superclass.tagBits & BeginHierarchyCheck) == 0)
+ detectCycle(sourceType, sourceType.superclass, null);
+ // ensure Object is initialized if it comes from a source file
+ }
+ 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;
+
+ 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;
+ }
+ 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;
+ }
+ referenceContext.superInterfaces[i].binding = superInterface;
+ // 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();
+ checkForInheritedMemberTypes(sourceType);
+ }
+
+ 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) {
+ 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;
+ }
+
+ /* 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;
+ } else {
+ return outerMethodScope.problemReporter();
+ }
+ }
+
+ /* Answer the reference type of this scope.
+ *
+ * i.e. 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();
+ else
+ return "--- Class Scope ---\n\n Binding not initialized" ; //$NON-NLS-1$
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.CompoundNameVector;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfType;
+import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
+import net.sourceforge.phpdt.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 SourceTypeBinding[] topLevelTypes;
+
+ private CompoundNameVector qualifiedReferences;
+ private SimpleNameVector simpleNameReferences;
+ private ObjectVector referencedTypes;
+
+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 ? NoCharChar : 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)) {
+ problemReporter().packageIsNotExpectedPackage(referenceContext);
+ currentPackageName = expectedPackageName.length == 0 ? NoCharChar : expectedPackageName;
+ }
+ }
+ if (currentPackageName == NoCharChar) {
+ 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;
+ }
+ boolean packageExists = currentPackageName == NoCharChar
+ ? environment.getTopLevelPackage(typeDecl.name) != null
+ : (fPackage.getPackage(typeDecl.name)) != null;
+ if (packageExists) {
+ // 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);
+ topLevelTypes[count++] = child.buildType(null, fPackage);
+ }
+
+ // 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() {
+ // initialize the default imports if necessary... share the default java.lang.* import
+ if (environment.defaultImports == null) {
+ Binding importBinding = environment.getTopLevelPackage(JAVA);
+ if (importBinding != null)
+ importBinding = ((PackageBinding) importBinding).getTypeOrPackage(JAVA_LANG[1]);
+
+ // abort if java.lang cannot be found...
+ if (importBinding == null || !importBinding.isValidBinding())
+ problemReporter().isClassPathCorrect(JAVA_LANG_OBJECT, referenceCompilationUnit());
+
+ environment.defaultImports = new ImportBinding[] {new ImportBinding(JAVA_LANG, true, importBinding, null)};
+ }
+ if (referenceContext.imports == null) {
+ imports = environment.defaultImports;
+ 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] = environment.defaultImports[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;
+}
+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] = environment.defaultImports[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()) {
+ 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;
+ }
+ 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;
+}
+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 >= CompilerOptions.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++) {
+ // 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 >= CompilerOptions.JDK1_4)
+ return new ProblemReferenceBinding(compoundName, NotFound);
+ ReferenceBinding typeBinding = findType(compoundName[0], environment.defaultPackage, fPackage);
+ if (typeBinding == null)
+ return new ProblemReferenceBinding(compoundName, NotFound);
+ else
+ return typeBinding;
+ }
+ return findOnDemandImport(compoundName);
+}
+/* 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() && !referencedTypes.containsIdentical(type))
+ 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);
+}
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.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;
+ final int AccThrowsExceptions = 0x20000;
+ final int AccProblem = 0x40000;
+ final int AccFromClassFile = 0x80000;
+ final int AccIsConstantValue = 0x80000;
+ final int AccDefaultAbstract = 0x80000;
+ final int AccDeprecatedImplicitly = 0x200000; // ie. is deprecated itself or contained by a deprecated type
+ final int AccAlternateModifierProblem = 0x400000;
+ final int AccModifierProblem = 0x800000;
+ final int AccSemicolonBody = 0x1000000;
+ final int AccUnresolved = 0x2000000;
+ final int AccClearPrivateModifier = 0x4000000; // might be requested during private access emulation
+ final int AccVisibilityMASK = AccPublic | AccProtected | AccPrivate;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+
+public class FieldBinding extends VariableBinding {
+ public ReferenceBinding declaringClass;
+protected FieldBinding() {
+}
+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, ReferenceBinding declaringClass) {
+ this(field.name, type, field.modifiers, declaringClass, null);
+
+ field.binding = this;
+}
+// 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()){
+ 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;
+}
+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 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+public class InnerEmulationDependency{
+ public BlockScope scope;
+ public boolean wasEnclosingInstanceSupplied;
+ public boolean useDirectAccess;
+
+public InnerEmulationDependency(BlockScope scope, boolean wasEnclosingInstanceSupplied, boolean useDirectAccess) {
+ this.scope = scope;
+ this.wasEnclosingInstanceSupplied = wasEnclosingInstanceSupplied;
+ this.useDirectAccess = useDirectAccess;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+public final class LocalTypeBinding extends NestedTypeBinding {
+ final static char[] LocalTypePrefix = { '$', 'L', 'o', 'c', 'a', 'l', '$' };
+
+ private InnerEmulationDependency[] dependents;
+public LocalTypeBinding(ClassScope scope, SourceTypeBinding enclosingType) {
+ super(
+ new char[][] {CharOperation.concat(LocalTypePrefix, scope.referenceContext.name)},
+ scope,
+ enclosingType);
+
+ if (this.sourceName == AnonymousLocalTypeDeclaration.ANONYMOUS_EMPTY_NAME)
+ this.tagBits |= AnonymousTypeMask;
+ else
+ this.tagBits |= LocalTypeMask;
+}
+/* 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 scope, boolean wasEnclosingInstanceSupplied, boolean useDirectAccess) {
+ 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 == scope)
+ return; // already stored
+ System.arraycopy(dependents, 0, (dependents = new InnerEmulationDependency[index + 1]), 0, index);
+ }
+ dependents[index] = new InnerEmulationDependency(scope, wasEnclosingInstanceSupplied, useDirectAccess);
+ // 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;
+}
+public void constantPoolName(char[] computedConstantPoolName) /* java/lang/Object */ {
+ this.constantPoolName = computedConstantPoolName;
+}
+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;
+ }
+}
+// Record that the type is a local member type
+
+public void setAsMemberType() {
+ tagBits |= MemberTypeMask;
+}
+public char[] sourceName() {
+ if (isAnonymousType())
+ return readableName();
+ 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, dependency.useDirectAccess);
+ }
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+
+public class LocalVariableBinding extends VariableBinding {
+ public boolean isArgument;
+
+ public int resolvedPosition; // for code generation (position in method context)
+ public boolean used; // for flow analysis
+ 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;
+ if (this.isArgument = 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();
+ if (!used)
+ s += "[pos: unused]"; //$NON-NLS-1$
+ else
+ s += "[pos: " + String.valueOf(resolvedPosition) + "]"; //$NON-NLS-2$ //$NON-NLS-1$
+ 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.env.IBinaryType;
+import net.sourceforge.phpdt.internal.compiler.env.INameEnvironment;
+import net.sourceforge.phpdt.internal.compiler.env.NameEnvironmentAnswer;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.impl.ITypeRequestor;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfPackage;
+import net.sourceforge.phpdt.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(new char[0], NotFound);
+ static final ProblemReferenceBinding theNotFoundType = new ProblemReferenceBinding(new char[0], NotFound);
+
+ private INameEnvironment nameEnvironment;
+ private MethodVerifier verifier;
+ private ArrayBinding[][] uniqueArrayBindings;
+
+ private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4];
+ private int lastUnitIndex = -1;
+ private int lastCompletedUnitIndex = -1;
+
+ // indicate in which step on the compilation we are.
+ // step 1 : build the reference binding
+ // step 2 : conect the hierarchy (connect bindings)
+ // step 3 : build fields and method bindings.
+ private int stepCompleted;
+ final static int BUILD_TYPE_HIERARCHY = 1;
+ final static int CHECK_AND_SET_IMPORTS = 2;
+ final static int CONNECT_TYPE_HIERARCHY = 3;
+ final static int BUILD_FIELDS_AND_METHODS = 4;
+public 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 = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
+ units[i].scope.checkAndSetImports();
+ }
+ stepCompleted = CHECK_AND_SET_IMPORTS;
+
+ for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
+ units[i].scope.connectTypeHierarchy();
+ }
+ stepCompleted = CONNECT_TYPE_HIERARCHY;
+
+ for (int i = lastCompletedUnitIndex + 1; i <= lastUnitIndex; i++) {
+ units[i].scope.buildFieldsAndMethods();
+ units[i] = null; // release unnecessary reference to the parsed unit
+ }
+ stepCompleted = BUILD_FIELDS_AND_METHODS;
+ lastCompletedUnitIndex = lastUnitIndex;
+}
+/*
+* 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)
+ parsedUnit.scope.checkAndSetImports();
+
+ if (stepCompleted >= CONNECT_TYPE_HIERARCHY)
+ parsedUnit.scope.connectTypeHierarchy();
+ }
+}
+/*
+* 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
+
+ parsedUnit.scope.checkAndSetImports();
+ parsedUnit.scope.connectTypeHierarchy();
+
+ if (buildFieldsAndMethods)
+ parsedUnit.scope.buildFieldsAndMethods();
+}
+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) {
+ // 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;
+ else
+ 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 (i.e. package1.A$B)
+ if (referenceBinding.isNestedType())
+ return new ProblemReferenceBinding(compoundName, InternalNameProvided);
+ else
+ 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 - 1;
+
+ 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 - 1);
+ }
+
+ if (dimension == 0)
+ return binding;
+ else
+ 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);
+ else
+ 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;
+
+ // 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;
+ }
+ }
+ }
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.util.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$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.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() {
+}
+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()){
+ 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 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 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 a native method
+*/
+
+public final boolean isNative() {
+ return (modifiers & AccNative) != 0;
+}
+/* Answer true if the receiver has private visibility
+*/
+
+public final boolean isPrivate() {
+ return (modifiers & AccPrivate) != 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'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();
+}
+protected final void selector(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('(');
+ if (isConstructorRelated() && declaringClass.isNestedType()) {
+ // 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());
+ SyntheticArgumentBinding[] syntheticArguments = declaringClass.syntheticOuterLocalVariables();
+ count = syntheticArguments == null ? 0 : syntheticArguments.length;
+ for (int i = 0; i < count; i++)
+ buffer.append(syntheticArguments[i].type.signature());
+ }
+ if (parameters != NoParameters)
+ for (int i = 0, length = parameters.length; i < length; 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;
+ else
+ 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;
+ else
+ 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleNameReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
+import net.sourceforge.phpdt.internal.compiler.flow.UnconditionalFlowInfo;
+import net.sourceforge.phpdt.internal.compiler.impl.ReferenceContext;
+import net.sourceforge.phpdt.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 needToCompactLocalVariables;
+ public boolean isStatic; // method modifier or initializer one
+
+ //fields used in the TC process (no real meaning)
+ public static final int NotInFieldDecl = -1; //must be a negative value
+ public boolean isConstructorCall = false; //modified on the fly by the TC
+ public int fieldDeclarationIndex = NotInFieldDecl;
+ //modified on the fly by the TC
+
+ 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][];
+
+ 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;
+ }
+
+ /* 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()) {
+ 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) {
+
+ FieldBinding field = super.findField(receiverType, fieldName, invocationSite);
+ 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.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.declaringClass,
+ fieldName,
+ NonStaticReferenceInConstructorInvocation);
+ }
+ return field;
+ }
+
+ 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;
+ } else {
+ return outerMethodScope.problemReporter();
+ }
+ }
+
+ public final int recordInitializationStates(FlowInfo flowInfo) {
+
+ if ((flowInfo == FlowInfo.DeadEnd) || (flowInfo.isFakeReachable())) {
+ 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 type of this scope.
+ *
+ * i.e. the nearest enclosing type of this scope.
+ */
+ public TypeDeclaration referenceType() {
+
+ return (TypeDeclaration) ((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 + "fieldDeclarationIndex = " + fieldDeclarationIndex; //$NON-NLS-1$
+ return s;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfObject;
+
+public final class MethodVerifier implements TagBits, TypeConstants {
+ SourceTypeBinding type;
+ HashtableOfObject inheritedMethods;
+ HashtableOfObject currentMethods;
+ ReferenceBinding runtimeException;
+ ReferenceBinding errorException;
+/*
+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)
+
+verifyTypeStructure
+
+ | hasHierarchyProblem superclass current names interfaces interfacesByIndentity duplicateExists invalidType |
+
+ (type basicModifiers anyMask: AccModifierProblem | AccAlternateModifierProblem) ifTrue: [
+ self reportModifierProblemsOnType: type].
+
+ type controller isJavaDefaultPackage ifFalse: [
+ (nameEnvironment class doesPackageExistNamed: type javaQualifiedName) ifTrue: [
+ problemSummary
+ reportVerificationProblem: #CollidesWithPackage
+ args: (Array with: type javaQualifiedName)
+ severity: nil
+ forType: type]].
+
+ hasHierarchyProblem := false.
+
+ type isJavaClass
+ ifTrue: [
+ (superclass := self superclassFor: type) ~~ nil ifTrue: [
+ superclass isBuilderClass ifTrue: [
+ superclass := superclass newClass].
+ superclass isJavaMissing
+ ifTrue: [
+ hasHierarchyProblem := true.
+ type javaSuperclassIsMissing ifTrue: [
+ problemSummary
+ reportVerificationProblem: #MissingSuperclass
+ args: (Array with: superclass javaQualifiedName with: superclass unmatchedDescriptor)
+ severity: nil
+ forType: type].
+ type javaSuperclassCreatesCycle ifTrue: [
+ problemSummary
+ reportVerificationProblem: #CyclicSuperclass
+ args: (Array with: superclass javaQualifiedName)
+ severity: nil
+ forType: type].
+ type javaSuperclassIsInterface ifTrue: [
+ problemSummary
+ reportVerificationProblem: #ClassCannotExtendAnInterface
+ args: (Array with: superclass javaQualifiedName)
+ severity: nil
+ forType: type]]
+ ifFalse: [
+ "NOTE: If type is a Java class and its superclass is
+ a valid descriptor then it should NEVER be an interface."
+
+ superclass isJavaFinal ifTrue: [
+ problemSummary
+ reportVerificationProblem: #ClassCannotExtendFinalClass
+ args: nil
+ severity: nil
+ forType: type]]]]
+ ifFalse: [
+ type isJavaLocalType ifTrue: [
+ problemSummary
+ reportVerificationProblem: #CannotDefineLocalInterface
+ args: nil
+ severity: nil
+ forType: type]].
+
+ type isJavaNestedType ifTrue: [
+ (current := type) sourceName notEmpty ifTrue: [
+ names := Set new.
+ [(current := current enclosingType) ~~ nil] whileTrue: [
+ names add: current sourceName].
+
+ (names includes: type sourceName) ifTrue: [
+ problemSummary
+ reportVerificationProblem: #NestedTypeCannotShadowTypeName
+ args: nil
+ severity: nil
+ forType: type]].
+
+ (type enclosingType isJavaNestedType and: [type enclosingType isJavaClass]) ifTrue: [
+ type enclosingType isJavaStatic ifFalse: [
+ type isJavaClass
+ ifTrue: [
+ type isJavaStatic ifTrue: [
+ problemSummary
+ reportVerificationProblem: #StaticClassCannotExistInNestedClass
+ args: nil
+ severity: nil
+ forType: type]]
+ ifFalse: [
+ problemSummary
+ reportVerificationProblem: #InterfaceCannotExistInNestedClass
+ args: nil
+ severity: nil
+ forType: type]]]].
+
+ (interfaces := newClass superinterfaces) notEmpty ifTrue: [
+ interfacesByIndentity := interfaces asSet.
+ duplicateExists := interfaces size ~~ interfacesByIndentity size.
+
+ interfacesByIndentity do: [:interface |
+ duplicateExists ifTrue: [
+ (interfaces occurrencesOf: interface) > 1 ifTrue: [
+ problemSummary
+ reportVerificationProblem: #InterfaceIsSpecifiedMoreThanOnce
+ args: (Array with: interface javaQualifiedName)
+ severity: nil
+ forType: type]].
+
+ interface isJavaMissing ifTrue: [
+ hasHierarchyProblem := true.
+ interface basicClass == JavaInterfaceIsClass basicClass
+ ifTrue: [
+ problemSummary
+ reportVerificationProblem: #UsingClassWhereInterfaceIsRequired
+ args: (Array with: interface javaQualifiedName)
+ severity: nil
+ forType: type]
+ ifFalse: [
+ interface basicClass == JavaMissingInterface basicClass
+ ifTrue: [
+ problemSummary
+ reportVerificationProblem: #MissingInterface
+ args: (Array with: interface javaQualifiedName with: interface unmatchedDescriptor)
+ severity: nil
+ forType: type]
+ ifFalse: [
+ problemSummary
+ reportVerificationProblem: #CyclicSuperinterface
+ args: (Array with: interface javaQualifiedName)
+ severity: nil
+ forType: type]]]]].
+
+ hasHierarchyProblem ifFalse: [
+ "Search up the type's hierarchy for
+ 1. missing superclass,
+ 2. superclass cycle, or
+ 3. superclass is interface."
+ (invalidType := newClass findFirstInvalidSupertypeSkipping: EsIdentitySet new) ~~ nil ifTrue: [
+ problemSummary
+ reportVerificationProblem: #HasHierarchyProblem
+ args: (Array with: invalidType javaReadableName)
+ severity: nil
+ forType: type]]
+
+reportModifierProblemsOnType: aType
+
+ (type basicModifiers anyMask: AccAlternateModifierProblem) ifTrue: [
+ (type basicModifiers anyMask: AccModifierProblem)
+ ifTrue: [
+ ^problemSummary
+ reportVerificationProblem: #OnlyOneVisibilityModifierAllowed
+ args: nil
+ severity: nil
+ forType: aType]
+ ifFalse: [
+ ^problemSummary
+ reportVerificationProblem: #DuplicateModifier
+ args: nil
+ severity: nil
+ forType: aType]].
+
+ type isJavaInterface ifTrue: [
+ ^problemSummary
+ reportVerificationProblem: #IllegalModifierForInterface
+ args: nil
+ severity: nil
+ forType: aType].
+
+ (type basicModifiers allMask: AccAbstract | AccFinal) ifTrue: [
+ ^problemSummary
+ reportVerificationProblem: #IllegalModifierCombinationAbstractFinal
+ args: nil
+ severity: nil
+ forType: aType].
+
+ ^problemSummary
+ reportVerificationProblem: #IllegalModifierForClass
+ args: nil
+ severity: nil
+ forType: aType
+
+void reportModifierProblems() {
+ if (this.type.isAbstract() && this.type.isFinal())
+ this.problemReporter.illegalModifierCombinationAbstractFinal(this.type);
+
+ // Should be able to detect all 3 problems NOT just 1
+ if ((type.modifiers() & Modifiers.AccAlternateModifierProblem) == 0) {
+ if (this.type.isInterface())
+ this.problemReporter.illegalModifierForInterface(this.type);
+ else
+ this.problemReporter.illegalModifier(this.type);
+ } else {
+ if ((type.modifiers() & Modifiers.AccModifierProblem) != 0)
+ this.problemReporter.onlyOneVisibilityModifierAllowed(this.type);
+ else
+ this.problemReporter.duplicateModifier(this.type);
+ }
+}
+*/
+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;
+}
+private void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] methods, int length) {
+ for (int i = length; --i >= 0;) {
+ MethodBinding inheritedMethod = methods[i];
+ if (currentMethod.returnType != inheritedMethod.returnType) {
+ this.problemReporter(currentMethod).incompatibleReturnType(currentMethod, inheritedMethod);
+ } else if (currentMethod.isStatic() != inheritedMethod.isStatic()) { // Cannot override a static method or hide an instance method
+ this.problemReporter(currentMethod).staticAndInstanceConflict(currentMethod, inheritedMethod);
+ } 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 (inheritedMethod.isViewedAsDeprecated())
+ if (!currentMethod.isViewedAsDeprecated())
+ 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 = newMethod.thrownExceptions;
+ ReferenceBinding[] inheritedExceptions = inheritedMethod.thrownExceptions;
+ for (int i = newExceptions.length; --i >= 0;) {
+ ReferenceBinding newException = newExceptions[i];
+ int j = inheritedExceptions.length;
+ while (--j > -1 && !this.isSameClassOrSubclassOf(newException, inheritedExceptions[j]));
+ 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) {
+ TypeBinding returnType = methods[0].returnType;
+ int index = length;
+ while ((--index > 0) && (returnType == methods[index].returnType));
+ 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]))
+ return; // in this case, we have already reported problem against the concrete superclass
+
+ TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+ if (typeDeclaration != null) {
+ MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(methods[0]);
+ missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+ } else {
+ this.problemReporter().abstractMethodMustBeImplemented(this.type, methods[0]);
+ }
+ }
+ 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();
+ char[][] methodSelectors = this.inheritedMethods.keyTable;
+ for (int s = methodSelectors.length; --s >= 0;) {
+ if (methodSelectors[s] != null) {
+ MethodBinding[] current = (MethodBinding[]) this.currentMethods.get(methodSelectors[s]);
+ MethodBinding[] inherited = (MethodBinding[]) this.inheritedMethods.valueTable[s];
+
+ int index = -1;
+ MethodBinding[] matchingInherited = new MethodBinding[inherited.length];
+ if (current != null) {
+ for (int i = 0, length1 = current.length; i < length1; i++) {
+ while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
+ MethodBinding currentMethod = current[i];
+ for (int j = 0, length2 = inherited.length; j < length2; j++) {
+ if (inherited[j] != null && currentMethod.areParametersEqual(inherited[j])) {
+ matchingInherited[++index] = inherited[j];
+ inherited[j] = null; // do not want to find it again
+ }
+ }
+ if (index >= 0)
+ this.checkAgainstInheritedMethods(currentMethod, matchingInherited, index + 1); // pass in the length of matching
+ }
+ }
+ for (int i = 0, length = inherited.length; i < length; i++) {
+ while (index >= 0) matchingInherited[index--] = null; // clear the previous contents of the matching methods
+ if (inherited[i] != null) {
+ matchingInherited[++index] = inherited[i];
+ for (int j = i + 1; j < length; j++) {
+ if (inherited[j] != null && inherited[i].areParametersEqual(inherited[j])) {
+ matchingInherited[++index] = inherited[j];
+ inherited[j] = null; // do not want to find it again
+ }
+ }
+ }
+ if (index > 0) {
+ this.checkInheritedMethods(matchingInherited, index + 1); // pass in the length of matching
+ } else {
+ if (mustImplementAbstractMethods && index == 0 && matchingInherited[0].isAbstract())
+ if (mustImplementAbstractMethod(matchingInherited[0])) {
+ TypeDeclaration typeDeclaration = this.type.scope.referenceContext;
+ if (typeDeclaration != null) {
+ MethodDeclaration missingAbstractMethod = typeDeclaration.addMissingAbstractMethodFor(matchingInherited[0]);
+ missingAbstractMethod.scope.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
+ } else {
+ this.problemReporter().abstractMethodMustBeImplemented(this.type, matchingInherited[0]);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+/*
+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[5][];
+ int lastPosition = 0;
+ interfacesToVisit[lastPosition] = type.superInterfaces();
+
+ ReferenceBinding superType;
+ if (this.type.isClass()) {
+ superType = this.type.superclass();
+ } else { // check interface methods against Object
+ superType = this.type.scope.getJavaLangObject();
+ }
+ MethodBinding[] nonVisibleDefaultMethods = null;
+ int nonVisibleCount = 0;
+
+ while (superType != null) {
+ if (superType.isValidBinding()) {
+ 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;
+ }
+
+ MethodBinding[] methods = superType.methods();
+ nextMethod : for (int m = methods.length; --m >= 0;) {
+ MethodBinding method = methods[m];
+ if (!(method.isPrivate() || method.isConstructor() || method.isDefaultAbstract())) { // look at all methods which are NOT private or constructors or default abstract
+ MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
+ if (existingMethods != null)
+ for (int i = 0, length = existingMethods.length; i < length; i++)
+ if (method.returnType == existingMethods[i].returnType)
+ if (method.areParametersEqual(existingMethods[i]))
+ continue nextMethod;
+ if (nonVisibleDefaultMethods != null)
+ for (int i = 0; i < nonVisibleCount; i++)
+ if (method.returnType == nonVisibleDefaultMethods[i].returnType)
+ if (CharOperation.equals(method.selector, nonVisibleDefaultMethods[i].selector))
+ if (method.areParametersEqual(nonVisibleDefaultMethods[i]))
+ continue nextMethod;
+
+ if (!(method.isDefault() && (method.declaringClass.fPackage != type.fPackage))) { // ignore methods which have default visibility and are NOT defined in another package
+ if (existingMethods == null)
+ existingMethods = new MethodBinding[1];
+ else
+ System.arraycopy(existingMethods, 0,
+ (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
+ existingMethods[existingMethods.length - 1] = method;
+ this.inheritedMethods.put(method.selector, existingMethods);
+ } else {
+ if (nonVisibleDefaultMethods == null)
+ nonVisibleDefaultMethods = new MethodBinding[10];
+ else if (nonVisibleCount == nonVisibleDefaultMethods.length)
+ System.arraycopy(nonVisibleDefaultMethods, 0,
+ (nonVisibleDefaultMethods = new MethodBinding[nonVisibleCount * 2]), 0, nonVisibleCount);
+ nonVisibleDefaultMethods[nonVisibleCount++] = method;
+
+ if (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 (method.returnType == current[i].returnType) {
+ if (method.areParametersEqual(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, length = interfaces.length; j < length; j++) {
+ superType = interfaces[j];
+ if ((superType.tagBits & InterfaceVisited) == 0) {
+ superType.tagBits |= InterfaceVisited;
+ if (superType.isValidBinding()) {
+ 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;
+ }
+
+ MethodBinding[] methods = superType.methods();
+ for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public
+ MethodBinding method = methods[m];
+ MethodBinding[] existingMethods = (MethodBinding[]) this.inheritedMethods.get(method.selector);
+ if (existingMethods == null)
+ existingMethods = new MethodBinding[1];
+ else
+ System.arraycopy(existingMethods, 0,
+ (existingMethods = new MethodBinding[existingMethods.length + 1]), 0, existingMethods.length - 1);
+ existingMethods[existingMethods.length - 1] = method;
+ this.inheritedMethods.put(method.selector, existingMethods);
+ }
+ }
+ }
+ }
+ }
+
+ // 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;
+ }
+}
+/*
+computeInheritedMethodMembers
+
+ "8.4.6.4"
+ "Compute all of the members for the type that are inherited from its supertypes.
+ This includes:
+ All of the methods implemented in the supertype hierarchy that are not overridden.
+ PROBLEM: Currently we do not remove overridden methods in the interface hierarchy.
+ This could cause a non-existent exception error to be detected."
+
+ | supertype allSuperinterfaces methodsSeen interfacesSeen |
+ inheritedMethodMembers := LookupTable new: 50.
+ allSuperinterfaces := OrderedCollection new.
+
+ type isJavaClass ifTrue: [
+ supertype := type.
+ methodsSeen := EsIdentitySet new: 20.
+ [(supertype := self superclassFor: supertype) == nil] whileFalse: [
+ (supertype isBuilderClass or: [supertype isValidDescriptor]) ifTrue: [
+ allSuperinterfaces addAll: (self superinterfacesFor: supertype).
+ supertype javaUserDefinedMethodsDo: [:method |
+ (method isJavaPrivate or: [method isJavaConstructor]) ifFalse: [
+ (method isJavaDefault and: [method declaringClass package symbol ~= type package symbol]) ifFalse: [
+ (methodsSeen includes: method selector) ifFalse: [
+ methodsSeen add: method selector.
+ (inheritedMethodMembers
+ at: (self methodSignatureFor: method selector)
+ ifAbsentPut: [OrderedCollection new: 3])
+ add: method]]]]]]].
+
+ allSuperinterfaces addAll: (self superinterfacesFor: type).
+ interfacesSeen := EsIdentitySet new: allSuperinterfaces size * 2.
+ [allSuperinterfaces notEmpty] whileTrue: [
+ supertype := allSuperinterfaces removeFirst.
+ (interfacesSeen includes: supertype) ifFalse: [
+ interfacesSeen add: supertype.
+ (supertype isBuilderClass or: [supertype isValidDescriptor]) ifTrue: [
+ allSuperinterfaces addAll: (self superinterfacesFor: supertype).
+ supertype javaUserDefinedMethodsDo: [:method | "Interface methods are all abstract public."
+ (inheritedMethodMembers
+ at: (self methodSignatureFor: method selector)
+ ifAbsentPut: [OrderedCollection new: 3])
+ add: method]]]]
+*/
+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))
+ return !this.type.isAbstract();
+ 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;
+}
+private ReferenceBinding runtimeException() {
+ if (runtimeException == null)
+ this.runtimeException = this.type.scope.getJavaLangRuntimeException();
+ return runtimeException;
+}
+public void verify(SourceTypeBinding type) {
+ this.type = type;
+ this.computeMethods();
+ this.computeInheritedMethods();
+ this.checkMethods();
+}
+private void zzFieldProblems() {
+}
+/*
+Binding creation is responsible for reporting all problems with fields:
+ - all modifier problems (duplicates & multiple visibility modifiers + incompatible combinations - final/volatile)
+ - plus invalid modifiers given the context (the verifier did not do this before)
+ - include initializers in the modifier checks even though bindings are not created
+ - collisions... 2 fields with same name
+ - interfaces cannot define initializers
+ - nested types cannot define static fields
+ - with the type of the field:
+ - void is not a valid type (or for an array)
+ - an ambiguous, invisible or missing type
+
+verifyFields
+
+ | toSearch |
+ (toSearch := newClass fields) notEmpty ifTrue: [
+ newClass fromJavaClassFile
+ ifTrue: [
+ toSearch do: [:field |
+ field isJavaInitializer ifFalse: [
+ self verifyFieldType: field]]]
+ ifFalse: [
+ toSearch do: [:field |
+ field isJavaInitializer
+ ifTrue: [self verifyFieldInitializer: field]
+ ifFalse: [self verifyField: field]]]]
+
+verifyFieldInitializer: field
+
+ type isJavaInterface
+ ifTrue: [
+ problemSummary
+ reportVerificationProblem: #InterfacesCannotHaveInitializers
+ args: #()
+ severity: nil
+ forField: field]
+ ifFalse: [
+ field isJavaStatic
+ ifTrue: [
+ field modifiers == AccStatic ifFalse: [
+ problemSummary
+ reportVerificationProblem: #IllegalModifierForStaticInitializer
+ args: #()
+ severity: nil
+ forField: field]]
+ ifFalse: [
+ field modifiers == 0 ifFalse: [
+ problemSummary
+ reportVerificationProblem: #IllegalModifierForInitializer
+ args: #()
+ severity: nil
+ forField: field]]]
+
+verifyField: field
+
+ (field basicModifiers anyMask: AccAlternateModifierProblem | AccModifierProblem) ifTrue: [
+ self reportModifierProblemsOnField: field].
+
+ field isJavaStatic ifTrue: [
+ type isJavaStatic ifFalse: [
+ (type isJavaNestedType and: [type isJavaClass]) ifTrue: [
+ problemSummary
+ reportVerificationProblem: #NestedClassCannotHaveStaticField
+ args: #()
+ severity: nil
+ forField: field]]].
+
+ self verifyFieldType: field
+
+verifyFieldType: field
+
+ | descriptor fieldType |
+ "8.3 (Class) 9.3 (Interface)"
+ "Optimize the base type case"
+ field typeIsBaseType
+ ifTrue: [
+ field typeName = 'V' ifTrue: [ "$NON-NLS$"
+ problemSummary
+ reportVerificationProblem: #IllegalTypeForField
+ args: (Array with: JavaVoid)
+ severity: nil
+ forField: field]]
+ ifFalse: [
+ descriptor := field asDescriptorIn: nameEnvironment.
+ (fieldType := descriptor type) isValidDescriptor
+ ifTrue: [
+ (fieldType isArrayType and: [fieldType leafComponentType isVoidType]) ifTrue: [
+ problemSummary
+ reportVerificationProblem: #InvalidArrayType
+ args: (Array with: fieldType javaReadableName)
+ severity: nil
+ forField: field]]
+ ifFalse: [
+ problemSummary
+ reportVerificationProblem: #UnboundTypeForField
+ args: (Array with: fieldType javaReadableName with: fieldType leafComponentType)
+ severity: nil
+ forField: field]].
+
+reportModifierProblemsOnField: field
+
+ (field basicModifiers anyMask: AccAlternateModifierProblem) ifTrue: [
+ (field basicModifiers anyMask: AccModifierProblem)
+ ifTrue: [
+ ^problemSummary
+ reportVerificationProblem: #OnlyOneVisibilityModifierAllowed
+ args: #()
+ severity: ErrorInfo::ConflictingModifier
+ forField: field]
+ ifFalse: [
+ ^problemSummary
+ reportVerificationProblem: #DuplicateModifier
+ args: #()
+ severity: ErrorInfo::ConflictingModifier
+ forField: field]].
+
+ type isJavaInterface ifTrue: [
+ ^problemSummary
+ reportVerificationProblem: #IllegalModifierForInterfaceField
+ args: #()
+ severity: nil
+ forField: field].
+
+ (field basicModifiers allMask: AccFinal | AccVolatile) ifTrue: [
+ ^problemSummary
+ reportVerificationProblem: #IllegalModifierCombinationFinalVolatile
+ args: #()
+ severity: nil
+ forField: field].
+
+ ^problemSummary
+ reportVerificationProblem: #IllegalModifierForField
+ args: #()
+ severity: nil
+ forField: field
+
+void reportModifierProblems(FieldBinding field) {
+ if (field.isFinal() && field.isVolatile())
+ this.problemReporter.illegalModifierCombinationFinalVolatile(field);
+
+ // Should be able to detect all 3 problems NOT just 1
+ if ((type.modifiers() & Modifiers.AccAlternateModifierProblem) == 0) {
+ if (this.type.isInterface())
+ this.problemReporter.illegalModifierForInterfaceField(field);
+ else
+ this.problemReporter.illegalModifier(field);
+ } else {
+ if ((field.modifiers & Modifiers.AccModifierProblem) != 0)
+ this.problemReporter.onlyOneVisibilityModifierAllowed(field);
+ else
+ this.problemReporter.duplicateModifier(field);
+ }
+}
+*/
+private void zzImportProblems() {
+}
+/*
+Binding creation is responsible for reporting all problems with imports:
+ - on demand imports which refer to missing packages
+ - with single type imports:
+ - resolves to an ambiguous, invisible or missing type
+ - conflicts with the type's source name
+ - has the same simple name as another import
+
+Note: VAJ ignored duplicate imports (only one was kept)
+
+verifyImports
+
+ | importsBySimpleName nameEnvClass imports cl first |
+ importsBySimpleName := LookupTable new.
+ nameEnvClass := nameEnvironment class.
+
+ "7.5.2"
+ type imports do: [:import |
+ import isOnDemand
+ ifTrue: [
+ (nameEnvClass doesPackageExistNamed: import javaPackageName) ifFalse: [
+ (nameEnvClass findJavaClassNamedFrom: import javaPackageName) == nil ifTrue: [
+ problemSummary
+ reportVerificationProblem: #OnDemandImportRefersToMissingPackage
+ args: (Array with: import asString)
+ severity: ErrorInfo::ImportVerification
+ forType: type]]]
+ ifFalse: [
+ (imports := importsBySimpleName at: import javaSimpleName ifAbsent: []) == nil
+ ifTrue: [
+ importsBySimpleName at: import javaSimpleName put: (Array with: import)]
+ ifFalse: [
+ (imports includes: import) ifFalse: [
+ importsBySimpleName at: import javaSimpleName put: imports, (Array with: import)]].
+
+ "Ignore any imports which are simple names - we will treat these as no-ops."
+
+ import javaPackageName notEmpty ifTrue: [
+ cl := nameEnvClass findJavaClassNamedFrom: import asString.
+
+ (cl ~~ nil and: [cl isJavaPublic or: [cl controller symbol == type controller symbol]]) ifFalse: [
+ problemSummary
+ reportVerificationProblem: #SingleTypeImportRefersToInvisibleType
+ args: (Array with: import asString)
+ severity: ErrorInfo::ImportVerification
+ forType: type]]]].
+
+ importsBySimpleName notEmpty ifTrue: [
+ importsBySimpleName keysAndValuesDo: [:simpleName :matching |
+ matching size == 1
+ ifTrue: [
+ simpleName = type sourceName ifTrue: [
+ matching first javaReadableName = type javaReadableName ifFalse: [
+ problemSummary
+ reportVerificationProblem: #SingleTypeImportConflictsWithType
+ args: #()
+ severity: nil
+ forType: type]]]
+ ifFalse: [
+ problemSummary
+ reportVerificationProblem: #SingleTypeImportsHaveSameSimpleName
+ args: (Array with: simpleName)
+ severity: nil
+ forType: type]]]
+*/
+private void zzTypeProblems() {
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+public class NestedTypeBinding extends SourceTypeBinding {
+ public SourceTypeBinding enclosingType;
+
+ public SyntheticArgumentBinding[] enclosingInstances;
+ public SyntheticArgumentBinding[] outerLocalVariables;
+ public int syntheticArgumentsOffset; // amount of slots used by synthetic constructor arguments
+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 enclosingType) {
+ SyntheticArgumentBinding synthLocal = null;
+ if (enclosingInstances == null) {
+ synthLocal = new SyntheticArgumentBinding(enclosingType);
+ enclosingInstances = new SyntheticArgumentBinding[] {synthLocal};
+ } else {
+ int size = enclosingInstances.length;
+ int newArgIndex = size;
+ for (int i = size; --i >= 0;) {
+ if (enclosingInstances[i].type == enclosingType)
+ return enclosingInstances[i]; // already exists
+ if (this.enclosingType() == enclosingType)
+ newArgIndex = 0;
+ }
+ SyntheticArgumentBinding[] newInstances = new SyntheticArgumentBinding[size + 1];
+ System.arraycopy(enclosingInstances, 0, newInstances, newArgIndex == 0 ? 1 : 0, size);
+ newInstances[newArgIndex] = synthLocal = new SyntheticArgumentBinding(enclosingType);
+ 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 enclosingType) {
+ SyntheticArgumentBinding synthLocal = addSyntheticArgument(enclosingType);
+ if (synthLocal == null) return null;
+
+ if (synthLocal.matchingField == null)
+ synthLocal.matchingField = addSyntheticField(enclosingType);
+ return synthLocal;
+}
+/**
+ * Compute the resolved positions for all the synthetic arguments
+ */
+final public void computeSyntheticArgumentsOffset() {
+
+ int position = 1; // inside constructor, reserve room for receiver
+
+ // insert enclosing instances first, followed by the outerLocals
+ SyntheticArgumentBinding[] enclosingInstances = this.syntheticEnclosingInstances();
+ int enclosingInstancesCount = enclosingInstances == null ? 0 : enclosingInstances.length;
+ for (int i = 0; i < enclosingInstancesCount; i++){
+ SyntheticArgumentBinding syntheticArg = enclosingInstances[i];
+ syntheticArg.resolvedPosition = position;
+ if ((syntheticArg.type == LongBinding) || (syntheticArg.type == DoubleBinding)){
+ position += 2;
+ } else {
+ position ++;
+ }
+ }
+ SyntheticArgumentBinding[] outerLocals = this.syntheticOuterLocalVariables();
+ int outerLocalsCount = outerLocals == null ? 0 : outerLocals.length;
+ for (int i = 0; i < outerLocalsCount; i++){
+ SyntheticArgumentBinding syntheticArg = outerLocals[i];
+ syntheticArg.resolvedPosition = position;
+ if ((syntheticArg.type == LongBinding) || (syntheticArg.type == DoubleBinding)){
+ position += 2;
+ } else {
+ position ++;
+ }
+ }
+ this.syntheticArgumentsOffset = position;
+}
+/* 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 enclosing instances 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, BlockScope scope, 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfPackage;
+import net.sourceforge.phpdt.internal.compiler.util.HashtableOfType;
+
+public class PackageBinding extends Binding implements TypeConstants {
+ public char[][] compoundName;
+ PackageBinding parent;
+ LookupEnvironment environment;
+ HashtableOfType knownTypes;
+ HashtableOfPackage knownPackages;
+protected PackageBinding() {
+}
+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(NoCharChar, null, environment);
+}
+private void addNotFoundPackage(char[] simpleName) {
+ knownPackages.put(simpleName, environment.theNotFoundPackage);
+}
+private void addNotFoundType(char[] simpleName) {
+ if (knownTypes == null)
+ knownTypes = new HashtableOfType(25);
+ knownTypes.put(simpleName, environment.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[][] compoundName = CharOperation.arrayConcat(this.compoundName, name);
+ PackageBinding newPackageBinding = new PackageBinding(compoundName, this, environment);
+ addPackage(newPackageBinding);
+ return newPackageBinding;
+}
+/* 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 == environment.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 == environment.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 package.
+* Treat the type 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) {
+ PackageBinding packageBinding = getPackage0(name);
+ if (packageBinding != null && packageBinding != environment.theNotFoundPackage)
+ return packageBinding;
+
+ ReferenceBinding typeBinding = getType0(name);
+ if (typeBinding != null && typeBinding != environment.theNotFoundType) {
+ if (typeBinding instanceof UnresolvedReferenceBinding)
+ typeBinding = ((UnresolvedReferenceBinding) typeBinding).resolve(environment);
+ if (typeBinding.isNestedType())
+ return new ProblemReferenceBinding(name, InternalNameProvided);
+ return typeBinding;
+ }
+
+ if (typeBinding == null && packageBinding == null) {
+ // find the package
+ if ((packageBinding = findPackage(name)) != null)
+ return packageBinding;
+
+ // if no package was found, find the type named name relative to the receiver
+ if ((typeBinding = environment.askForType(this, name)) != null) {
+ if (typeBinding.isNestedType())
+ return new ProblemReferenceBinding(name, InternalNameProvided);
+ return typeBinding;
+ }
+
+ // Since name could not be found, add problem bindings
+ // to the collections so it will be reported as an error next time.
+ addNotFoundPackage(name);
+ addNotFoundType(name);
+ } else {
+ if (packageBinding == environment.theNotFoundPackage)
+ packageBinding = null;
+ if (typeBinding == environment.theNotFoundType)
+ typeBinding = null;
+ }
+
+ if (packageBinding != null)
+ return packageBinding;
+ else
+ return typeBinding;
+}
+public char[] readableName() /*java.lang*/ {
+ return CharOperation.concatWith(compoundName, '.');
+}
+public String toString() {
+ if (compoundName == NoCharChar)
+ return "The Default Package"; //$NON-NLS-1$
+ else
+ return "package " + ((compoundName != null) ? CharOperation.toString(compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.util.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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class ProblemFieldBinding extends FieldBinding {
+ private int problemId;
+// NOTE: must only answer the subset of the name related to the problem
+
+public ProblemFieldBinding(ReferenceBinding declaringClass, char[][] compoundName, int problemId) {
+ this(declaringClass, CharOperation.concatWith(compoundName, '.'), problemId);
+}
+public ProblemFieldBinding(ReferenceBinding declaringClass, char[] name, int problemId) {
+ 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
+/* API
+* Answer the problem id associated with the receiver.
+* NoError if the receiver is a valid binding.
+*/
+
+public final int problemId() {
+ return problemId;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+public class ProblemReferenceBinding extends ReferenceBinding {
+ public Binding 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, Binding original, int problemId) {
+ this.compoundName = compoundName;
+ this.original = original;
+ this.problemId = problemId;
+}
+public ProblemReferenceBinding(char[] name, Binding 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.env.IDependent;
+import net.sourceforge.phpdt.internal.compiler.util.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 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.
+*
+* NOTE: Cannot invoke this method with a compilation unit scope.
+*/
+
+public final boolean canBeSeenBy(Scope scope) {
+ if (isPublic()) return true;
+
+ SourceTypeBinding invocationType = scope.enclosingSourceType();
+ if (invocationType == this) return true;
+
+ if (isProtected()) {
+ // answer true if the receiver (or its enclosing type) is the superclass
+ // of the invocationType or in the same package
+ return invocationType.fPackage == fPackage
+ || isSuperclassOf(invocationType)
+ || enclosingType().isSuperclassOf(invocationType); // protected types always have an enclosing one
+ }
+
+ 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;
+ }
+ return; // all other types are in java.*.*
+ }
+
+ if (!CharOperation.equals(JAVA, compoundName[0]))
+ return; // assumes we only look up types in java
+
+ if (!CharOperation.equals(LANG, compoundName[1])) {
+ if (CharOperation.equals(JAVA_IO_PRINTSTREAM, compoundName)) {
+ id = T_JavaIoPrintStream;
+ return;
+ }
+ return; // all other types are in java.lang
+ }
+
+ if (CharOperation.equals(JAVA_LANG_OBJECT, compoundName)) {
+ id = T_JavaLangObject;
+ return;
+ }
+ if (CharOperation.equals(JAVA_LANG_STRING, compoundName)) {
+ id = T_JavaLangString;
+ return;
+ }
+
+ // well-known exception types
+ if (CharOperation.equals(JAVA_LANG_THROWABLE, compoundName)) {
+ id = T_JavaLangThrowable;
+ return;
+ }
+ if (CharOperation.equals(JAVA_LANG_ERROR, compoundName)) {
+ id = T_JavaLangError;
+ return;
+ }
+ if (CharOperation.equals(JAVA_LANG_EXCEPTION, compoundName)) {
+ id = T_JavaLangException;
+ return;
+ }
+ if (CharOperation.equals(JAVA_LANG_CLASSNOTFOUNDEXCEPTION, compoundName)) {
+ id = T_JavaLangClassNotFoundException;
+ return;
+ }
+ if (CharOperation.equals(JAVA_LANG_NOCLASSDEFERROR, compoundName)) {
+ id = T_JavaLangNoClassDefError;
+ return;
+ }
+
+ // other well-known types
+ if (CharOperation.equals(JAVA_LANG_CLASS, compoundName)) {
+ id = T_JavaLangClass;
+ return;
+ }
+ if (CharOperation.equals(JAVA_LANG_STRINGBUFFER, compoundName)) {
+ id = T_JavaLangStringBuffer;
+ return;
+ }
+ if (CharOperation.equals(JAVA_LANG_SYSTEM, compoundName)) {
+ id = T_JavaLangSystem;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_INTEGER, compoundName)) {
+ id = T_JavaLangInteger;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_BYTE, compoundName)) {
+ id = T_JavaLangByte;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_CHARACTER, compoundName)) {
+ id = T_JavaLangCharacter;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_FLOAT, compoundName)) {
+ id = T_JavaLangFloat;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_DOUBLE, compoundName)) {
+ id = T_JavaLangDouble;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_BOOLEAN, compoundName)) {
+ id = T_JavaLangBoolean;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_SHORT, compoundName)) {
+ id = T_JavaLangShort;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_LONG, compoundName)) {
+ id = T_JavaLangLong;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_VOID, compoundName)) {
+ id = T_JavaLangVoid;
+ return;
+ }
+
+ if (CharOperation.equals(JAVA_LANG_ASSERTIONERROR, compoundName)) {
+ id = T_JavaLangAssertionError;
+ 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) {
+ 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;
+}
+/* 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)
+*/
+
+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 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(), '.');
+ } else {
+ return sourceName();
+ }
+}
+public char[] readableName() /*java.lang.Object*/ {
+ if (isMemberType())
+ return CharOperation.concat(enclosingType().readableName(), sourceName, '.');
+ else
+ return CharOperation.concatWith(compoundName, '.');
+}
+/* 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;
+ else
+ return new ReferenceBinding[] {enclosingType};
+}
+public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
+ return null; // is null if no enclosing instances are required
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.util.ObjectVector;
+
+public abstract class Scope
+ implements
+ BaseTypes,
+ BindingIds,
+ CompilerModifiers,
+ ProblemReasons,
+ TagBits,
+ TypeConstants,
+ TypeIds {
+
+ public Scope parent;
+ public int kind;
+
+ 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;
+ protected Scope(int kind, Scope parent) {
+ this.kind = kind;
+ this.parent = parent;
+ }
+
+ public abstract ProblemReporter problemReporter();
+
+ // 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;
+ }
+
+ /* Answer true if the left type can be assigned to right
+ */
+ public static boolean areTypesCompatible(TypeBinding left, TypeBinding right) {
+ return left.isCompatibleWith(right);
+ }
+
+ /* 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 (areTypesCompatible(left, right))
+ return EqualOrMoreSpecific;
+ if (areTypesCompatible(right, left))
+ return MoreGeneric;
+ return NotRelated;
+ }
+
+ /* 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 environment().createArrayType(type, dimension);
+ else
+ return new ArrayBinding(type, dimension);
+ }
+
+ /* 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;
+ }
+
+ // 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;
+ else
+ return new ProblemReferenceBinding(typeName, memberType, NotVisible);
+ }
+ return null;
+ }
+
+ // Internal use only
+ public MethodBinding findExactMethod(
+ ReferenceBinding receiverType,
+ char[] selector,
+ TypeBinding[] argumentTypes,
+ InvocationSite invocationSite) {
+
+ 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) {
+ if (receiverType.isBaseType()) return null;
+ if (receiverType.isArrayType()) {
+ if (CharOperation.equals(fieldName, LENGTH))
+ return ArrayBinding.LengthField;
+ return null;
+ }
+
+ compilationUnitScope().recordTypeReference(receiverType);
+
+ ReferenceBinding currentType = (ReferenceBinding) receiverType;
+ if (!currentType.canBeSeenBy(this))
+ return new ProblemFieldBinding(currentType, fieldName, NotVisible);
+ // *** Need a new problem id - TypeNotVisible?
+
+ FieldBinding field = currentType.getField(fieldName);
+ if (field != null) {
+ if (field.canBeSeenBy(currentType, invocationSite, this))
+ return field;
+ else
+ return new ProblemFieldBinding(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)) != null) {
+ keepLooking = false;
+ if (field.canBeSeenBy(receiverType, invocationSite, this)) {
+ if (visibleField == null)
+ visibleField = field;
+ else
+ return new ProblemFieldBinding(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)) != null) {
+ if (visibleField == null) {
+ visibleField = field;
+ } else {
+ ambiguous = new ProblemFieldBinding(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;
+ else
+ 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();
+
+ 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();
+ }
+
+ // superclass lookup
+ ReferenceBinding classHierarchyStart = currentType;
+ while (currentType != null) {
+ 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);
+ }
+ currentType = currentType.superclass();
+ }
+
+ int foundSize = found.size;
+ if (foundSize == 0) {
+ if (matchingMethod != null && areParametersAssignable(matchingMethod.parameters, argumentTypes))
+ return matchingMethod;
+ return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, matchingMethod, found);
+ }
+
+ MethodBinding[] candidates = new MethodBinding[foundSize];
+ int candidatesCount = 0;
+ // argument type compatibility check
+ for (int i = 0; i < foundSize; i++) {
+ MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
+ if (areParametersAssignable(methodBinding.parameters, argumentTypes))
+ candidates[candidatesCount++] = methodBinding;
+ }
+ if (candidatesCount == 1) {
+ compilationUnitScope().recordTypeReferences(candidates[0].thrownExceptions);
+ return candidates[0]; // have not checked visibility
+ }
+ if (candidatesCount == 0) { // try to find a close match when the parameter order is wrong or missing some parameters
+ 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
+ }
+
+ // 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].selector, argumentTypes, candidates[0].declaringClass, NotVisible);
+ }
+ if (candidates[0].declaringClass.isClass()) {
+ return mostSpecificClassMethodBinding(candidates, visiblesCount);
+ } else {
+ return mostSpecificInterfaceMethodBinding(candidates, visiblesCount);
+ }
+ }
+
+ // 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) 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);
+ }
+
+ 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 MethodBinding findMethodForArray(
+ ArrayBinding receiverType,
+ char[] selector,
+ TypeBinding[] argumentTypes,
+ InvocationSite invocationSite) {
+
+ ReferenceBinding object = getJavaLangObject();
+ MethodBinding methodBinding = object.getExactMethod(selector, argumentTypes);
+ if (methodBinding != null) {
+ // handle the method clone() specially... cannot be protected or throw exceptions
+ if (argumentTypes == NoParameters && CharOperation.equals(selector, CLONE))
+ return new MethodBinding(
+ (methodBinding.modifiers ^ AccProtected) | AccPublic,
+ CLONE,
+ methodBinding.returnType,
+ argumentTypes,
+ null,
+ object);
+ if (methodBinding.canBeSeenBy(receiverType, invocationSite, this))
+ return methodBinding;
+ }
+ // answers closest approximation, may not check argumentTypes or visibility
+ methodBinding = findMethod(object, selector, argumentTypes, invocationSite);
+ if (methodBinding == null)
+ return new ProblemMethodBinding(selector, argumentTypes, NotFound);
+ if (methodBinding.isValidBinding()) {
+ if (!areParametersAssignable(methodBinding.parameters, argumentTypes))
+ return new ProblemMethodBinding(
+ methodBinding,
+ selector,
+ argumentTypes,
+ NotFound);
+ if (!methodBinding.canBeSeenBy(receiverType, invocationSite, this))
+ return new ProblemMethodBinding(
+ selector,
+ argumentTypes,
+ methodBinding.declaringClass,
+ NotVisible);
+ }
+ return methodBinding;
+ }
+
+ // 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()) {
+// Not convinced that this is necessary
+// compilationUnitScope().recordTypeReference(typeBinding); // to record supertypes
+ if (declarationPackage != invocationPackage && !typeBinding.canBeSeenBy(invocationPackage))
+ return new ProblemReferenceBinding(typeName, typeBinding, NotVisible);
+ }
+ return typeBinding;
+ }
+
+ 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;
+ }
+
+ public final PackageBinding getCurrentPackage() {
+ Scope scope, unitScope = this;
+ while ((scope = unitScope.parent) != null)
+ unitScope = scope;
+ return ((CompilationUnitScope) unitScope).fPackage;
+ }
+
+ 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 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 getJavaLangAssertionError() {
+ compilationUnitScope().recordQualifiedReference(JAVA_LANG_ASSERTIONERROR);
+ ReferenceBinding type = environment().getType(JAVA_LANG_ASSERTIONERROR);
+ if (type != null) return type;
+ problemReporter().isClassPathCorrect(JAVA_LANG_ASSERTIONERROR, referenceCompilationUnit());
+ return null; // will not get here since the above error aborts the compilation
+ }
+
+ public final ReferenceBinding getJavaLangObject() {
+ compilationUnitScope().recordQualifiedReference(JAVA_LANG_OBJECT);
+ ReferenceBinding type = environment().getType(JAVA_LANG_OBJECT);
+ 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);
+ }
+
+ /* 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())
+ return new ProblemReferenceBinding(
+ CharOperation.subarray(compoundName, 0, currentIndex),
+ typeBinding.problemId());
+ }
+ return typeBinding;
+ }
+
+ /* Answer the type binding that corresponds the given name, starting the lookup in the receiver.
+ * The name provided is a simple source name (e.g., "Object" , "Point", ...)
+ */
+ // 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);
+ }
+
+ // 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;
+ }
+
+ /* 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;
+ if (CharOperation.equals(sourceType.sourceName, name)) {
+ if (foundType != null && foundType != sourceType)
+ return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+ return sourceType;
+ }
+
+ ReferenceBinding memberType = findMemberType(name, sourceType);
+ if (memberType != null) { // skip it if we did not find anything
+ if (memberType.problemId() == Ambiguous) {
+ if (foundType == null || foundType.problemId() == NotVisible)
+ // supercedes any potential InheritedNameHidesEnclosingName problem
+ return memberType;
+ else
+ // make the user qualify the type, likely wants the first inherited type
+ return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+ }
+ if (memberType.isValidBinding()) {
+ if (sourceType == memberType.enclosingType()
+ || environment().options.complianceLevel >= CompilerOptions.JDK1_4) {
+ // found a valid type in the 'immediate' scope (ie. not inherited)
+ // OR in 1.4 mode (inherited shadows enclosing)
+ if (foundType == null)
+ return memberType;
+ if (foundType.isValidBinding())
+ // if a valid type was found, complain when another is found in an 'immediate' enclosing type (ie. not inherited)
+ if (foundType != memberType)
+ return new ProblemReferenceBinding(name, InheritedNameHidesEnclosingName);
+ }
+ }
+ if (foundType == null || (foundType.problemId() == NotVisible && memberType.problemId() != NotVisible))
+ // only remember the memberType if its the first one found or the previous one was not visible & memberType is...
+ foundType = memberType;
+ }
+ 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;
+ // ask for the imports + name
+ if ((mask & TYPE) != 0) {
+ // check single type imports.
+ ImportBinding[] imports = unitScope.imports;
+ if (imports != null){
+ // copy the list, since single type imports are removed if they cannot be resolved
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportBinding typeImport = imports[i];
+ if (!typeImport.onDemand)
+ if (CharOperation.equals(typeImport.compoundName[typeImport.compoundName.length - 1], name))
+ if (unitScope.resolveSingleTypeImport(typeImport) != null) {
+ if (typeImport.reference != null) typeImport.reference.used = true;
+ return typeImport.resolvedImport; // already know its visible
+ }
+ }
+ }
+ // check if the name is in the current package (answer the problem binding unless its not found in which case continue to look)
+ ReferenceBinding type = findType(name, unitScope.fPackage, unitScope.fPackage); // is always visible
+ if (type != null) return type;
+
+ // check on demand imports
+ boolean foundInImport = false;
+ if (imports != null){
+ for (int i = 0, length = imports.length; i < length; i++) {
+ ImportBinding someImport = imports[i];
+ if (someImport.onDemand) {
+ Binding resolvedImport = someImport.resolvedImport;
+ ReferenceBinding temp =
+ (resolvedImport instanceof PackageBinding)
+ ? findType(name, (PackageBinding) resolvedImport, unitScope.fPackage)
+ : findDirectMemberType(name, (ReferenceBinding) resolvedImport);
+ if (temp != null && temp.isValidBinding()) {
+ if (someImport.reference != null) someImport.reference.used = true;
+ if (foundInImport)
+ // Answer error binding -- import on demand conflict; name found in two import on demand packages.
+ return new ProblemReferenceBinding(name, Ambiguous);
+ type = temp;
+ foundInImport = true;
+ }
+ }
+ }
+ }
+ if (type != null)
+ return type;
+ }
+ // see if the name is a package
+ if ((mask & PACKAGE) != 0) {
+ compilationUnitScope().recordSimpleReference(name);
+ PackageBinding packageBinding = unitScope.environment.getTopLevelPackage(name);
+ if (packageBinding != null)
+ return packageBinding;
+ }
+
+ compilationUnitScope().recordSimpleReference(name);
+ // Answer error binding -- could not find name
+ if (foundType != null){
+ return foundType;
+ }
+ return new ProblemReferenceBinding(name, NotFound);
+ }
+
+ /* 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;
+ }
+
+ public final boolean isJavaIoSerializable(TypeBinding tb) {
+ //a first -none optimized version-...:-)....
+ //please modify as needed
+
+ return tb == getJavaIoSerializable();
+ }
+
+ public final boolean isJavaLangCloneable(TypeBinding tb) {
+ //a first -none optimized version-...:-)....
+ //please modify as needed
+
+ return tb == getJavaLangCloneable();
+ }
+
+ public final boolean isJavaLangObject(TypeBinding type) {
+ return type.id == T_JavaLangObject;
+ }
+
+ 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
+ previous = method;
+ 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);
+ }
+
+ 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 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;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.AssertStatement;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.internal.compiler.impl.Constant;
+import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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, fields, class literals and changed declaring class bindings
+ public final static int METHOD = 0;
+ public final static int FIELD = 1;
+ public final static int CLASS_LITERAL = 2;
+ public final static int CHANGED_DECLARING_CLASS = 3;
+
+ Hashtable[] synthetics;
+protected SourceTypeBinding() {
+}
+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;
+
+ 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 >= CompilerOptions.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[] methods = superType.methods();
+ for (int m = methods.length; --m >= 0;) {
+ MethodBinding method = methods[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] == null) {
+ synthetics[FIELD] = new Hashtable(5);
+ }
+
+ FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
+ if (synthField == null) {
+ synthField = new SyntheticFieldBinding(
+ CharOperation.concat(SyntheticArgumentBinding.OuterLocalPrefix, actualOuterLocalVariable.name),
+ actualOuterLocalVariable.type,
+ AccPrivate | AccFinal | AccSynthetic,
+ this,
+ Constant.NotAConstant,
+ synthetics[FIELD].size());
+ synthetics[FIELD].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)) != 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] == null) {
+ synthetics[FIELD] = new Hashtable(5);
+ }
+
+ FieldBinding synthField = (FieldBinding) synthetics[FIELD].get(enclosingType);
+ if (synthField == null) {
+ synthField = new SyntheticFieldBinding(
+ CharOperation.concat(
+ SyntheticArgumentBinding.EnclosingInstancePrefix,
+ String.valueOf(enclosingType.depth()).toCharArray()),
+ enclosingType,
+ AccPrivate | AccFinal | AccSynthetic,
+ this,
+ Constant.NotAConstant,
+ synthetics[FIELD].size());
+ synthetics[FIELD].put(enclosingType, synthField);
+ }
+ // ensure there is not already such a field defined by the user
+ FieldBinding existingField;
+ if ((existingField = this.getField(synthField.name)) != 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] == null) {
+ synthetics[CLASS_LITERAL] = new Hashtable(5);
+ }
+
+ // use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
+ FieldBinding synthField = (FieldBinding) synthetics[CLASS_LITERAL].get(targetType);
+ if (synthField == null) {
+ synthField = new SyntheticFieldBinding(
+ ("class$" + synthetics[CLASS_LITERAL].size()).toCharArray(), //$NON-NLS-1$
+ blockScope.getJavaLangClass(),
+ AccDefault | AccStatic | AccSynthetic,
+ this,
+ Constant.NotAConstant,
+ synthetics[CLASS_LITERAL].size());
+ synthetics[CLASS_LITERAL].put(targetType, synthField);
+ }
+ // ensure there is not already such a field defined by the user
+ FieldBinding existingField;
+ if ((existingField = this.getField(synthField.name)) != 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] == null) {
+ synthetics[FIELD] = new Hashtable(5);
+ }
+
+ FieldBinding synthField = (FieldBinding) synthetics[FIELD].get("assertionEmulation"); //$NON-NLS-1$
+ if (synthField == null) {
+ synthField = new SyntheticFieldBinding(
+ "$assertionsDisabled".toCharArray(), //$NON-NLS-1$
+ BooleanBinding,
+ AccDefault | AccStatic | AccSynthetic | AccFinal,
+ this,
+ Constant.NotAConstant,
+ 0);
+ synthetics[FIELD].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)) != 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] == null) {
+ synthetics[METHOD] = new Hashtable(5);
+ }
+
+ SyntheticAccessMethodBinding accessMethod = null;
+ SyntheticAccessMethodBinding[] accessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].get(targetField);
+ if (accessors == null) {
+ accessMethod = new SyntheticAccessMethodBinding(targetField, isReadAccess, this);
+ synthetics[METHOD].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>.
+ Answer the new method or the existing method if one already existed.
+*/
+
+public SyntheticAccessMethodBinding addSyntheticMethod(MethodBinding targetMethod) {
+
+ if (synthetics == null) {
+ synthetics = new Hashtable[4];
+ }
+ if (synthetics[METHOD] == null) {
+ synthetics[METHOD] = new Hashtable(5);
+ }
+
+ SyntheticAccessMethodBinding accessMethod = (SyntheticAccessMethodBinding) synthetics[METHOD].get(targetMethod);
+ if (accessMethod == null) {
+ accessMethod = new SyntheticAccessMethodBinding(targetMethod, this);
+ synthetics[METHOD].put(targetMethod, 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[] methods = getMethods(ConstructorDeclaration.ConstantPoolName); // takes care of duplicates & default abstract methods
+ nextMethod : for (int m = methods.length; --m >= 0;) {
+ MethodBinding method = methods[m];
+ TypeBinding[] toMatch = method.parameters;
+ if (toMatch.length == argCount) {
+ 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 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.prefixEquals(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[] methods = getMethods(selector); // takes care of duplicates & default abstract methods
+ foundNothing = methods == NoMethods;
+ nextMethod : for (int m = methods.length; --m >= 0;) {
+ MethodBinding method = methods[m];
+ 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) {
+ int fieldLength = fieldName.length;
+ for (int f = fields.length; --f >= 0;) {
+ FieldBinding field = fields[f];
+ if (field.name.length == fieldLength && CharOperation.prefixEquals(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.prefixEquals(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.prefixEquals(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.prefixEquals(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.prefixEquals(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] == null) return null;
+ return (FieldBinding) synthetics[FIELD].get(actualOuterLocalVariable);
+}
+public ReferenceBinding[] memberTypes() {
+ return memberTypes;
+}
+public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
+
+ if (synthetics == null) {
+ synthetics = new Hashtable[4];
+ }
+ if (synthetics[CHANGED_DECLARING_CLASS] == null) {
+ synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
+ }
+
+ Hashtable fieldMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetField);
+ if (fieldMap == null) {
+ fieldMap = new Hashtable(5);
+ synthetics[CHANGED_DECLARING_CLASS].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 (synthetics == null) {
+ synthetics = new Hashtable[4];
+ }
+ if (synthetics[CHANGED_DECLARING_CLASS] == null) {
+ synthetics[CHANGED_DECLARING_CLASS] = new Hashtable(5);
+ }
+
+
+ Hashtable methodMap = (Hashtable) synthetics[CHANGED_DECLARING_CLASS].get(targetMethod);
+ if (methodMap == null) {
+ methodMap = new Hashtable(5);
+ synthetics[CHANGED_DECLARING_CLASS].put(targetMethod, methodMap);
+ }
+ MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
+ if (updatedMethod == null){
+ updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
+ methodMap.put(newDeclaringClass, updatedMethod);
+ }
+ return updatedMethod;
+}
+
+// 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.type != null)
+ 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);
+ 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] == null || synthetics[METHOD].size() == 0) return null;
+
+ // difficult to compute size up front because of the embedded arrays so assume there is only 1
+ int index = 0;
+ SyntheticAccessMethodBinding[] bindings = new SyntheticAccessMethodBinding[1];
+ Enumeration fieldsOrMethods = synthetics[METHOD].keys();
+ while (fieldsOrMethods.hasMoreElements()) {
+ Object fieldOrMethod = fieldsOrMethods.nextElement();
+ if (fieldOrMethod instanceof MethodBinding) {
+ if (index + 1 > bindings.length)
+ System.arraycopy(bindings, 0, (bindings = new SyntheticAccessMethodBinding[index + 1]), 0, index);
+ bindings[index++] = (SyntheticAccessMethodBinding) synthetics[METHOD].get(fieldOrMethod);
+ } else {
+ SyntheticAccessMethodBinding[] fieldAccessors = (SyntheticAccessMethodBinding[]) synthetics[METHOD].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];
+ if (fieldAccessors[1] != null)
+ bindings[index++] = fieldAccessors[1];
+ }
+ }
+
+ // 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] == null ? 0 : synthetics[FIELD].size();
+ int literalSize = synthetics[CLASS_LITERAL] == null ? 0 :synthetics[CLASS_LITERAL].size();
+ int totalSize = fieldSize + literalSize;
+ if (totalSize == 0) return null;
+ FieldBinding[] bindings = new FieldBinding[totalSize];
+
+ // add innerclass synthetics
+ if (synthetics[FIELD] != null){
+ Enumeration elements = synthetics[FIELD].elements();
+ for (int i = 0; i < fieldSize; i++) {
+ SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.nextElement();
+ bindings[synthBinding.index] = synthBinding;
+ }
+ }
+ // add class literal synthetics
+ if (synthetics[CLASS_LITERAL] != null){
+ Enumeration elements = synthetics[CLASS_LITERAL].elements();
+ 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, BlockScope scope, boolean onlyExactMatch) {
+
+ if (synthetics == null || synthetics[FIELD] == null) return null;
+ FieldBinding field = (FieldBinding) synthetics[FIELD].get(targetEnclosingType);
+ if (field != null) return field;
+
+ // type compatibility : to handle cases such as
+ // class T { class M{}}
+ // class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
+ if (!onlyExactMatch){
+ Enumeration enum = synthetics[FIELD].elements();
+ while (enum.hasMoreElements()) {
+ field = (FieldBinding) enum.nextElement();
+ if (CharOperation.startsWith(field.name, SyntheticArgumentBinding.EnclosingInstancePrefix)
+ && targetEnclosingType.isSuperclassOf((ReferenceBinding) field.type))
+ return field;
+ }
+ }
+ return null;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+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;
+ public final static int FieldWriteAccess = 2;
+ public final static int MethodAccess = 3;
+ public final static int ConstructorAccess = 4;
+
+ 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 (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 (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.selector(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, ReferenceBinding receiverType) {
+
+ if (targetMethod.isConstructor()) {
+ this.initializeConstructorAccessor(targetMethod);
+ } else {
+ this.initializeMethodAccessor(targetMethod, 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 targetConstructor) {
+
+ this.targetMethod = targetConstructor;
+ this.modifiers = AccDefault | AccSynthetic;
+ SourceTypeBinding sourceType =
+ (SourceTypeBinding) targetConstructor.declaringClass;
+ SyntheticAccessMethodBinding[] knownAccessMethods =
+ sourceType.syntheticAccessMethods();
+ this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length;
+
+ this.selector = targetConstructor.selector;
+ this.returnType = targetConstructor.returnType;
+ this.accessType = ConstructorAccess;
+ this.parameters = new TypeBinding[targetConstructor.parameters.length + 1];
+ System.arraycopy(
+ targetConstructor.parameters,
+ 0,
+ this.parameters,
+ 0,
+ targetConstructor.parameters.length);
+ parameters[targetConstructor.parameters.length] =
+ targetConstructor.declaringClass;
+ this.thrownExceptions = targetConstructor.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 (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 (this.selector == knownAccessMethods[i].selector
+ && this.areParametersEqual(methods[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 == targetConstructor) {
+ 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 targetMethod, ReferenceBinding declaringClass) {
+
+ this.targetMethod = targetMethod;
+ 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());
+ this.returnType = targetMethod.returnType;
+ this.accessType = MethodAccess;
+
+ if (targetMethod.isStatic()) {
+ this.parameters = targetMethod.parameters;
+ } else {
+ this.parameters = new TypeBinding[targetMethod.parameters.length + 1];
+ this.parameters[0] = declaringSourceType;
+ System.arraycopy(targetMethod.parameters, 0, this.parameters, 1, targetMethod.parameters.length);
+ }
+ this.thrownExceptions = targetMethod.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 (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 (this.selector == knownAccessMethods[i].selector && this.areParametersEqual(methods[i])) {
+ needRename = true;
+ break check;
+ }
+ }
+ }
+ }
+ if (needRename) { // retry with a selector & a growing methodId
+ this.selector(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 == targetMethod) {
+ this.sourceStart = methodDecls[i].sourceStart;
+ return;
+ }
+ }
+ }
+}
+protected boolean isConstructorRelated() {
+ return accessType == ConstructorAccess;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class SyntheticArgumentBinding extends LocalVariableBinding {
+
+ {
+ this.isArgument = true;
+ this.used = true;
+ }
+ // 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);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+/*
+ * 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.
+ */
+
+public abstract char[] constantPoolName(); /* java/lang/Object */
+String debugName() {
+ return new String(readableName());
+}
+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)
+*/
+
+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() {
+ return getPackage() == null ? NoChar : getPackage().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();
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+public interface TypeConstants {
+ final char[] JAVA = new char[] {'j', 'a', 'v', 'a'};
+ final char[] LANG = new char[] {'l', 'a', 'n', 'g'};
+ final char[] IO = new char[] {'i', 'o'};
+ final char[] REFLECT = new char[] {'r', 'e', 'f', 'l', 'e', 'c', 't'};
+ final char[] CharArray_JAVA_LANG_OBJECT = new char[] {'j', 'a', 'v', 'a', '.', 'l', 'a', 'n', 'g', '.', 'O', 'b', 'j', 'e', 'c', 't'};
+ final char[] LENGTH = new char[] {'l', 'e', 'n', 'g', 't', 'h'};
+ final char[] CLONE = new char[] {'c', 'l', 'o', 'n', 'e'};
+
+ // Constant compound names
+ final char[][] JAVA_LANG = new char[][] {JAVA, LANG};
+ final char[][] JAVA_IO = new char[][] {JAVA, IO};
+ final char[][] JAVA_LANG_ASSERTIONERROR = new char[][] {JAVA, LANG, "AssertionError".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_CLASS = new char[][] {JAVA, LANG, {'C', 'l', 'a', 's', 's'}};
+ final char[][] JAVA_LANG_CLASSNOTFOUNDEXCEPTION = new char[][] {JAVA, LANG, {'C', 'l', 'a', 's', 's', 'N', 'o', 't', 'F', 'o', 'u', 'n', 'd', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n'}};
+ final char[][] JAVA_LANG_CLONEABLE = new char[][] {JAVA, LANG, {'C', 'l', 'o', 'n', 'e', 'a', 'b', 'l', 'e'}};
+ final char[][] JAVA_LANG_EXCEPTION = new char[][] {JAVA, LANG, {'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n'}};
+ final char[][] JAVA_LANG_ERROR = new char[][] {JAVA, LANG, {'E', 'r', 'r', 'o', 'r'}};
+ final char[][] JAVA_LANG_NOCLASSDEFERROR = new char[][] {JAVA, LANG, {'N', 'o', 'C', 'l', 'a', 's', 's', 'D', 'e', 'f', 'E', 'r', 'r', 'o', 'r'}};
+ final char[][] JAVA_LANG_OBJECT = new char[][] {JAVA, LANG, {'O', 'b', 'j', 'e', 'c', 't'}};
+ final char[][] JAVA_LANG_STRING = new char[][] {JAVA, LANG, {'S', 't', 'r', 'i', 'n', 'g'}};
+ final char[][] JAVA_LANG_STRINGBUFFER = new char[][] {JAVA, LANG, {'S', 't', 'r', 'i', 'n', 'g', 'B', 'u', 'f', 'f', 'e', 'r'}};
+ final char[][] JAVA_LANG_SYSTEM = new char[][] {JAVA, LANG, {'S', 'y', 's', 't', 'e', 'm'}};
+ final char[][] JAVA_LANG_RUNTIMEEXCEPTION = new char[][] {JAVA, LANG, {'R', 'u', 'n', 't', 'i', 'm', 'e', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n'}};
+ final char[][] JAVA_LANG_THROWABLE = new char[][] {JAVA, LANG, {'T', 'h', 'r', 'o', 'w', 'a', 'b', 'l', 'e'}};
+ final char[][] JAVA_LANG_REFLECT_CONSTRUCTOR = new char[][] {JAVA, LANG, REFLECT, {'C', 'o', 'n', 's', 't', 'r', 'u', 'c', 't', 'o', 'r'}};
+ final char[][] JAVA_IO_PRINTSTREAM = new char[][] {JAVA, IO, {'P', 'r', 'i', 'n', 't', 'S', 't', 'r', 'e', 'a', 'm'}};
+ final char[][] JAVA_IO_SERIALIZABLE = new char[][] {JAVA, IO, {'S', 'e', 'r', 'i', 'a', 'l', 'i', 'z', 'a', 'b', 'l', 'e'}};
+ final char[][] JAVA_LANG_BYTE = new char[][] {JAVA, LANG, "Byte".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_SHORT = new char[][] {JAVA, LANG, "Short".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_CHARACTER = new char[][] {JAVA, LANG, "Character".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_INTEGER = new char[][] {JAVA, LANG, "Integer".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_LONG = new char[][] {JAVA, LANG, "Long".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_FLOAT = new char[][] {JAVA, LANG, "Float".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_DOUBLE = new char[][] {JAVA, LANG, "Double".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_BOOLEAN = new char[][] {JAVA, LANG, "Boolean".toCharArray()}; //$NON-NLS-1$
+ final char[][] JAVA_LANG_VOID = new char[][] {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;
+
+ // Empty Collection which can later assign to null if performance is an issue.
+ final char[] NoChar = new char[0];
+ final char[][] NoCharChar = new char[0][];
+ // Method collections
+ final TypeBinding[] NoParameters = new TypeBinding[0];
+ final ReferenceBinding[] NoExceptions = new ReferenceBinding[0];
+ // 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];
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+ 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);
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class UnresolvedReferenceBinding extends ReferenceBinding {
+ ReferenceBinding resolvedType;
+UnresolvedReferenceBinding(char[][] compoundName, PackageBinding packageBinding) {
+ this.compoundName = compoundName;
+ 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$
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.lookup;
+
+import net.sourceforge.phpdt.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;
+}
+/* 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import net.sourceforge.phpdt.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();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import net.sourceforge.phpdt.core.compiler.*;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.env.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.problem.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+
+import java.io.*;
+import java.util.ArrayList;
+
+public class Parser implements BindingIds, ParserBasicInformation, ITerminalSymbols, CompilerModifiers, OperatorIds, TypeIds {
+ protected ProblemReporter problemReporter;
+ public int firstToken ; // handle for multiple parsing goals
+ public int lastAct ; //handle for multiple parsing goals
+ protected 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 hasReportedError;
+ protected int recoveredStaticInitializerStart;
+ protected int lastIgnoredToken, nextIgnoredToken;
+ protected int lastErrorEndPosition;
+
+ // 1.4 feature
+ protected boolean assertMode = false;
+
+ //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 , .... (what ever is int) ..... stack
+ 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 !
+ //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;
+ //===DATA===DATA===DATA===DATA===DATA===DATA===//
+ public final static byte rhs[] = {0,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,1,1,1,1,3,4,0,1,2,1,1,1,1,
+ 1,1,1,1,1,5,1,2,1,2,2,2,1,1,2,
+ 2,2,4,1,1,1,1,2,1,1,1,1,1,1,1,
+ 1,1,1,1,2,3,3,2,2,1,3,1,3,1,2,
+ 1,1,1,3,0,3,1,1,1,1,1,1,1,4,1,
+ 3,3,7,0,0,0,0,0,2,1,1,1,2,2,4,
+ 4,5,4,4,2,1,2,3,3,1,3,3,1,3,1,
+ 4,0,2,1,2,2,4,1,1,2,5,5,7,7,7,
+ 7,2,2,3,2,2,3,1,2,1,2,1,1,2,2,
+ 1,1,1,1,1,3,3,4,1,3,4,0,1,2,1,
+ 1,1,1,2,3,4,0,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,3,3,2,1,1,1,1,1,1,1,5,7,7,6,
+ 2,3,3,4,1,2,2,1,2,3,2,5,5,7,9,
+ 9,1,1,1,1,3,3,5,2,3,2,3,3,3,5,
+ 1,3,4,1,2,5,2,1,1,1,1,1,1,3,1,
+ 1,3,3,3,3,3,1,1,5,6,8,7,2,0,2,
+ 0,1,3,4,4,1,2,3,2,1,1,2,2,3,3,
+ 4,6,6,4,4,1,1,1,1,2,2,0,1,1,3,
+ 3,1,3,3,1,3,3,1,5,5,4,1,3,3,3,
+ 1,3,3,1,3,3,3,1,3,3,3,3,3,1,3,
+ 3,1,3,1,3,1,3,1,3,1,3,1,5,1,1,
+ 3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,0,1,0,1,0,1,0,1,0,1,
+ 0,1,0,2,0,1,0,1,0,1,0,1,0,1,0,
+ 1,0,1,0,2,0,0,1,0,1,0,1,0,1,0,
+ 1
+ };
+
+
+ public static char asb[] = null;
+ public static char asr[] = null;
+ public static char symbol_index[] = null;
+ private static final String UNEXPECTED_EOF = "Unexpected End Of File" ; //$NON-NLS-1$
+
+ public final static String name[] = { null,
+ "++",//$NON-NLS-1$
+ "--",//$NON-NLS-1$
+ "==",//$NON-NLS-1$
+ "<=",//$NON-NLS-1$
+ ">=",//$NON-NLS-1$
+ "!=",//$NON-NLS-1$
+ "<<",//$NON-NLS-1$
+ ">>",//$NON-NLS-1$
+ ">>>",//$NON-NLS-1$
+ "+=",//$NON-NLS-1$
+ "-=",//$NON-NLS-1$
+ "*=",//$NON-NLS-1$
+ "/=",//$NON-NLS-1$
+ "&=",//$NON-NLS-1$
+ "|=",//$NON-NLS-1$
+ "^=",//$NON-NLS-1$
+ "%=",//$NON-NLS-1$
+ "<<=",//$NON-NLS-1$
+ ">>=",//$NON-NLS-1$
+ ">>>=",//$NON-NLS-1$
+ "||",//$NON-NLS-1$
+ "&&",//$NON-NLS-1$
+ "+",//$NON-NLS-1$
+ "-",//$NON-NLS-1$
+ "!",//$NON-NLS-1$
+ "%",//$NON-NLS-1$
+ "^",//$NON-NLS-1$
+ "&",//$NON-NLS-1$
+ "*",//$NON-NLS-1$
+ "|",//$NON-NLS-1$
+ "~",//$NON-NLS-1$
+ "/",//$NON-NLS-1$
+ ">",//$NON-NLS-1$
+ "<",//$NON-NLS-1$
+ "(",//$NON-NLS-1$
+ ")",//$NON-NLS-1$
+ "{",//$NON-NLS-1$
+ "}",//$NON-NLS-1$
+ "[",//$NON-NLS-1$
+ "]",//$NON-NLS-1$
+ ";",//$NON-NLS-1$
+ "?",//$NON-NLS-1$
+ ":",//$NON-NLS-1$
+ ",",//$NON-NLS-1$
+ ".",//$NON-NLS-1$
+ "=",//$NON-NLS-1$
+ "",//$NON-NLS-1$
+ "$empty",//$NON-NLS-1$
+ "Identifier",//$NON-NLS-1$
+ "abstract",//$NON-NLS-1$
+ "assert",//$NON-NLS-1$
+ "boolean",//$NON-NLS-1$
+ "break",//$NON-NLS-1$
+ "byte",//$NON-NLS-1$
+ "case",//$NON-NLS-1$
+ "catch",//$NON-NLS-1$
+ "char",//$NON-NLS-1$
+ "class",//$NON-NLS-1$
+ "continue",//$NON-NLS-1$
+ "default",//$NON-NLS-1$
+ "do",//$NON-NLS-1$
+ "double",//$NON-NLS-1$
+ "else",//$NON-NLS-1$
+ "extends",//$NON-NLS-1$
+ "false",//$NON-NLS-1$
+ "final",//$NON-NLS-1$
+ "finally",//$NON-NLS-1$
+ "float",//$NON-NLS-1$
+ "for",//$NON-NLS-1$
+ "if",//$NON-NLS-1$
+ "implements",//$NON-NLS-1$
+ "import",//$NON-NLS-1$
+ "instanceof",//$NON-NLS-1$
+ "int",//$NON-NLS-1$
+ "interface",//$NON-NLS-1$
+ "long",//$NON-NLS-1$
+ "native",//$NON-NLS-1$
+ "new",//$NON-NLS-1$
+ "null",//$NON-NLS-1$
+ "package",//$NON-NLS-1$
+ "private",//$NON-NLS-1$
+ "protected",//$NON-NLS-1$
+ "public",//$NON-NLS-1$
+ "return",//$NON-NLS-1$
+ "short",//$NON-NLS-1$
+ "static",//$NON-NLS-1$
+ "strictfp",//$NON-NLS-1$
+ "super",//$NON-NLS-1$
+ "switch",//$NON-NLS-1$
+ "synchronized",//$NON-NLS-1$
+ "this",//$NON-NLS-1$
+ "throw",//$NON-NLS-1$
+ "throws",//$NON-NLS-1$
+ "transient",//$NON-NLS-1$
+ "true",//$NON-NLS-1$
+ "try",//$NON-NLS-1$
+ "void",//$NON-NLS-1$
+ "volatile",//$NON-NLS-1$
+ "while",//$NON-NLS-1$
+ "IntegerLiteral",//$NON-NLS-1$
+ "LongLiteral",//$NON-NLS-1$
+ "FloatingPointLiteral",//$NON-NLS-1$
+ "DoubleLiteral",//$NON-NLS-1$
+ "CharacterLiteral",//$NON-NLS-1$
+ "StringLiteral",//$NON-NLS-1$
+ UNEXPECTED_EOF,
+ "Invalid Character",//$NON-NLS-1$
+ "Goal",//$NON-NLS-1$
+ "MethodBody",//$NON-NLS-1$
+ "ConstructorBody",//$NON-NLS-1$
+ "StaticInitializer",//$NON-NLS-1$
+ "Initializer",//$NON-NLS-1$
+ "Headers",//$NON-NLS-1$
+ "BlockStatements",//$NON-NLS-1$
+ "MethodPushModifiersHeader",//$NON-NLS-1$
+ "CatchHeader",//$NON-NLS-1$
+ "FieldDeclaration",//$NON-NLS-1$
+ "ImportDeclaration",//$NON-NLS-1$
+ "PackageDeclaration",//$NON-NLS-1$
+ "TypeDeclaration",//$NON-NLS-1$
+ "GenericMethodDeclaration",//$NON-NLS-1$
+ "ClassBodyDeclaration",//$NON-NLS-1$
+ "Expression",//$NON-NLS-1$
+ "Type",//$NON-NLS-1$
+ "PrimitiveType",//$NON-NLS-1$
+ "ReferenceType",//$NON-NLS-1$
+ "ClassOrInterfaceType",//$NON-NLS-1$
+ "ArrayType",//$NON-NLS-1$
+ "Name",//$NON-NLS-1$
+ "Dims",//$NON-NLS-1$
+ "ClassType",//$NON-NLS-1$
+ "SimpleName",//$NON-NLS-1$
+ "Header",//$NON-NLS-1$
+ "ClassHeader",//$NON-NLS-1$
+ "InterfaceHeader",//$NON-NLS-1$
+ "MethodHeader",//$NON-NLS-1$
+ "ConstructorHeader",//$NON-NLS-1$
+ "FormalParameter",//$NON-NLS-1$
+ "ImportDeclarations",//$NON-NLS-1$
+ "TypeDeclarations",//$NON-NLS-1$
+ "PackageDeclarationName",//$NON-NLS-1$
+ "SingleTypeImportDeclarationName",//$NON-NLS-1$
+ "TypeImportOnDemandDeclarationName",//$NON-NLS-1$
+ "Modifiers",//$NON-NLS-1$
+ "Modifier",//$NON-NLS-1$
+ "ClassBody",//$NON-NLS-1$
+ "ClassHeaderName",//$NON-NLS-1$
+ "InterfaceTypeList",//$NON-NLS-1$
+ "InterfaceType",//$NON-NLS-1$
+ "ClassBodyDeclarations",//$NON-NLS-1$
+ "Block",//$NON-NLS-1$
+ "VariableDeclarators",//$NON-NLS-1$
+ "VariableDeclarator",//$NON-NLS-1$
+ "VariableDeclaratorId",//$NON-NLS-1$
+ "VariableInitializer",//$NON-NLS-1$
+ "ArrayInitializer",//$NON-NLS-1$
+ "MethodHeaderName",//$NON-NLS-1$
+ "MethodHeaderParameters",//$NON-NLS-1$
+ "MethodPushModifiersHeaderName",//$NON-NLS-1$
+ "ClassTypeList",//$NON-NLS-1$
+ "ConstructorHeaderName",//$NON-NLS-1$
+ "FormalParameterList",//$NON-NLS-1$
+ "ClassTypeElt",//$NON-NLS-1$
+ "StaticOnly",//$NON-NLS-1$
+ "ExplicitConstructorInvocation",//$NON-NLS-1$
+ "Primary",//$NON-NLS-1$
+ "InterfaceBody",//$NON-NLS-1$
+ "InterfaceHeaderName",//$NON-NLS-1$
+ "InterfaceMemberDeclarations",//$NON-NLS-1$
+ "InterfaceMemberDeclaration",//$NON-NLS-1$
+ "VariableInitializers",//$NON-NLS-1$
+ "BlockStatement",//$NON-NLS-1$
+ "Statement",//$NON-NLS-1$
+ "LocalVariableDeclaration",//$NON-NLS-1$
+ "StatementWithoutTrailingSubstatement",//$NON-NLS-1$
+ "StatementNoShortIf",//$NON-NLS-1$
+ "StatementExpression",//$NON-NLS-1$
+ "PostIncrementExpression",//$NON-NLS-1$
+ "PostDecrementExpression",//$NON-NLS-1$
+ "MethodInvocation",//$NON-NLS-1$
+ "ClassInstanceCreationExpression",//$NON-NLS-1$
+ "SwitchBlock",//$NON-NLS-1$
+ "SwitchBlockStatements",//$NON-NLS-1$
+ "SwitchLabels",//$NON-NLS-1$
+ "SwitchBlockStatement",//$NON-NLS-1$
+ "SwitchLabel",//$NON-NLS-1$
+ "ConstantExpression",//$NON-NLS-1$
+ "StatementExpressionList",//$NON-NLS-1$
+ "OnlySynchronized",//$NON-NLS-1$
+ "Catches",//$NON-NLS-1$
+ "Finally",//$NON-NLS-1$
+ "CatchClause",//$NON-NLS-1$
+ "PushLPAREN",//$NON-NLS-1$
+ "PushRPAREN",//$NON-NLS-1$
+ "PrimaryNoNewArray",//$NON-NLS-1$
+ "FieldAccess",//$NON-NLS-1$
+ "ArrayAccess",//$NON-NLS-1$
+ "ClassInstanceCreationExpressionName",//$NON-NLS-1$
+ "ArgumentList",//$NON-NLS-1$
+ "DimWithOrWithOutExprs",//$NON-NLS-1$
+ "DimWithOrWithOutExpr",//$NON-NLS-1$
+ "DimsLoop",//$NON-NLS-1$
+ "OneDimLoop",//$NON-NLS-1$
+ "PostfixExpression",//$NON-NLS-1$
+ "UnaryExpression",//$NON-NLS-1$
+ "UnaryExpressionNotPlusMinus",//$NON-NLS-1$
+ "MultiplicativeExpression",//$NON-NLS-1$
+ "AdditiveExpression",//$NON-NLS-1$
+ "ShiftExpression",//$NON-NLS-1$
+ "RelationalExpression",//$NON-NLS-1$
+ "EqualityExpression",//$NON-NLS-1$
+ "AndExpression",//$NON-NLS-1$
+ "ExclusiveOrExpression",//$NON-NLS-1$
+ "InclusiveOrExpression",//$NON-NLS-1$
+ "ConditionalAndExpression",//$NON-NLS-1$
+ "ConditionalOrExpression",//$NON-NLS-1$
+ "ConditionalExpression",//$NON-NLS-1$
+ "AssignmentExpression",//$NON-NLS-1$
+ "LeftHandSide",//$NON-NLS-1$
+ "AssignmentOperator"//$NON-NLS-1$
+ };
+
+ public static short check_table[] = null;
+ public static char lhs[] = null;
+ public static char action[] = lhs;
+ private final static String FILEPREFIX = "parser"; //$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, boolean assertMode) {
+
+ this.problemReporter = problemReporter;
+ this.optimizeStringLiterals = optimizeStringLiterals;
+ this.assertMode = assertMode;
+ this.initializeScanner();
+ astLengthStack = new int[50];
+ expressionLengthStack = new int[30];
+ intStack = new int[50];
+ identifierStack = new char[30][];
+ identifierLengthStack = new int[30];
+ nestedMethod = new int[30];
+ realBlockStack = new int[30];
+ identifierPositionStack = new long[30];
+ variablesCounter = new int[30];
+}
+/**
+ *
+ * INTERNAL USE-ONLY
+ */
+protected void adjustInterfaceModifiers() {
+ intStack[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
+ //i.e. it has not been decremented yet.
+
+ ArrayInitializer ai = new ArrayInitializer();
+ if (length != 0) {
+ expressionPtr -= length;
+ System.arraycopy(expressionStack, expressionPtr + 1, ai.expressions = new Expression[length], 0, length);
+ }
+ pushOnExpressionStack(ai);
+ //positionning
+ ai.sourceEnd = endStatementPosition;
+ int searchPosition = length == 0 ? endPosition : ai.expressions[0].sourceStart;
+ try {
+ //does not work with comments(that contain '{') nor '{' describes as a unicode....
+ while (scanner.source[--searchPosition] != '{') {
+ }
+ } catch (IndexOutOfBoundsException ex) {
+ //should never occur (except for strange cases like whose describe above)
+ searchPosition = (length == 0 ? endPosition : ai.expressions[0].sourceStart) - 1;
+ }
+ ai.sourceStart = searchPosition;
+}
+protected static int asi(int state) {
+
+ return asb[original_state(state)];
+}
+protected void blockReal() {
+ // See consumeLocalVariableDeclarationStatement in case of change: duplicated code
+ // increment the amount of declared variables for this block
+ realBlockStack[realBlockPtr]++;
+}
+private final static void buildFileFor(String filename, String tag, String[] tokens, boolean isShort) throws java.io.IOException {
+
+ //transform the String tokens into chars before dumping then into file
+
+ int i = 0;
+ //read upto the tag
+ while (!tokens[i++].equals(tag)) {}
+ //read upto the }
+ char[] chars = new char[tokens.length]; //can't be bigger
+ int ic = 0;
+ String token;
+ while (!(token = tokens[i++]).equals("}")) { //$NON-NLS-1$
+ int c = Integer.parseInt(token);
+ if (isShort)
+ c += 32768;
+ chars[ic++] = (char) c;
+ }
+
+ //resize
+ System.arraycopy(chars, 0, chars = new char[ic], 0, ic);
+
+ buildFileForTable(filename, chars);
+}
+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$
+}
+public final static void buildFilesFromLPG(String dataFilename) 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;
+ buildFileFor(prefix + (++i) + ".rsc", "lhs", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileFor(prefix + (++i) + ".rsc", "check_table", tokens, true); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileFor(prefix + (++i) + ".rsc", "asb", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileFor(prefix + (++i) + ".rsc", "asr", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
+ buildFileFor(prefix + (++i) + ".rsc", "symbol_index", tokens, false); //$NON-NLS-2$ //$NON-NLS-1$
+ 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
+ */
+ lastCheckPoint = 0;
+
+ RecoveredElement element = null;
+ if (referenceContext instanceof CompilationUnitDeclaration){
+ element = new RecoveredUnit(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
+ compilationUnit.currentPackage = null;
+ compilationUnit.imports = null;
+ compilationUnit.types = null;
+ currentToken = 0;
+ listLength = 0;
+ return element;
+ }
+ if (compilationUnit.currentPackage != null){
+ lastCheckPoint = compilationUnit.currentPackage.declarationSourceEnd+1;
+ }
+ if (compilationUnit.imports != null){
+ lastCheckPoint = compilationUnit.imports[compilationUnit.imports.length -1].declarationSourceEnd+1;
+ }
+ } else {
+ if (referenceContext instanceof AbstractMethodDeclaration){
+ element = new RecoveredMethod((AbstractMethodDeclaration) referenceContext, null, 0, this);
+ lastCheckPoint = ((AbstractMethodDeclaration) referenceContext).bodyStart;
+ } else {
+ /* Initializer bodies are parsed in the context of the type declaration, we must thus search it inside */
+ if (referenceContext instanceof TypeDeclaration){
+ TypeDeclaration type = (TypeDeclaration) referenceContext;
+ for (int i = 0; i < type.fields.length; i++){
+ FieldDeclaration field = type.fields[i];
+ if (!field.isField()
+ && field.declarationSourceStart <= scanner.initialPosition
+ && scanner.initialPosition <= field.declarationSourceEnd
+ && scanner.eofPosition <= field.declarationSourceEnd+1){
+ element = new RecoveredInitializer((Initializer) field, null, 1, this);
+ lastCheckPoint = field.declarationSourceStart;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (element == null) return element;
+
+ for(int i = 0; i <= astPtr; i++){
+ AstNode node = astStack[i];
+ if (node instanceof AbstractMethodDeclaration){
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) node;
+ if (method.declarationSourceEnd == 0){
+ element = element.add(method, 0);
+ lastCheckPoint = method.bodyStart;
+ } else {
+ element = element.add(method, 0);
+ lastCheckPoint = method.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof Initializer){
+ Initializer initializer = (Initializer) node;
+ if (initializer.declarationSourceEnd == 0){
+ element = element.add(initializer, 1);
+ lastCheckPoint = initializer.bodyStart;
+ } else {
+ element = element.add(initializer, 0);
+ 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){
+ lastCheckPoint = field.sourceEnd + 1;
+ } else {
+ lastCheckPoint = field.initialization.sourceEnd + 1;
+ }
+ } else {
+ element = element.add(field, 0);
+ lastCheckPoint = field.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof TypeDeclaration){
+ TypeDeclaration type = (TypeDeclaration) node;
+ if (type.declarationSourceEnd == 0){
+ element = element.add(type, 0);
+ lastCheckPoint = type.bodyStart;
+ } else {
+ element = element.add(type, 0);
+ lastCheckPoint = type.declarationSourceEnd + 1;
+ }
+ continue;
+ }
+ if (node instanceof ImportReference){
+ ImportReference importRef = (ImportReference) node;
+ element = element.add(importRef, 0);
+ lastCheckPoint = importRef.declarationSourceEnd + 1;
+ }
+ }
+ return element;
+}
+protected static short check(int i) {
+ return check_table[i - (NUM_RULES + 1)];
+}
+/*
+ * Reconsider the entire source looking for inconsistencies in {} () []
+ */
+public boolean checkAndReportBracketAnomalies(ProblemReporter problemReporter) {
+
+ scanner.wasAcr = false;
+ boolean anomaliesDetected = false;
+ try {
+ char[] source = scanner.source;
+ int[] leftCount = {0, 0, 0};
+ int[] rightCount = {0, 0, 0};
+ int[] depths = {0, 0, 0};
+ int[][] leftPositions = new int[][] {new int[10], new int[10], new int[10]};
+ int[][] leftDepths = new int[][] {new int[10], new int[10], new int[10]};
+ int[][] rightPositions = new int[][] {new int[10], new int[10], new int[10]};
+ int[][] rightDepths = new int[][] {new int[10], new int[10], new int[10]};
+ scanner.currentPosition = scanner.initialPosition; //starting point (first-zero-based char)
+ while (scanner.currentPosition < scanner.eofPosition) { //loop for jumping over comments
+ try {
+ // ---------Consume white space and handles startPosition---------
+ boolean isWhiteSpace;
+ do {
+ scanner.startPosition = scanner.currentPosition;
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ isWhiteSpace = scanner.jumpOverUnicodeWhiteSpace();
+ } else {
+ if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
+ if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
+ // only record line positions we have not recorded yet
+ scanner.pushLineSeparator();
+ }
+ }
+ isWhiteSpace = Character.isWhitespace(scanner.currentCharacter);
+ }
+ } while (isWhiteSpace && (scanner.currentPosition < scanner.eofPosition));
+
+ // -------consume token until } is found---------
+
+ switch (scanner.currentCharacter) {
+ case '{' :
+ {
+ int index = leftCount[CurlyBracket] ++;
+ if (index == leftPositions[CurlyBracket].length) {
+ System.arraycopy(leftPositions[CurlyBracket], 0, (leftPositions[CurlyBracket] = new int[index * 2]), 0, index);
+ System.arraycopy(leftDepths[CurlyBracket], 0, (leftDepths[CurlyBracket] = new int[index * 2]), 0, index);
+ }
+ leftPositions[CurlyBracket][index] = scanner.startPosition;
+ leftDepths[CurlyBracket][index] = depths[CurlyBracket] ++;
+ }
+ break;
+ case '}' :
+ {
+ int index = rightCount[CurlyBracket] ++;
+ if (index == rightPositions[CurlyBracket].length) {
+ System.arraycopy(rightPositions[CurlyBracket], 0, (rightPositions[CurlyBracket] = new int[index * 2]), 0, index);
+ System.arraycopy(rightDepths[CurlyBracket], 0, (rightDepths[CurlyBracket] = new int[index * 2]), 0, index);
+ }
+ rightPositions[CurlyBracket][index] = scanner.startPosition;
+ rightDepths[CurlyBracket][index] = --depths[CurlyBracket];
+ }
+ break;
+ case '(' :
+ {
+ int index = leftCount[RoundBracket] ++;
+ if (index == leftPositions[RoundBracket].length) {
+ System.arraycopy(leftPositions[RoundBracket], 0, (leftPositions[RoundBracket] = new int[index * 2]), 0, index);
+ System.arraycopy(leftDepths[RoundBracket], 0, (leftDepths[RoundBracket] = new int[index * 2]), 0, index);
+ }
+ leftPositions[RoundBracket][index] = scanner.startPosition;
+ leftDepths[RoundBracket][index] = depths[RoundBracket] ++;
+ }
+ break;
+ case ')' :
+ {
+ int index = rightCount[RoundBracket] ++;
+ if (index == rightPositions[RoundBracket].length) {
+ System.arraycopy(rightPositions[RoundBracket], 0, (rightPositions[RoundBracket] = new int[index * 2]), 0, index);
+ System.arraycopy(rightDepths[RoundBracket], 0, (rightDepths[RoundBracket] = new int[index * 2]), 0, index);
+ }
+ rightPositions[RoundBracket][index] = scanner.startPosition;
+ rightDepths[RoundBracket][index] = --depths[RoundBracket];
+ }
+ break;
+ case '[' :
+ {
+ int index = leftCount[SquareBracket] ++;
+ if (index == leftPositions[SquareBracket].length) {
+ System.arraycopy(leftPositions[SquareBracket], 0, (leftPositions[SquareBracket] = new int[index * 2]), 0, index);
+ System.arraycopy(leftDepths[SquareBracket], 0, (leftDepths[SquareBracket] = new int[index * 2]), 0, index);
+ }
+ leftPositions[SquareBracket][index] = scanner.startPosition;
+ leftDepths[SquareBracket][index] = depths[SquareBracket] ++;
+ }
+ break;
+ case ']' :
+ {
+ int index = rightCount[SquareBracket] ++;
+ if (index == rightPositions[SquareBracket].length) {
+ System.arraycopy(rightPositions[SquareBracket], 0, (rightPositions[SquareBracket] = new int[index * 2]), 0, index);
+ System.arraycopy(rightDepths[SquareBracket], 0, (rightDepths[SquareBracket] = new int[index * 2]), 0, index);
+ }
+ rightPositions[SquareBracket][index] = scanner.startPosition;
+ rightDepths[SquareBracket][index] = --depths[SquareBracket];
+ }
+ break;
+ case '\'' :
+ {
+ if (scanner.getNextChar('\\')) {
+ scanner.scanEscapeCharacter();
+ } else { // consume next character
+ scanner.unicodeAsBackSlash = false;
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ scanner.getNextUnicodeChar();
+ } else {
+ if (scanner.withoutUnicodePtr != 0) {
+ scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
+ }
+ }
+ }
+ scanner.getNextChar('\'');
+ break;
+ }
+ case '"' : // consume next character
+ scanner.unicodeAsBackSlash = false;
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ scanner.getNextUnicodeChar();
+ } else {
+ if (scanner.withoutUnicodePtr != 0) {
+ scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
+ }
+ }
+ while (scanner.currentCharacter != '"') {
+ if (scanner.currentCharacter == '\r') {
+ if (source[scanner.currentPosition] == '\n')
+ scanner.currentPosition++;
+ break; // the string cannot go further that the line
+ }
+ if (scanner.currentCharacter == '\n') {
+ break; // the string cannot go further that the line
+ }
+ if (scanner.currentCharacter == '\\') {
+ scanner.scanEscapeCharacter();
+ }
+ // consume next character
+ scanner.unicodeAsBackSlash = false;
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ scanner.getNextUnicodeChar();
+ } else {
+ if (scanner.withoutUnicodePtr != 0) {
+ scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
+ }
+ }
+ }
+ break;
+ case '/' :
+ {
+ int test;
+ if ((test = scanner.getNextChar('/', '*')) == 0) { //line comment
+ //get the next char
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ scanner.currentPosition++;
+ while (source[scanner.currentPosition] == 'u') {
+ scanner.currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value
+ scanner.currentCharacter = 'A';
+ } //something different from \n and \r
+ else {
+ scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ while (scanner.currentCharacter != '\r' && scanner.currentCharacter != '\n') {
+ //get the next char
+ scanner.startPosition = scanner.currentPosition;
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ scanner.currentPosition++;
+ while (source[scanner.currentPosition] == 'u') {
+ scanner.currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value
+ scanner.currentCharacter = 'A';
+ } //something different from \n and \r
+ else {
+ scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ }
+ if (scanner.recordLineSeparator && ((scanner.currentCharacter == '\r') || (scanner.currentCharacter == '\n'))) {
+ if (scanner.lineEnds[scanner.linePtr] < scanner.startPosition) {
+ // only record line positions we have not recorded yet
+ scanner.pushLineSeparator();
+ }
+ }
+ break;
+ }
+ if (test > 0) { //traditional and annotation comment
+ boolean star = false;
+ // consume next character
+ scanner.unicodeAsBackSlash = false;
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ scanner.getNextUnicodeChar();
+ } else {
+ if (scanner.withoutUnicodePtr != 0) {
+ scanner.withoutUnicodeBuffer[++scanner.withoutUnicodePtr] = scanner.currentCharacter;
+ }
+ }
+ if (scanner.currentCharacter == '*') {
+ star = true;
+ }
+ //get the next char
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ scanner.currentPosition++;
+ while (source[scanner.currentPosition] == 'u') {
+ scanner.currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value
+ scanner.currentCharacter = 'A';
+ } //something different from * and /
+ else {
+ scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ //loop until end of comment */
+ while ((scanner.currentCharacter != '/') || (!star)) {
+ star = scanner.currentCharacter == '*';
+ //get next char
+ if (((scanner.currentCharacter = source[scanner.currentPosition++]) == '\\') && (source[scanner.currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ scanner.currentPosition++;
+ while (source[scanner.currentPosition] == 'u') {
+ scanner.currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c1 < 0 || (c2 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c2 < 0 || (c3 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c3 < 0 || (c4 = Character.getNumericValue(source[scanner.currentPosition++])) > 15 || c4 < 0) { //error don't care of the value
+ scanner.currentCharacter = 'A';
+ } //something different from * and /
+ else {
+ scanner.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ }
+ break;
+ }
+ break;
+ }
+ default :
+ if (Character.isJavaIdentifierStart(scanner.currentCharacter)) {
+ scanner.scanIdentifierOrKeyword();
+ break;
+ }
+ if (Character.isDigit(scanner.currentCharacter)) {
+ scanner.scanNumber(false);
+ break;
+ }
+ }
+ //-----------------end switch while try--------------------
+ } catch (IndexOutOfBoundsException e) {
+ break; // read until EOF
+ } catch (InvalidInputException e) {
+ return false; // no clue
+ }
+ }
+ if (scanner.recordLineSeparator) {
+ compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
+ }
+
+ // check placement anomalies against other kinds of brackets
+ for (int kind = 0; kind < BracketKinds; kind++) {
+ for (int leftIndex = leftCount[kind] - 1; leftIndex >= 0; leftIndex--) {
+ int start = leftPositions[kind][leftIndex]; // deepest first
+ // find matching closing bracket
+ int depth = leftDepths[kind][leftIndex];
+ int end = -1;
+ for (int i = 0; i < rightCount[kind]; i++) {
+ int pos = rightPositions[kind][i];
+ // want matching bracket further in source with same depth
+ if ((pos > start) && (depth == rightDepths[kind][i])) {
+ end = pos;
+ break;
+ }
+ }
+ if (end < 0) { // did not find a good closing match
+ problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult);
+ return true;
+ }
+ // check if even number of opening/closing other brackets in between this pair of brackets
+ int balance = 0;
+ for (int otherKind = 0;(balance == 0) && (otherKind < BracketKinds); otherKind++) {
+ for (int i = 0; i < leftCount[otherKind]; i++) {
+ int pos = leftPositions[otherKind][i];
+ if ((pos > start) && (pos < end))
+ balance++;
+ }
+ for (int i = 0; i < rightCount[otherKind]; i++) {
+ int pos = rightPositions[otherKind][i];
+ if ((pos > start) && (pos < end))
+ balance--;
+ }
+ if (balance != 0) {
+ problemReporter.unmatchedBracket(start, referenceContext, compilationUnit.compilationResult); //bracket anomaly
+ return true;
+ }
+ }
+ }
+ // too many opening brackets ?
+ for (int i = rightCount[kind]; i < leftCount[kind]; i++) {
+ anomaliesDetected = true;
+ problemReporter.unmatchedBracket(leftPositions[kind][leftCount[kind] - i - 1], referenceContext, compilationUnit.compilationResult);
+ }
+ // too many closing brackets ?
+ for (int i = leftCount[kind]; i < rightCount[kind]; i++) {
+ anomaliesDetected = true;
+ problemReporter.unmatchedBracket(rightPositions[kind][i], referenceContext, compilationUnit.compilationResult);
+ }
+ if (anomaliesDetected) return true;
+ }
+
+ return anomaliesDetected;
+ } catch (ArrayStoreException e) { // jdk1.2.2 jit bug
+ return anomaliesDetected;
+ } catch (NullPointerException e) { // jdk1.2.2 jit bug
+ return anomaliesDetected;
+ }
+}
+public final void checkAndSetModifiers(int flag){
+ /*modify the current modifiers buffer.
+ When the startPosition of the modifiers is 0
+ 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 ((modifiers & flag) != 0){ // duplicate modifier
+ modifiers |= AccAlternateModifierProblem;
+ }
+ modifiers |= flag;
+
+ if (modifiersSourceStart < 0) modifiersSourceStart = scanner.startPosition;
+}
+public void checkAnnotation() {
+
+ boolean deprecated = false;
+ boolean checkDeprecated = false;
+ int lastAnnotationIndex = -1;
+
+ //since jdk1.2 look only in the last java doc comment...
+ found : for (lastAnnotationIndex = scanner.commentPtr; lastAnnotationIndex >= 0; lastAnnotationIndex--){
+ //look for @deprecated into the first javadoc comment preceeding the declaration
+ int commentSourceStart = scanner.commentStarts[lastAnnotationIndex];
+ // javadoc only (non javadoc comment have negative end positions.)
+ if (modifiersSourceStart != -1 && modifiersSourceStart < commentSourceStart) {
+ continue;
+ }
+ if (scanner.commentStops[lastAnnotationIndex] < 0) {
+ break found;
+ }
+ checkDeprecated = true;
+ int commentSourceEnd = scanner.commentStops[lastAnnotationIndex] - 1; //stop is one over
+ char[] comment = scanner.source;
+
+ for (int i = commentSourceStart + 3; i < commentSourceEnd - 10; i++) {
+ if ((comment[i] == '@')
+ && (comment[i + 1] == 'd')
+ && (comment[i + 2] == 'e')
+ && (comment[i + 3] == 'p')
+ && (comment[i + 4] == 'r')
+ && (comment[i + 5] == 'e')
+ && (comment[i + 6] == 'c')
+ && (comment[i + 7] == 'a')
+ && (comment[i + 8] == 't')
+ && (comment[i + 9] == 'e')
+ && (comment[i + 10] == 'd')) {
+ // ensure the tag is properly ended: either followed by a space, a tab, line end or asterisk.
+ int nextPos = i+11;
+ deprecated = (comment[nextPos] == ' ') || (comment[nextPos] == '\t') || (comment[nextPos] == '\n') || (comment[nextPos] == '\r') || (comment[nextPos] == '*');
+ break found;
+ }
+ }
+ break found;
+ }
+ if (deprecated) {
+ checkAndSetModifiers(AccDeprecated);
+ }
+ // modify the modifier source start to point at the first comment
+ if (lastAnnotationIndex >= 0 && checkDeprecated) {
+ modifiersSourceStart = scanner.commentStarts[lastAnnotationIndex];
+ }
+}
+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 = astLengthStack[astLengthPtr--]) == 1)
+ && (astStack[astPtr] == null)) {
+ //NO ClassBody
+ astPtr--;
+ if (alwaysQualified) {
+ alloc = new QualifiedAllocationExpression();
+ } else {
+ alloc = new AllocationExpression();
+ }
+ alloc.sourceEnd = endPosition; //the position has been stored explicitly
+
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ 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 = intStack[intPtr--];
+ pushOnExpressionStack(alloc);
+ } else {
+ dispatchDeclarationInto(length);
+ AnonymousLocalTypeDeclaration anonymousTypeDeclaration = (AnonymousLocalTypeDeclaration) astStack[astPtr];
+ anonymousTypeDeclaration.declarationSourceEnd = endStatementPosition;
+ anonymousTypeDeclaration.bodyEnd = endStatementPosition;
+ if (anonymousTypeDeclaration.allocation != null) {
+ anonymousTypeDeclaration.allocation.sourceEnd = endStatementPosition;
+ }
+ astPtr--;
+ astLengthPtr--;
+
+ // mark fields and initializer with local type mark if needed
+ markFieldsWithLocalType(anonymousTypeDeclaration);
+ }
+}
+protected final void concatExpressionLists() {
+ expressionLengthStack[--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.
+ */
+
+ astLengthStack[astLengthPtr - 1] += astLengthStack[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 (currentElement == null){
+ return; // should never occur, this consumeRule is only used in recovery mode
+ }
+ if (currentToken == TokenNameLBRACE){
+ // beginning of an anonymous type
+ AnonymousLocalTypeDeclaration anonymousType = new AnonymousLocalTypeDeclaration(this.compilationUnit.compilationResult);
+ anonymousType.sourceStart = intStack[intPtr--];
+ anonymousType.sourceEnd = rParenPos; // closing parenthesis
+ lastCheckPoint = anonymousType.bodyStart = scanner.currentPosition;
+ currentElement = currentElement.add(anonymousType, 0);
+ lastIgnoredToken = -1;
+ currentToken = 0; // opening brace already taken into account
+ return;
+ }
+ lastCheckPoint = scanner.startPosition; // force to restart at this exact position
+ 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 =
+ expressionStack[expressionPtr] =
+ new ArrayReference(
+ getUnspecifiedReferenceOptimized(),
+ expressionStack[expressionPtr]);
+ } else {
+ expressionPtr--;
+ expressionLengthPtr--;
+ exp =
+ expressionStack[expressionPtr] =
+ new ArrayReference(
+ expressionStack[expressionPtr],
+ expressionStack[expressionPtr + 1]);
+ }
+ exp.sourceEnd = endPosition;
+}
+protected void consumeArrayCreationExpression() {
+ // ArrayCreationExpression ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializeropt
+ // ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializeropt
+
+ int length;
+ ArrayAllocationExpression aae = new ArrayAllocationExpression();
+ if (expressionLengthStack[expressionLengthPtr] != 0) {
+ expressionLengthPtr -- ;
+ aae.initializer = (ArrayInitializer) expressionStack[expressionPtr--];
+ } else {
+ expressionLengthPtr--;
+ }
+
+ aae.type = getTypeReference(0);
+ length = (expressionLengthStack[expressionLengthPtr--]);
+ expressionPtr -= length ;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr+1,
+ aae.dimensions = new Expression[length],
+ 0,
+ length);
+ aae.sourceStart = intStack[intPtr--];
+ if (aae.initializer == null) {
+ aae.sourceEnd = endPosition;
+ } else {
+ aae.sourceEnd = aae.initializer.sourceEnd ;
+ }
+ pushOnExpressionStack(aae);
+}
+protected void consumeArrayInitializer() {
+ // ArrayInitializer ::= '{' VariableInitializers '}'
+ // ArrayInitializer ::= '{' VariableInitializers , '}'
+
+ arrayInitializer(expressionLengthStack[expressionLengthPtr--]);
+}
+
+protected void consumeAssertStatement() {
+ // AssertStatement ::= 'assert' Expression ':' Expression ';'
+ expressionLengthPtr-=2;
+ pushOnAstStack(new AssertStatement(expressionStack[expressionPtr--], expressionStack[expressionPtr--], intStack[intPtr--]));
+}
+
+protected void consumeAssignment() {
+ // Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression
+ //optimize the push/pop
+
+ int op = intStack[intPtr--] ; //<--the encoded operator
+
+ expressionPtr -- ; expressionLengthPtr -- ;
+ expressionStack[expressionPtr] =
+ (op != EQUAL ) ?
+ new CompoundAssignment(
+ expressionStack[expressionPtr] ,
+ expressionStack[expressionPtr+1],
+ op,
+ scanner.startPosition - 1) :
+ new Assignment(
+ expressionStack[expressionPtr] ,
+ expressionStack[expressionPtr+1],
+ scanner.startPosition - 1);
+}
+protected void consumeAssignmentOperator(int pos) {
+ // AssignmentOperator ::= '='
+ // AssignmentOperator ::= '*='
+ // AssignmentOperator ::= '/='
+ // AssignmentOperator ::= '%='
+ // AssignmentOperator ::= '+='
+ // AssignmentOperator ::= '-='
+ // AssignmentOperator ::= '<<='
+ // AssignmentOperator ::= '>>='
+ // AssignmentOperator ::= '>>>='
+ // AssignmentOperator ::= '&='
+ // AssignmentOperator ::= '^='
+ // AssignmentOperator ::= '|='
+
+ try {
+ intStack[++intPtr] = pos;
+ } catch (IndexOutOfBoundsException e) {
+ //intPtr is correct
+ int oldStackLength = intStack.length;
+ int oldStack[] = intStack;
+ intStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldStack, 0, intStack, 0, oldStackLength);
+ intStack[intPtr] = 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
+
+ expressionPtr--;
+ expressionLengthPtr--;
+ if (op == OR_OR) {
+ expressionStack[expressionPtr] =
+ new OR_OR_Expression(
+ expressionStack[expressionPtr],
+ expressionStack[expressionPtr + 1],
+ op);
+ } else {
+ if (op == AND_AND) {
+ expressionStack[expressionPtr] =
+ new AND_AND_Expression(
+ expressionStack[expressionPtr],
+ expressionStack[expressionPtr + 1],
+ op);
+ } else {
+ // look for "string1" + "string2"
+ if ((op == PLUS) && optimizeStringLiterals) {
+ Expression expr1, expr2;
+ expr1 = expressionStack[expressionPtr];
+ expr2 = expressionStack[expressionPtr + 1];
+ if (expr1 instanceof StringLiteral) {
+ if (expr2 instanceof CharLiteral) { // string+char
+ expressionStack[expressionPtr] =
+ ((StringLiteral) expr1).extendWith((CharLiteral) expr2);
+ } else if (expr2 instanceof StringLiteral) { //string+string
+ expressionStack[expressionPtr] =
+ ((StringLiteral) expr1).extendWith((StringLiteral) expr2);
+ } else {
+ expressionStack[expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else {
+ expressionStack[expressionPtr] = new BinaryExpression(expr1, expr2, PLUS);
+ }
+ } else {
+ expressionStack[expressionPtr] =
+ new BinaryExpression(
+ expressionStack[expressionPtr],
+ expressionStack[expressionPtr + 1],
+ op);
+ }
+ }
+ }
+}
+protected void consumeBlock() {
+ // Block ::= OpenBlock '{' BlockStatementsopt '}'
+ // simpler action for empty blocks
+
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) == 0) { // empty block
+ pushOnAstStack(Block.EmptyWith(intStack[intPtr--], endStatementPosition));
+ realBlockPtr--; // still need to pop the block variable counter
+ } else {
+ Block bk = new Block(realBlockStack[realBlockPtr--]);
+ astPtr -= length;
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ bk.statements = new Statement[length],
+ 0,
+ length);
+ pushOnAstStack(bk);
+ bk.sourceStart = intStack[intPtr--];
+ bk.sourceEnd = endStatementPosition;
+ }
+}
+protected void consumeBlockStatements() {
+ // BlockStatements ::= BlockStatements BlockStatement
+ concatNodeLists();
+}
+protected void consumeCaseLabel() {
+ // SwitchLabel ::= 'case' ConstantExpression ':'
+ expressionLengthPtr--;
+ pushOnAstStack(new Case(intStack[intPtr--], expressionStack[expressionPtr--]));
+}
+protected void consumeCastExpression() {
+ // CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN UnaryExpression
+ // CastExpression ::= PushLPAREN Name Dims PushRPAREN UnaryExpressionNotPlusMinus
+
+ //intStack : posOfLeftParen dim posOfRightParen
+
+ //optimize the push/pop
+
+ Expression exp, cast, castType;
+ int end = intStack[intPtr--];
+ expressionStack[expressionPtr] = cast = new CastExpression(exp = expressionStack[expressionPtr], castType = getTypeReference(intStack[intPtr--]));
+ castType.sourceEnd = end - 1;
+ castType.sourceStart = (cast.sourceStart = intStack[intPtr--]) + 1;
+ cast.sourceEnd = exp.sourceEnd;
+}
+protected void consumeCastExpressionLL1() {
+ //CastExpression ::= '(' Expression ')' UnaryExpressionNotPlusMinus
+ // Expression is used in order to make the grammar LL1
+
+ //optimize push/pop
+
+ Expression castType,cast,exp;
+ expressionPtr--;
+ expressionStack[expressionPtr] =
+ cast = new CastExpression( exp=expressionStack[expressionPtr+1] ,
+ castType = getTypeReference(expressionStack[expressionPtr]));
+ expressionLengthPtr -- ;
+ updateSourcePosition(castType);
+ cast.sourceStart=castType.sourceStart;
+ cast.sourceEnd=exp.sourceEnd;
+ castType.sourceStart++;
+ castType.sourceEnd--;
+ }
+protected void consumeCatches() {
+ // Catches ::= Catches CatchClause
+ optimizedConcatNodeLists();
+}
+protected void consumeCatchHeader() {
+ // CatchDeclaration ::= 'catch' '(' FormalParameter ')' '{'
+
+ if (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 (!(currentElement instanceof RecoveredBlock)){
+ return;
+ }
+ // exception argument is already on astStack
+ ((RecoveredBlock)currentElement).attach(
+ new RecoveredLocalVariable((Argument)astStack[astPtr--], currentElement, 0)); // insert catch variable in catch block
+ lastCheckPoint = scanner.startPosition; // force to restart at this exact position
+ restartRecovery = true; // request to restart from here on
+ lastIgnoredToken = -1;
+}
+protected void consumeClassBodyDeclaration() {
+ // ClassBodyDeclaration ::= Diet Block
+ //push an Initializer
+ //optimize the push/pop
+ nestedMethod[nestedType]--;
+ Initializer initializer = new Initializer((Block) astStack[astPtr], 0);
+ intPtr--; // pop sourcestart left on the stack by consumeNestedMethod.
+ realBlockPtr--; // pop the block variable counter left on the stack by consumeNestedMethod
+ int javadocCommentStart = intStack[intPtr--];
+ if (javadocCommentStart != -1) {
+ initializer.declarationSourceStart = javadocCommentStart;
+ }
+ astStack[astPtr] = initializer;
+ initializer.sourceEnd = endStatementPosition;
+ initializer.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+}
+protected void consumeClassBodyDeclarations() {
+ // ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration
+ concatNodeLists();
+}
+protected void consumeClassBodyDeclarationsopt() {
+ // ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations
+ nestedType-- ;
+}
+protected void consumeClassBodyopt() {
+ // ClassBodyopt ::= $empty
+ pushOnAstStack(null);
+ endPosition = scanner.startPosition - 1;
+}
+protected void consumeClassDeclaration() {
+ // ClassDeclaration ::= ClassHeader ClassBody
+
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ //there are length declarations
+ //dispatch according to the type of the declarations
+ dispatchDeclarationInto(length);
+ }
+
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+
+ // mark fields and initializer with local type mark if needed
+ markFieldsWithLocalType(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) {
+ boolean insideFieldInitializer = false;
+ if (diet) {
+ for (int i = nestedType; i > 0; i--){
+ if (variablesCounter[i] > 0) {
+ insideFieldInitializer = true;
+ break;
+ }
+ }
+ }
+ typeDecl.createsInternalConstructor(!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 = endStatementPosition;
+ typeDecl.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+}
+protected void consumeClassHeader() {
+ // ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt
+
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ if (currentToken == TokenNameLBRACE) {
+ typeDecl.bodyStart = scanner.currentPosition;
+ }
+ if (currentElement != null) {
+ restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+ // flush the comments related to the class header
+ scanner.commentPtr = -1;
+}
+protected void consumeClassHeaderExtends() {
+ // ClassHeaderExtends ::= 'extends' ClassType
+ // There is a class declaration on the top of stack
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ //superclass
+ typeDecl.superclass = getTypeReference(0);
+ typeDecl.bodyStart = typeDecl.superclass.sourceEnd + 1;
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = typeDecl.bodyStart;
+ }
+}
+protected void consumeClassHeaderImplements() {
+ // ClassHeaderImplements ::= 'implements' InterfaceTypeList
+ int length = astLengthStack[astLengthPtr--];
+ //super interfaces
+ astPtr -= length;
+ // There is a class declaration on the top of stack
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ typeDecl.superInterfaces = new TypeReference[length],
+ 0,
+ length);
+ typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
+ listLength = 0; // reset after having read super-interfaces
+ // recovery
+ if (currentElement != null) { // is recovering
+ lastCheckPoint = typeDecl.bodyStart;
+ }
+}
+protected void consumeClassHeaderName() {
+ // ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+ TypeDeclaration typeDecl;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+ markCurrentMethodWithLocalType();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ 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 = intStack[intPtr--];
+ intPtr--; // remove the end position of the class token
+
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.modifiersSourceStart >= 0) {
+ typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+
+ listLength = 0; // will be updated when reading super-interfaces
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = typeDecl.bodyStart;
+ currentElement = currentElement.add(typeDecl, 0);
+ lastIgnoredToken = -1;
+ }
+}
+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....
+
+ expressionLengthPtr--;
+ QualifiedAllocationExpression qae =
+ (QualifiedAllocationExpression) expressionStack[expressionPtr--];
+ qae.enclosingInstance = expressionStack[expressionPtr];
+ expressionStack[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 */
+ 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
+
+ expressionPtr -= 2;
+ expressionLengthPtr -= 2;
+ expressionStack[expressionPtr] =
+ new ConditionalExpression(
+ expressionStack[expressionPtr],
+ expressionStack[expressionPtr + 1],
+ expressionStack[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 '}'
+ nestedMethod[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
+ intPtr--;
+
+ //statements
+ realBlockPtr--;
+ ExplicitConstructorCall constructorCall = null;
+ Statement[] statements = null;
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ astPtr -= length;
+ if (astStack[astPtr + 1] instanceof ExplicitConstructorCall) {
+ //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+ System.arraycopy(
+ astStack,
+ astPtr + 2,
+ statements = new Statement[length - 1],
+ 0,
+ length - 1);
+ constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
+ } else { //need to add explicitly the super();
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ statements = new Statement[length],
+ 0,
+ length);
+ constructorCall = SuperReference.implicitSuperConstructorCall();
+ }
+ } else {
+ if (!diet){
+ // 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) astStack[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;
+ }
+
+ //watch for } that could be given as a unicode ! ( u007D is '}' )
+ // store the endPosition (position just before the '}') in case there is
+ // a trailing comment behind the end of the method
+ cd.bodyEnd = endPosition;
+ cd.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+}
+
+protected void consumeInvalidConstructorDeclaration() {
+ // ConstructorDeclaration ::= ConstructorHeader ';'
+ // now we know that the top of stack is a constructorDeclaration
+ ConstructorDeclaration cd = (ConstructorDeclaration) astStack[astPtr];
+
+ cd.bodyEnd = endPosition; // position just before the trailing semi-colon
+ cd.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+ // report the problem and continue the parsing - narrowing the problem onto the method
+}
+protected void consumeConstructorHeader() {
+ // ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
+
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration)astStack[astPtr];
+
+ if (currentToken == TokenNameLBRACE){
+ method.bodyStart = scanner.currentPosition;
+ }
+ // recovery
+ if (currentElement != null){
+ restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+}
+protected void consumeConstructorHeaderName() {
+
+ /* recovering - might be an empty message send */
+ if (currentElement != null){
+ if (lastIgnoredToken == TokenNamenew){ // was an allocation expression
+ lastCheckPoint = scanner.startPosition; // force to restart at this exact position
+ restartRecovery = true;
+ return;
+ }
+ }
+
+ // ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
+ ConstructorDeclaration cd = new ConstructorDeclaration(this.compilationUnit.compilationResult);
+
+ //name -- this is not really revelant but we do .....
+ cd.selector = identifierStack[identifierPtr];
+ long selectorSource = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //modifiers
+ cd.declarationSourceStart = intStack[intPtr--];
+ cd.modifiers = intStack[intPtr--];
+
+ //highlight starts at the selector starts
+ cd.sourceStart = (int) (selectorSource >>> 32);
+ pushOnAstStack(cd);
+ cd.sourceEnd = lParenPos;
+ cd.bodyStart = lParenPos+1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = cd.bodyStart;
+ if ((currentElement instanceof RecoveredType && lastIgnoredToken != TokenNameDOT)
+ || cd.modifiers != 0){
+ currentElement = currentElement.add(cd, 0);
+ lastIgnoredToken = -1;
+ }
+ }
+}
+protected void consumeDefaultLabel() {
+ // SwitchLabel ::= 'default' ':'
+ pushOnAstStack(new DefaultCase(intStack[intPtr--], intStack[intPtr--]));
+}
+protected void consumeDefaultModifiers() {
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(
+ modifiersSourceStart >= 0 ? modifiersSourceStart : scanner.startPosition);
+ resetModifiers();
+}
+protected void consumeDiet() {
+ // Diet ::= $empty
+ checkAnnotation();
+ pushOnIntStack(modifiersSourceStart); // push the start position of a javadoc comment if there is one
+ jumpOverMethodBody();
+}
+protected void consumeDims() {
+ // Dims ::= DimsLoop
+ pushOnIntStack(dimensions);
+ dimensions = 0;
+}
+protected void consumeDimWithOrWithOutExpr() {
+ // DimWithOrWithOutExpr ::= '[' ']'
+ pushOnExpressionStack(null);
+}
+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);
+}
+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[endStatementPosition] == ';') {
+ pushOnAstStack(new EmptyStatement(endStatementPosition, endStatementPosition));
+ } else {
+ // we have a Unicode for the ';' (/u003B)
+ pushOnAstStack(new EmptyStatement(endStatementPosition - 5, endStatementPosition));
+ }
+}
+protected void consumeEmptySwitchBlock() {
+ // SwitchBlock ::= '{' '}'
+ pushOnAstLengthStack(0);
+}
+protected void consumeEmptyTypeDeclaration() {
+ // TypeDeclaration ::= ';'
+ pushOnAstLengthStack(0);
+}
+protected void consumeEmptyTypeDeclarationsopt() {
+ // TypeDeclarationsopt ::= $empty
+ pushOnAstLengthStack(0);
+}
+protected void consumeEnterAnonymousClassBody() {
+ // EnterAnonymousClassBody ::= $empty
+ QualifiedAllocationExpression alloc;
+ AnonymousLocalTypeDeclaration anonymousType =
+ new AnonymousLocalTypeDeclaration(this.compilationUnit.compilationResult);
+ alloc =
+ anonymousType.allocation = new QualifiedAllocationExpression(anonymousType);
+ markCurrentMethodWithLocalType();
+ pushOnAstStack(anonymousType);
+
+ alloc.sourceEnd = rParenPos; //the position has been stored explicitly
+ int argumentLength;
+ if ((argumentLength = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= argumentLength;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ alloc.arguments = new Expression[argumentLength],
+ 0,
+ argumentLength);
+ }
+ alloc.type = 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 = intStack[intPtr--];
+ pushOnExpressionStack(alloc);
+
+ anonymousType.bodyStart = scanner.currentPosition;
+ listLength = 0; // will be updated when reading super-interfaces
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = anonymousType.bodyStart;
+ // the recoveryTokenCheck will deal with the open brace
+ currentElement = currentElement.add(anonymousType, 0);
+ currentToken = 0; // opening brace already taken into account
+ lastIgnoredToken = -1;
+ }
+}
+protected void consumeEnterCompilationUnit() {
+ // EnterCompilationUnit ::= $empty
+ // do nothing by default
+}
+protected void consumeEnterVariable() {
+ // EnterVariable ::= $empty
+ // do nothing by default
+
+ char[] name = identifierStack[identifierPtr];
+ long namePosition = identifierPositionStack[identifierPtr];
+ int extendedDimension = intStack[intPtr--];
+ AbstractVariableDeclaration declaration;
+ // create the ast node
+ boolean isLocalDeclaration = nestedMethod[nestedType] != 0;
+ if (isLocalDeclaration) {
+ // create the local variable declarations
+ declaration =
+ this.createLocalDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ } else {
+ // create the field declaration
+ declaration =
+ this.createFieldDeclaration(null, name, (int) (namePosition >>> 32), (int) namePosition);
+ }
+
+ identifierPtr--;
+ identifierLengthPtr--;
+ TypeReference type;
+ int variableIndex = variablesCounter[nestedType];
+ int typeDim = 0;
+ if (variableIndex == 0) {
+ // first variable of the declaration (FieldDeclaration or LocalDeclaration)
+ if (isLocalDeclaration) {
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ type = getTypeReference(typeDim = intStack[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 = intStack[intPtr--]); // type dimension
+ pushOnAstStack(type);
+ declaration.declarationSourceStart = intStack[intPtr--];
+ declaration.modifiers = intStack[intPtr--];
+ }
+ } else {
+ type = (TypeReference) astStack[astPtr - variableIndex];
+ typeDim = type.dimensions();
+ AbstractVariableDeclaration previousVariable =
+ (AbstractVariableDeclaration) astStack[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 = identifierLengthStack[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);
+ }
+ }
+ variablesCounter[nestedType]++;
+ pushOnAstStack(declaration);
+ // recovery
+ if (currentElement != null) {
+ if (!(currentElement instanceof RecoveredType)
+ && (currentToken == TokenNameDOT
+ //|| declaration.modifiers != 0
+ || (scanner.getLineNumber(declaration.type.sourceStart)
+ != scanner.getLineNumber((int) (namePosition >>> 32))))){
+ lastCheckPoint = (int) (namePosition >>> 32);
+ restartRecovery = true;
+ return;
+ }
+ if (isLocalDeclaration){
+ LocalDeclaration localDecl = (LocalDeclaration) astStack[astPtr];
+ lastCheckPoint = localDecl.sourceEnd + 1;
+ currentElement = currentElement.add(localDecl, 0);
+ } else {
+ FieldDeclaration fieldDecl = (FieldDeclaration) astStack[astPtr];
+ lastCheckPoint = fieldDecl.sourceEnd + 1;
+ currentElement = currentElement.add(fieldDecl, 0);
+ }
+ lastIgnoredToken = -1;
+ }
+}
+protected void consumeEqualityExpression(int op) {
+ // EqualityExpression ::= EqualityExpression '==' RelationalExpression
+ // EqualityExpression ::= EqualityExpression '!=' RelationalExpression
+
+ //optimize the push/pop
+
+ expressionPtr--;
+ expressionLengthPtr--;
+ expressionStack[expressionPtr] =
+ new EqualExpression(
+ expressionStack[expressionPtr],
+ expressionStack[expressionPtr + 1],
+ op);
+}
+protected void consumeExitVariableWithInitialization() {
+ // ExitVariableWithInitialization ::= $empty
+ // do nothing by default
+ expressionLengthPtr--;
+ AbstractVariableDeclaration variableDecl = (AbstractVariableDeclaration) astStack[astPtr];
+ variableDecl.initialization = expressionStack[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;
+}
+protected void consumeExitVariableWithoutInitialization() {
+ // ExitVariableWithoutInitialization ::= $empty
+ // do nothing by default
+}
+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 = intStack[intPtr--];
+ ExplicitConstructorCall ecc = new ExplicitConstructorCall(recFlag);
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(expressionStack, expressionPtr + 1, ecc.arguments = new Expression[length], 0, length);
+ }
+ switch (flag) {
+ case 0 :
+ ecc.sourceStart = startPosition;
+ break;
+ case 1 :
+ expressionLengthPtr--;
+ ecc.sourceStart = (ecc.qualification = expressionStack[expressionPtr--]).sourceStart;
+ break;
+ case 2 :
+ ecc.sourceStart = (ecc.qualification = getUnspecifiedReferenceOptimized()).sourceStart;
+ break;
+ };
+ pushOnAstStack(ecc);
+ ecc.sourceEnd = endPosition;
+}
+protected void consumeExpressionStatement() {
+ // ExpressionStatement ::= StatementExpression ';'
+ expressionLengthPtr--;
+ pushOnAstStack(expressionStack[expressionPtr--]);
+}
+protected void consumeFieldAccess(boolean isSuperAccess) {
+ // FieldAccess ::= Primary '.' 'Identifier'
+ // FieldAccess ::= 'super' '.' 'Identifier'
+
+ FieldReference fr =
+ new FieldReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ identifierLengthPtr--;
+ if (isSuperAccess) {
+ //considerates the fieldReference beginning at the 'super' ....
+ fr.sourceStart = intStack[intPtr--];
+ fr.receiver = new SuperReference(fr.sourceStart, endPosition);
+ pushOnExpressionStack(fr);
+ } else {
+ //optimize push/pop
+ if ((fr.receiver = expressionStack[expressionPtr]).isThis()) {
+ //fieldreference begins at the this
+ fr.sourceStart = fr.receiver.sourceStart;
+ }
+ expressionStack[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 = astLengthStack[astLengthPtr];
+
+ for (int i = variableDeclaratorsCounter - 1; i >= 0; i--) {
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) astStack[astPtr - i];
+ fieldDeclaration.declarationSourceEnd = endStatementPosition;
+ fieldDeclaration.declarationEnd = endStatementPosition; // semi-colon included
+ }
+ updateSourceDeclarationParts(variableDeclaratorsCounter);
+ int endPos = flushAnnotationsDefinedPriorTo(endStatementPosition);
+ if (endPos != endStatementPosition) {
+ for (int i = 0; i < variableDeclaratorsCounter; i++) {
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) astStack[astPtr - i];
+ fieldDeclaration.declarationSourceEnd = endPos;
+ }
+ }
+ // update the astStack, astPtr and astLengthStack
+ int startIndex = astPtr - variablesCounter[nestedType] + 1;
+ System.arraycopy(
+ astStack,
+ startIndex,
+ astStack,
+ startIndex - 1,
+ variableDeclaratorsCounter);
+ astPtr--; // remove the type reference
+ astLengthStack[--astLengthPtr] = variableDeclaratorsCounter;
+
+ // recovery
+ if (currentElement != null) {
+ lastCheckPoint = endPos + 1;
+ if (currentElement.parent != null && currentElement instanceof RecoveredField){
+ currentElement = currentElement.parent;
+ }
+ restartRecovery = true;
+ }
+ variablesCounter[nestedType] = 0;
+}
+protected void consumeForceNoDiet() {
+ // ForceNoDiet ::= $empty
+ 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 :
+ */
+
+ identifierLengthPtr--;
+ char[] name = identifierStack[identifierPtr];
+ long namePositions = identifierPositionStack[identifierPtr--];
+ TypeReference type = getTypeReference(intStack[intPtr--] + intStack[intPtr--]);
+ int modifierPositions = intStack[intPtr--];
+ intPtr--;
+ Argument arg =
+ new Argument(
+ name,
+ namePositions,
+ type,
+ intStack[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 */
+ 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 = astLengthStack[astLengthPtr--]) != 0) {
+ astPtr -= length;
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ compilationUnit.imports = new ImportReference[length],
+ 0,
+ length);
+ }
+}
+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;
+ expressionStack[expressionPtr] = exp =
+ new InstanceOfExpression(
+ expressionStack[expressionPtr],
+ getTypeReference(intStack[intPtr--]),
+ op);
+ if (exp.sourceEnd == 0) {
+ //array on base type....
+ exp.sourceEnd = 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 = astLengthStack[astLengthPtr--]) != 0) {
+ //there are length declarations
+ //dispatch.....according to the type of the declarations
+ dispatchDeclarationInto(length);
+ }
+
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+
+ // mark fields and initializer with local type mark if needed
+ markFieldsWithLocalType(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 = endStatementPosition;
+ typeDecl.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+}
+protected void consumeInterfaceHeader() {
+ // InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt
+
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ if (currentToken == TokenNameLBRACE){
+ typeDecl.bodyStart = scanner.currentPosition;
+ }
+ if (currentElement != null){
+ restartRecovery = true; // used to avoid branching back into the regular automaton
+ }
+ // flush the comments related to the interface header
+ scanner.commentPtr = -1;
+}
+protected void consumeInterfaceHeaderExtends() {
+ // InterfaceHeaderExtends ::= 'extends' InterfaceTypeList
+ int length = astLengthStack[astLengthPtr--];
+ //super interfaces
+ astPtr -= length;
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ typeDecl.superInterfaces = new TypeReference[length],
+ 0,
+ length);
+ typeDecl.bodyStart = typeDecl.superInterfaces[length-1].sourceEnd + 1;
+ listLength = 0; // reset after having read super-interfaces
+ // recovery
+ if (currentElement != null) {
+ lastCheckPoint = typeDecl.bodyStart;
+ }
+}
+protected void consumeInterfaceHeaderName() {
+ // InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
+ TypeDeclaration typeDecl;
+ if (nestedMethod[nestedType] == 0) {
+ if (nestedType != 0) {
+ typeDecl = new MemberTypeDeclaration(this.compilationUnit.compilationResult);
+ } else {
+ typeDecl = new TypeDeclaration(this.compilationUnit.compilationResult);
+ }
+ } else {
+ // Record that the block has a declaration for local types
+ typeDecl = new LocalTypeDeclaration(this.compilationUnit.compilationResult);
+ markCurrentMethodWithLocalType();
+ blockReal();
+ }
+
+ //highlight the name of the type
+ long pos = identifierPositionStack[identifierPtr];
+ typeDecl.sourceEnd = (int) pos;
+ typeDecl.sourceStart = (int) (pos >>> 32);
+ typeDecl.name = identifierStack[identifierPtr--];
+ 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 = intStack[intPtr--];
+ intPtr--; // remove the end position of the class token
+ typeDecl.modifiersSourceStart = intStack[intPtr--];
+ typeDecl.modifiers = intStack[intPtr--];
+ if (typeDecl.modifiersSourceStart >= 0) {
+ typeDecl.declarationSourceStart = typeDecl.modifiersSourceStart;
+ }
+ typeDecl.bodyStart = typeDecl.sourceEnd + 1;
+ pushOnAstStack(typeDecl);
+ listLength = 0; // will be updated when reading super-interfaces
+ // recovery
+ if (currentElement != null){ // is recovering
+ lastCheckPoint = typeDecl.bodyStart;
+ currentElement = currentElement.add(typeDecl, 0);
+ lastIgnoredToken = -1;
+ }
+}
+protected void consumeInterfaceMemberDeclarations() {
+ // InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration
+ concatNodeLists();
+}
+protected void consumeInterfaceMemberDeclarationsopt() {
+ // InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations
+ 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 */
+ listLength++;
+}
+protected void consumeInterfaceTypeList() {
+ // InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType
+ optimizedConcatNodeLists();
+}
+protected void consumeLeftHandSide() {
+ // LeftHandSide ::= Name
+
+ pushOnExpressionStack(getUnspecifiedReferenceOptimized());
+}
+protected void consumeLeftParen() {
+ // PushLPAREN ::= '('
+ pushOnIntStack(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 = astLengthStack[astLengthPtr];
+
+ // update the astStack, astPtr and astLengthStack
+ int startIndex = astPtr - variablesCounter[nestedType] + 1;
+ System.arraycopy(
+ astStack,
+ startIndex,
+ astStack,
+ startIndex - 1,
+ variableDeclaratorsCounter);
+ astPtr--; // remove the type reference
+ astLengthStack[--astLengthPtr] = variableDeclaratorsCounter;
+ variablesCounter[nestedType] = 0;
+}
+protected void consumeLocalVariableDeclarationStatement() {
+ // LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';'
+ // see blockReal in case of change: duplicated code
+ // increment the amount of declared variables for this block
+ realBlockStack[realBlockPtr]++;
+}
+protected void consumeMethodBody() {
+ // MethodBody ::= NestedMethod '{' BlockStatementsopt '}'
+ nestedMethod[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
+ intPtr--;
+ }
+
+ int explicitDeclarations = 0;
+ Statement[] statements = null;
+ if (isNotAbstract) {
+ //statements
+ explicitDeclarations = realBlockStack[realBlockPtr--];
+ if ((length = astLengthStack[astLengthPtr--]) != 0)
+ System.arraycopy(
+ astStack,
+ (astPtr -= length) + 1,
+ statements = new Statement[length],
+ 0,
+ length);
+ }
+
+ // now we know that we have a method declaration at the top of the ast stack
+ MethodDeclaration md = (MethodDeclaration) astStack[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;
+ }
+ // store the endPosition (position just before the '}') in case there is
+ // a trailing comment behind the end of the method
+ md.bodyEnd = endPosition;
+ md.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+}
+protected void consumeMethodHeader() {
+ // MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
+ // retrieve end position of method declarator
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration)astStack[astPtr];
+
+ if (currentToken == TokenNameLBRACE){
+ method.bodyStart = scanner.currentPosition;
+ }
+ // recovery
+ if (currentElement != null){
+ if (currentToken == TokenNameSEMICOLON){
+ method.modifiers |= AccSemicolonBody;
+ method.declarationSourceEnd = scanner.currentPosition-1;
+ method.bodyEnd = scanner.currentPosition-1;
+ if (currentElement.parent != null){
+ currentElement = currentElement.parent;
+ }
+ }
+ 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) astStack[astPtr];
+ int extendedDims = intStack[intPtr--];
+ if (extendedDims != 0) {
+ TypeReference returnType = md.returnType;
+ md.sourceEnd = endPosition;
+ int dims = returnType.dimensions() + extendedDims;
+ int baseType;
+ if ((baseType = identifierLengthStack[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 (currentToken == TokenNameLBRACE){
+ md.bodyStart = endPosition + 1;
+ }
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = md.bodyStart;
+ }
+ }
+}
+protected void consumeMethodHeaderName() {
+ // MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+ MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ long selectorSource = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+ //type
+ md.returnType = getTypeReference(intStack[intPtr--]);
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSource >>> 32);
+ pushOnAstStack(md);
+ md.sourceEnd = lParenPos;
+ md.bodyStart = lParenPos+1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ // recovery
+ if (currentElement != null){
+ if (currentElement instanceof RecoveredType
+ //|| md.modifiers != 0
+ || (scanner.getLineNumber(md.returnType.sourceStart)
+ == scanner.getLineNumber(md.sourceStart))){
+ lastCheckPoint = md.bodyStart;
+ currentElement = currentElement.add(md, 0);
+ lastIgnoredToken = -1;
+ } else {
+ lastCheckPoint = md.sourceStart;
+ restartRecovery = true;
+ }
+ }
+}
+protected void consumeMethodHeaderParameters() {
+ // MethodHeaderParameters ::= FormalParameterListopt ')'
+ int length = astLengthStack[astLengthPtr--];
+ astPtr -= length;
+ AbstractMethodDeclaration md = (AbstractMethodDeclaration) astStack[astPtr];
+ md.sourceEnd = rParenPos;
+ //arguments
+ if (length != 0) {
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ md.arguments = new Argument[length],
+ 0,
+ length);
+ }
+ md.bodyStart = rParenPos+1;
+ listLength = 0; // reset listLength after having read all parameters
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = md.bodyStart;
+ if (currentElement.parseTree() == md) return;
+
+ // might not have been attached yet - in some constructor scenarii
+ if (md.isConstructor()){
+ if ((length != 0)
+ || (currentToken == TokenNameLBRACE)
+ // || (currentToken == TokenNamethrows)
+ ){
+ currentElement = currentElement.add(md, 0);
+ lastIgnoredToken = -1;
+ }
+ }
+ }
+}
+protected void consumeMethodHeaderThrowsClause() {
+ // MethodHeaderThrowsClause ::= 'throws' ClassTypeList
+ int length = astLengthStack[astLengthPtr--];
+ astPtr -= length;
+ AbstractMethodDeclaration md = (AbstractMethodDeclaration) astStack[astPtr];
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ md.thrownExceptions = new TypeReference[length],
+ 0,
+ length);
+ md.sourceEnd = md.thrownExceptions[length-1].sourceEnd;
+ md.bodyStart = md.thrownExceptions[length-1].sourceEnd + 1;
+ listLength = 0; // reset listLength after having read all thrown exceptions
+ // recovery
+ if (currentElement != null){
+ 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 = rParenPos;
+ m.sourceStart =
+ (int) ((m.nameSourcePosition = identifierPositionStack[identifierPtr]) >>> 32);
+ m.selector = identifierStack[identifierPtr--];
+ if (identifierLengthStack[identifierLengthPtr] == 1) {
+ m.receiver = ThisReference.ThisImplicit;
+ identifierLengthPtr--;
+ } else {
+ identifierLengthStack[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 = identifierPositionStack[identifierPtr]) >>> 32);
+ m.selector = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+ m.receiver = expressionStack[expressionPtr];
+ m.sourceStart = m.receiver.sourceStart;
+ m.sourceEnd = rParenPos;
+ expressionStack[expressionPtr] = m;
+}
+protected void consumeMethodInvocationSuper() {
+ // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
+
+ MessageSend m = newMessageSend();
+ m.sourceStart = intStack[intPtr--];
+ m.sourceEnd = rParenPos;
+ m.nameSourcePosition = identifierPositionStack[identifierPtr];
+ m.selector = identifierStack[identifierPtr--];
+ identifierLengthPtr--;
+ m.receiver = new SuperReference(m.sourceStart, endPosition);
+ pushOnExpressionStack(m);
+}
+protected void consumeMethodPushModifiersHeaderName() {
+ // MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers 'Identifier' '('
+ // MethodPushModifiersHeaderName ::= Type PushModifiers 'Identifier' '('
+ MethodDeclaration md = new MethodDeclaration(this.compilationUnit.compilationResult);
+
+ //name
+ md.selector = identifierStack[identifierPtr];
+ long selectorSource = identifierPositionStack[identifierPtr--];
+ identifierLengthPtr--;
+
+ //modifiers
+ md.declarationSourceStart = intStack[intPtr--];
+ md.modifiers = intStack[intPtr--];
+
+ //type
+ md.returnType = getTypeReference(intStack[intPtr--]);
+
+ //highlight starts at selector start
+ md.sourceStart = (int) (selectorSource >>> 32);
+ pushOnAstStack(md);
+ md.sourceEnd = lParenPos;
+ md.bodyStart = lParenPos + 1;
+ listLength = 0; // initialize listLength before reading parameters/throws
+
+ // recovery
+ if (currentElement != null) {
+ lastCheckPoint = md.bodyStart;
+ currentElement = currentElement.add(md, 0);
+ lastIgnoredToken = -1;
+ }
+}
+protected void consumeModifiers() {
+ int savedModifiersSourceStart = modifiersSourceStart;
+ checkAnnotation(); // might update modifiers with AccDeprecated
+ pushOnIntStack(modifiers); // modifiers
+ if (modifiersSourceStart >= savedModifiersSourceStart) {
+ modifiersSourceStart = savedModifiersSourceStart;
+ }
+ pushOnIntStack(modifiersSourceStart);
+ resetModifiers();
+}
+protected void consumeNestedMethod() {
+ // NestedMethod ::= $empty
+ jumpOverMethodBody();
+ nestedMethod[nestedType] ++;
+ consumeOpenBlock();
+}
+protected void consumeNestedType() {
+ // NestedType ::= $empty
+ nestedType++;
+ try {
+ nestedMethod[nestedType] = 0;
+ } catch (IndexOutOfBoundsException e) {
+ //except in test's cases, it should never raise
+ int oldL = nestedMethod.length;
+ System.arraycopy(nestedMethod , 0, (nestedMethod = new int[oldL + 30]), 0, oldL);
+ nestedMethod[nestedType] = 0;
+ // increase the size of the fieldsCounter as well. It has to be consistent with the size of the nestedMethod collection
+ System.arraycopy(variablesCounter, 0, (variablesCounter = new int[oldL + 30]), 0, oldL);
+ }
+ variablesCounter[nestedType] = 0;
+}
+protected void consumeOneDimLoop() {
+ // OneDimLoop ::= '[' ']'
+ dimensions++;
+}
+protected void consumeOnlySynchronized() {
+ // OnlySynchronized ::= 'synchronized'
+ pushOnIntStack(this.synchronizedBlockSourceStart);
+ resetModifiers();
+}
+protected void consumeOpenBlock() {
+ // OpenBlock ::= $empty
+
+ pushOnIntStack(scanner.startPosition);
+ try {
+ realBlockStack[++realBlockPtr] = 0;
+ } catch (IndexOutOfBoundsException e) {
+ //realBlockPtr is correct
+ int oldStackLength = realBlockStack.length;
+ int oldStack[] = realBlockStack;
+ realBlockStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldStack, 0, realBlockStack, 0, oldStackLength);
+ realBlockStack[realBlockPtr] = 0;
+ }
+}
+protected void consumePackageDeclaration() {
+ // PackageDeclaration ::= 'package' Name ';'
+ /* build an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ ImportReference impt = compilationUnit.currentPackage;
+ // flush annotations defined prior to import statements
+ impt.declarationEnd = endStatementPosition;
+ impt.declarationSourceEnd = this.flushAnnotationsDefinedPriorTo(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 = identifierLengthStack[identifierLengthPtr--]][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, ++identifierPtr, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr--,
+ positions,
+ 0,
+ length);
+ compilationUnit.currentPackage =
+ impt = new ImportReference(tokens, positions, true);
+
+ if (currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //endPosition is just before the ;
+ impt.declarationSourceStart = intStack[intPtr--];
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = impt.declarationSourceEnd+1;
+ 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
+ updateSourcePosition(expressionStack[expressionPtr]);
+}
+protected void consumePrimaryNoNewArrayArrayType() {
+ // PrimaryNoNewArray ::= ArrayType '.' 'class'
+ intPtr--;
+ pushOnExpressionStack(
+ new ClassLiteralAccess(intStack[intPtr--],
+ getTypeReference(intStack[intPtr--])));
+}
+protected void consumePrimaryNoNewArrayName() {
+ // PrimaryNoNewArray ::= Name '.' 'class'
+ intPtr--;
+ pushOnExpressionStack(
+ new ClassLiteralAccess(intStack[intPtr--],
+ getTypeReference(0)));
+}
+protected void consumePrimaryNoNewArrayNameSuper() {
+ // PrimaryNoNewArray ::= Name '.' 'super'
+ pushOnExpressionStack(
+ new QualifiedSuperReference(
+ getTypeReference(0),
+ intStack[intPtr--],
+ endPosition));
+}
+protected void consumePrimaryNoNewArrayNameThis() {
+ // PrimaryNoNewArray ::= Name '.' 'this'
+ pushOnExpressionStack(
+ new QualifiedThisReference(
+ getTypeReference(0),
+ intStack[intPtr--],
+ endPosition));
+}
+protected void consumePrimaryNoNewArrayPrimitiveType() {
+ // PrimaryNoNewArray ::= PrimitiveType '.' 'class'
+ intPtr--;
+ pushOnExpressionStack(
+ new ClassLiteralAccess(intStack[intPtr--],
+ getTypeReference(0)));
+}
+protected void consumePrimaryNoNewArrayThis() {
+ // PrimaryNoNewArray ::= 'this'
+ pushOnExpressionStack(new ThisReference(intStack[intPtr--], endPosition));
+}
+protected void consumePrimitiveType() {
+ // Type ::= PrimitiveType
+ pushOnIntStack(0);
+}
+protected void consumePushModifiers() {
+ if ((modifiers & AccSynchronized) != 0) {
+ /* remove the starting position of the synchronized keyword
+ * we don't need it when synchronized is part of the modifiers
+ */
+ intPtr--;
+ }
+ pushOnIntStack(modifiers); // modifiers
+ pushOnIntStack(modifiersSourceStart);
+ resetModifiers();
+}
+protected void consumePushPosition() {
+ // for source managment purpose
+ // PushPosition ::= $empty
+ pushOnIntStack(endPosition);
+}
+protected void consumeQualifiedName() {
+ // QualifiedName ::= Name '.' SimpleName
+ /*back from the recursive loop of QualifiedName.
+ Updates identifier length into the length stack*/
+
+ identifierLengthStack[--identifierLengthPtr]++;
+}
+protected void consumeReferenceType() {
+ // ReferenceType ::= ClassOrInterfaceType
+ pushOnIntStack(0);
+}
+protected void consumeRestoreDiet() {
+ // RestoreDiet ::= $empty
+ dietInt--;
+}
+protected void consumeRightParen() {
+ // PushRPAREN ::= ')'
+ pushOnIntStack(rParenPos);
+}
+ // This method is part of an automatic generation : do NOT edit-modify
+ // This method is part of an automatic generation : do NOT edit-modify
+ protected void consumeRule(int act) {
+ switch ( act ) {
+ case 29 : // System.out.println("Type ::= PrimitiveType");
+ consumePrimitiveType();
+ break ;
+
+ case 43 : // System.out.println("ReferenceType ::= ClassOrInterfaceType");
+ consumeReferenceType();
+ break ;
+
+ case 52 : // System.out.println("QualifiedName ::= Name DOT SimpleName");
+ consumeQualifiedName();
+ break ;
+
+ case 53 : // System.out.println("CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt");
+ consumeCompilationUnit();
+ break ;
+
+ case 54 : // System.out.println("EnterCompilationUnit ::=");
+ consumeEnterCompilationUnit();
+ break ;
+
+ case 66 : // System.out.println("CatchHeader ::= catch LPAREN FormalParameter RPAREN LBRACE");
+ consumeCatchHeader();
+ break ;
+
+ case 68 : // System.out.println("ImportDeclarations ::= ImportDeclarations ImportDeclaration");
+ consumeImportDeclarations();
+ break ;
+
+ case 70 : // System.out.println("TypeDeclarations ::= TypeDeclarations TypeDeclaration");
+ consumeTypeDeclarations();
+ break ;
+
+ case 71 : // System.out.println("PackageDeclaration ::= PackageDeclarationName SEMICOLON");
+ consumePackageDeclaration();
+ break ;
+
+ case 72 : // System.out.println("PackageDeclarationName ::= package Name");
+ consumePackageDeclarationName();
+ break ;
+
+ case 75 : // System.out.println("SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName SEMICOLON");
+ consumeSingleTypeImportDeclaration();
+ break ;
+
+ case 76 : // System.out.println("SingleTypeImportDeclarationName ::= import Name");
+ consumeSingleTypeImportDeclarationName();
+ break ;
+
+ case 77 : // System.out.println("TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName SEMICOLON");
+ consumeTypeImportOnDemandDeclaration();
+ break ;
+
+ case 78 : // System.out.println("TypeImportOnDemandDeclarationName ::= import Name DOT MULTIPLY");
+ consumeTypeImportOnDemandDeclarationName();
+ break ;
+
+ case 81 : // System.out.println("TypeDeclaration ::= SEMICOLON");
+ consumeEmptyTypeDeclaration();
+ break ;
+
+ case 95 : // System.out.println("ClassDeclaration ::= ClassHeader ClassBody");
+ consumeClassDeclaration();
+ break ;
+
+ case 96 : // System.out.println("ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt");
+ consumeClassHeader();
+ break ;
+
+ case 97 : // System.out.println("ClassHeaderName ::= Modifiersopt class Identifier");
+ consumeClassHeaderName();
+ break ;
+
+ case 98 : // System.out.println("ClassHeaderExtends ::= extends ClassType");
+ consumeClassHeaderExtends();
+ break ;
+
+ case 99 : // System.out.println("ClassHeaderImplements ::= implements InterfaceTypeList");
+ consumeClassHeaderImplements();
+ break ;
+
+ case 101 : // System.out.println("InterfaceTypeList ::= InterfaceTypeList COMMA InterfaceType");
+ consumeInterfaceTypeList();
+ break ;
+
+ case 102 : // System.out.println("InterfaceType ::= ClassOrInterfaceType");
+ consumeInterfaceType();
+ break ;
+
+ case 105 : // System.out.println("ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration");
+ consumeClassBodyDeclarations();
+ break ;
+
+ case 109 : // System.out.println("ClassBodyDeclaration ::= Diet NestedMethod Block");
+ consumeClassBodyDeclaration();
+ break ;
+
+ case 110 : // System.out.println("Diet ::=");
+ consumeDiet();
+ break ;
+
+ case 111 : // System.out.println("Initializer ::= Diet NestedMethod Block");
+ consumeClassBodyDeclaration();
+ break ;
+
+ case 118 : // System.out.println("ClassMemberDeclaration ::= SEMICOLON");
+ consumeEmptyClassMemberDeclaration();
+ break ;
+
+ case 119 : // System.out.println("FieldDeclaration ::= Modifiersopt Type VariableDeclarators SEMICOLON");
+ consumeFieldDeclaration();
+ break ;
+
+ case 121 : // System.out.println("VariableDeclarators ::= VariableDeclarators COMMA VariableDeclarator");
+ consumeVariableDeclarators();
+ break ;
+
+ case 124 : // System.out.println("EnterVariable ::=");
+ consumeEnterVariable();
+ break ;
+
+ case 125 : // System.out.println("ExitVariableWithInitialization ::=");
+ consumeExitVariableWithInitialization();
+ break ;
+
+ case 126 : // System.out.println("ExitVariableWithoutInitialization ::=");
+ consumeExitVariableWithoutInitialization();
+ break ;
+
+ case 127 : // System.out.println("ForceNoDiet ::=");
+ consumeForceNoDiet();
+ break ;
+
+ case 128 : // System.out.println("RestoreDiet ::=");
+ consumeRestoreDiet();
+ break ;
+
+ case 133 : // System.out.println("MethodDeclaration ::= MethodHeader MethodBody");
+ // set to true to consume a method with a body
+ consumeMethodDeclaration(true);
+ break ;
+
+ case 134 : // System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON");
+ // set to false to consume a method without body
+ consumeMethodDeclaration(false);
+ break ;
+
+ case 135 : // System.out.println("MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims");
+ consumeMethodHeader();
+ break ;
+
+ case 136 : // System.out.println("MethodPushModifiersHeader ::= MethodPushModifiersHeaderName MethodHeaderParameters");
+ consumeMethodHeader();
+ break ;
+
+ case 137 : // System.out.println("MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers Identifier LPAREN");
+ consumeMethodPushModifiersHeaderName();
+ break ;
+
+ case 138 : // System.out.println("MethodPushModifiersHeaderName ::= Type PushModifiers Identifier LPAREN");
+ consumeMethodPushModifiersHeaderName();
+ break ;
+
+ case 139 : // System.out.println("MethodHeaderName ::= Modifiersopt Type Identifier LPAREN");
+ consumeMethodHeaderName();
+ break ;
+
+ case 140 : // System.out.println("MethodHeaderParameters ::= FormalParameterListopt RPAREN");
+ consumeMethodHeaderParameters();
+ break ;
+
+ case 141 : // System.out.println("MethodHeaderExtendedDims ::= Dimsopt");
+ consumeMethodHeaderExtendedDims();
+ break ;
+
+ case 142 : // System.out.println("MethodHeaderThrowsClause ::= throws ClassTypeList");
+ consumeMethodHeaderThrowsClause();
+ break ;
+
+ case 143 : // System.out.println("ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters...");
+ consumeConstructorHeader();
+ break ;
+
+ case 144 : // System.out.println("ConstructorHeaderName ::= Modifiersopt Identifier LPAREN");
+ consumeConstructorHeaderName();
+ break ;
+
+ case 146 : // System.out.println("FormalParameterList ::= FormalParameterList COMMA FormalParameter");
+ consumeFormalParameterList();
+ break ;
+
+ case 147 : // System.out.println("FormalParameter ::= Modifiersopt Type VariableDeclaratorId");
+ // the boolean is used to know if the modifiers should be reset
+ consumeFormalParameter();
+ break ;
+
+ case 149 : // System.out.println("ClassTypeList ::= ClassTypeList COMMA ClassTypeElt");
+ consumeClassTypeList();
+ break ;
+
+ case 150 : // System.out.println("ClassTypeElt ::= ClassType");
+ consumeClassTypeElt();
+ break ;
+
+ case 151 : // System.out.println("MethodBody ::= NestedMethod LBRACE BlockStatementsopt RBRACE");
+ consumeMethodBody();
+ break ;
+
+ case 152 : // System.out.println("NestedMethod ::=");
+ consumeNestedMethod();
+ break ;
+
+ case 153 : // System.out.println("StaticInitializer ::= StaticOnly Block");
+ consumeStaticInitializer();
+ break ;
+
+ case 154 : // System.out.println("StaticOnly ::= static");
+ consumeStaticOnly();
+ break ;
+
+ case 155 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader ConstructorBody");
+ consumeConstructorDeclaration() ;
+ break ;
+
+ case 156 : // System.out.println("ConstructorDeclaration ::= ConstructorHeader SEMICOLON");
+ consumeInvalidConstructorDeclaration() ;
+ break ;
+
+ case 157 : // System.out.println("ConstructorBody ::= NestedMethod LBRACE ConstructorBlockStatementsopt RBRACE");
+ consumeConstructorBody();
+ break ;
+
+ case 160 : // System.out.println("ConstructorBlockStatementsopt ::= ExplicitConstructorInvocation BlockStatements");
+ consumeConstructorBlockStatements();
+ break ;
+
+ case 161 : // System.out.println("ExplicitConstructorInvocation ::= this LPAREN ArgumentListopt RPAREN SEMICOLON");
+ consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This);
+ break ;
+
+ case 162 : // System.out.println("ExplicitConstructorInvocation ::= super LPAREN ArgumentListopt RPAREN SEMICOLON");
+ consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super);
+ break ;
+
+ case 163 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT super LPAREN ArgumentListopt RPAREN");
+ consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super);
+ break ;
+
+ case 164 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT super LPAREN ArgumentListopt RPAREN...");
+ consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super);
+ break ;
+
+ case 165 : // System.out.println("ExplicitConstructorInvocation ::= Primary DOT this LPAREN ArgumentListopt RPAREN...");
+ consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This);
+ break ;
+
+ case 166 : // System.out.println("ExplicitConstructorInvocation ::= Name DOT this LPAREN ArgumentListopt RPAREN...");
+ consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This);
+ break ;
+
+ case 167 : // System.out.println("InterfaceDeclaration ::= InterfaceHeader InterfaceBody");
+ consumeInterfaceDeclaration();
+ break ;
+
+ case 168 : // System.out.println("InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt");
+ consumeInterfaceHeader();
+ break ;
+
+ case 169 : // System.out.println("InterfaceHeaderName ::= Modifiersopt interface Identifier");
+ consumeInterfaceHeaderName();
+ break ;
+
+ case 171 : // System.out.println("InterfaceHeaderExtends ::= extends InterfaceTypeList");
+ consumeInterfaceHeaderExtends();
+ break ;
+
+ case 174 : // System.out.println("InterfaceMemberDeclarations ::= InterfaceMemberDeclarations...");
+ consumeInterfaceMemberDeclarations();
+ break ;
+
+ case 175 : // System.out.println("InterfaceMemberDeclaration ::= SEMICOLON");
+ consumeEmptyInterfaceMemberDeclaration();
+ break ;
+
+ case 178 : // System.out.println("InterfaceMemberDeclaration ::= InvalidMethodDeclaration");
+ ignoreMethodBody();
+ break ;
+
+ case 179 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody");
+ ignoreInvalidConstructorDeclaration(true);
+ break ;
+
+ case 180 : // System.out.println("InvalidConstructorDeclaration ::= ConstructorHeader SEMICOLON");
+ ignoreInvalidConstructorDeclaration(false);
+ break ;
+
+ case 186 : // System.out.println("ArrayInitializer ::= LBRACE ,opt RBRACE");
+ consumeEmptyArrayInitializer();
+ break ;
+
+ case 187 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers RBRACE");
+ consumeArrayInitializer();
+ break ;
+
+ case 188 : // System.out.println("ArrayInitializer ::= LBRACE VariableInitializers COMMA RBRACE");
+ consumeArrayInitializer();
+ break ;
+
+ case 190 : // System.out.println("VariableInitializers ::= VariableInitializers COMMA VariableInitializer");
+ consumeVariableInitializers();
+ break ;
+
+ case 191 : // System.out.println("Block ::= OpenBlock LBRACE BlockStatementsopt RBRACE");
+ consumeBlock();
+ break ;
+
+ case 192 : // System.out.println("OpenBlock ::=");
+ consumeOpenBlock() ;
+ break ;
+
+ case 194 : // System.out.println("BlockStatements ::= BlockStatements BlockStatement");
+ consumeBlockStatements() ;
+ break ;
+
+ case 198 : // System.out.println("BlockStatement ::= InvalidInterfaceDeclaration");
+ ignoreInterfaceDeclaration();
+ break ;
+
+ case 199 : // System.out.println("LocalVariableDeclarationStatement ::= LocalVariableDeclaration SEMICOLON");
+ consumeLocalVariableDeclarationStatement();
+ break ;
+
+ case 200 : // System.out.println("LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators");
+ consumeLocalVariableDeclaration();
+ break ;
+
+ case 201 : // System.out.println("LocalVariableDeclaration ::= Modifiers Type PushModifiers VariableDeclarators");
+ consumeLocalVariableDeclaration();
+ break ;
+
+ case 202 : // System.out.println("PushModifiers ::=");
+ consumePushModifiers();
+ break ;
+
+ case 226 : // System.out.println("EmptyStatement ::= SEMICOLON");
+ consumeEmptyStatement();
+ break ;
+
+ case 227 : // System.out.println("LabeledStatement ::= Identifier COLON Statement");
+ consumeStatementLabel() ;
+ break ;
+
+ case 228 : // System.out.println("LabeledStatementNoShortIf ::= Identifier COLON StatementNoShortIf");
+ consumeStatementLabel() ;
+ break ;
+
+ case 229 : // System.out.println("ExpressionStatement ::= StatementExpression SEMICOLON");
+ consumeExpressionStatement();
+ break ;
+
+ case 237 : // System.out.println("IfThenStatement ::= if LPAREN Expression RPAREN Statement");
+ consumeStatementIfNoElse();
+ break ;
+
+ case 238 : // System.out.println("IfThenElseStatement ::= if LPAREN Expression RPAREN StatementNoShortIf else...");
+ consumeStatementIfWithElse();
+ break ;
+
+ case 239 : // System.out.println("IfThenElseStatementNoShortIf ::= if LPAREN Expression RPAREN StatementNoShortIf...");
+ consumeStatementIfWithElse();
+ break ;
+
+ case 240 : // System.out.println("SwitchStatement ::= switch OpenBlock LPAREN Expression RPAREN SwitchBlock");
+ consumeStatementSwitch() ;
+ break ;
+
+ case 241 : // System.out.println("SwitchBlock ::= LBRACE RBRACE");
+ consumeEmptySwitchBlock() ;
+ break ;
+
+ case 244 : // System.out.println("SwitchBlock ::= LBRACE SwitchBlockStatements SwitchLabels RBRACE");
+ consumeSwitchBlock() ;
+ break ;
+
+ case 246 : // System.out.println("SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement");
+ consumeSwitchBlockStatements() ;
+ break ;
+
+ case 247 : // System.out.println("SwitchBlockStatement ::= SwitchLabels BlockStatements");
+ consumeSwitchBlockStatement() ;
+ break ;
+
+ case 249 : // System.out.println("SwitchLabels ::= SwitchLabels SwitchLabel");
+ consumeSwitchLabels() ;
+ break ;
+
+ case 250 : // System.out.println("SwitchLabel ::= case ConstantExpression COLON");
+ consumeCaseLabel();
+ break ;
+
+ case 251 : // System.out.println("SwitchLabel ::= default COLON");
+ consumeDefaultLabel();
+ break ;
+
+ case 252 : // System.out.println("WhileStatement ::= while LPAREN Expression RPAREN Statement");
+ consumeStatementWhile() ;
+ break ;
+
+ case 253 : // System.out.println("WhileStatementNoShortIf ::= while LPAREN Expression RPAREN StatementNoShortIf");
+ consumeStatementWhile() ;
+ break ;
+
+ case 254 : // System.out.println("DoStatement ::= do Statement while LPAREN Expression RPAREN SEMICOLON");
+ consumeStatementDo() ;
+ break ;
+
+ case 255 : // System.out.println("ForStatement ::= for LPAREN ForInitopt SEMICOLON Expressionopt SEMICOLON...");
+ consumeStatementFor() ;
+ break ;
+
+ case 256 : // System.out.println("ForStatementNoShortIf ::= for LPAREN ForInitopt SEMICOLON Expressionopt SEMICOLON");
+ consumeStatementFor() ;
+ break ;
+
+ case 257 : // System.out.println("ForInit ::= StatementExpressionList");
+ consumeForInit() ;
+ break ;
+
+ case 261 : // System.out.println("StatementExpressionList ::= StatementExpressionList COMMA StatementExpression");
+ consumeStatementExpressionList() ;
+ break ;
+
+ case 262 : // System.out.println("AssertStatement ::= assert Expression SEMICOLON");
+ consumeSimpleAssertStatement() ;
+ break ;
+
+ case 263 : // System.out.println("AssertStatement ::= assert Expression COLON Expression SEMICOLON");
+ consumeAssertStatement() ;
+ break ;
+
+ case 264 : // System.out.println("BreakStatement ::= break SEMICOLON");
+ consumeStatementBreak() ;
+ break ;
+
+ case 265 : // System.out.println("BreakStatement ::= break Identifier SEMICOLON");
+ consumeStatementBreakWithLabel() ;
+ break ;
+
+ case 266 : // System.out.println("ContinueStatement ::= continue SEMICOLON");
+ consumeStatementContinue() ;
+ break ;
+
+ case 267 : // System.out.println("ContinueStatement ::= continue Identifier SEMICOLON");
+ consumeStatementContinueWithLabel() ;
+ break ;
+
+ case 268 : // System.out.println("ReturnStatement ::= return Expressionopt SEMICOLON");
+ consumeStatementReturn() ;
+ break ;
+
+ case 269 : // System.out.println("ThrowStatement ::= throw Expression SEMICOLON");
+ consumeStatementThrow();
+
+ break ;
+
+ case 270 : // System.out.println("SynchronizedStatement ::= OnlySynchronized LPAREN Expression RPAREN Block");
+ consumeStatementSynchronized();
+ break ;
+
+ case 271 : // System.out.println("OnlySynchronized ::= synchronized");
+ consumeOnlySynchronized();
+ break ;
+
+ case 272 : // System.out.println("TryStatement ::= try Block Catches");
+ consumeStatementTry(false);
+ break ;
+
+ case 273 : // System.out.println("TryStatement ::= try Block Catchesopt Finally");
+ consumeStatementTry(true);
+ break ;
+
+ case 275 : // System.out.println("Catches ::= Catches CatchClause");
+ consumeCatches();
+ break ;
+
+ case 276 : // System.out.println("CatchClause ::= catch LPAREN FormalParameter RPAREN Block");
+ consumeStatementCatch() ;
+ break ;
+
+ case 278 : // System.out.println("PushLPAREN ::= LPAREN");
+ consumeLeftParen();
+ break ;
+
+ case 279 : // System.out.println("PushRPAREN ::= RPAREN");
+ consumeRightParen();
+ break ;
+
+ case 283 : // System.out.println("PrimaryNoNewArray ::= this");
+ consumePrimaryNoNewArrayThis();
+ break ;
+
+ case 284 : // System.out.println("PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN");
+ consumePrimaryNoNewArray();
+ break ;
+
+ case 287 : // System.out.println("PrimaryNoNewArray ::= Name DOT this");
+ consumePrimaryNoNewArrayNameThis();
+ break ;
+
+ case 288 : // System.out.println("PrimaryNoNewArray ::= Name DOT super");
+ consumePrimaryNoNewArrayNameSuper();
+ break ;
+
+ case 289 : // System.out.println("PrimaryNoNewArray ::= Name DOT class");
+ consumePrimaryNoNewArrayName();
+ break ;
+
+ case 290 : // System.out.println("PrimaryNoNewArray ::= ArrayType DOT class");
+ consumePrimaryNoNewArrayArrayType();
+ break ;
+
+ case 291 : // System.out.println("PrimaryNoNewArray ::= PrimitiveType DOT class");
+ consumePrimaryNoNewArrayPrimitiveType();
+ break ;
+
+ case 294 : // System.out.println("AllocationHeader ::= new ClassType LPAREN ArgumentListopt RPAREN");
+ consumeAllocationHeader();
+ break ;
+
+ case 295 : // System.out.println("ClassInstanceCreationExpression ::= new ClassType LPAREN ArgumentListopt RPAREN...");
+ consumeClassInstanceCreationExpression();
+ break ;
+
+ case 296 : // System.out.println("ClassInstanceCreationExpression ::= Primary DOT new SimpleName LPAREN...");
+ consumeClassInstanceCreationExpressionQualified() ;
+ break ;
+
+ case 297 : // System.out.println("ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName new...");
+ consumeClassInstanceCreationExpressionQualified() ;
+ break ;
+
+ case 298 : // System.out.println("ClassInstanceCreationExpressionName ::= Name DOT");
+ consumeClassInstanceCreationExpressionName() ;
+ break ;
+
+ case 299 : // System.out.println("ClassBodyopt ::=");
+ consumeClassBodyopt();
+ break ;
+
+ case 301 : // System.out.println("EnterAnonymousClassBody ::=");
+ consumeEnterAnonymousClassBody();
+ break ;
+
+ case 303 : // System.out.println("ArgumentList ::= ArgumentList COMMA Expression");
+ consumeArgumentList();
+ break ;
+
+ case 304 : // System.out.println("ArrayCreationExpression ::= new PrimitiveType DimWithOrWithOutExprs...");
+ consumeArrayCreationExpression();
+ break ;
+
+ case 305 : // System.out.println("ArrayCreationExpression ::= new ClassOrInterfaceType DimWithOrWithOutExprs...");
+ consumeArrayCreationExpression();
+ break ;
+
+ case 307 : // System.out.println("DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr");
+ consumeDimWithOrWithOutExprs();
+ break ;
+
+ case 309 : // System.out.println("DimWithOrWithOutExpr ::= LBRACKET RBRACKET");
+ consumeDimWithOrWithOutExpr();
+ break ;
+
+ case 310 : // System.out.println("Dims ::= DimsLoop");
+ consumeDims();
+ break ;
+
+ case 313 : // System.out.println("OneDimLoop ::= LBRACKET RBRACKET");
+ consumeOneDimLoop();
+ break ;
+
+ case 314 : // System.out.println("FieldAccess ::= Primary DOT Identifier");
+ consumeFieldAccess(false);
+ break ;
+
+ case 315 : // System.out.println("FieldAccess ::= super DOT Identifier");
+ consumeFieldAccess(true);
+ break ;
+
+ case 316 : // System.out.println("MethodInvocation ::= Name LPAREN ArgumentListopt RPAREN");
+ consumeMethodInvocationName();
+ break ;
+
+ case 317 : // System.out.println("MethodInvocation ::= Primary DOT Identifier LPAREN ArgumentListopt RPAREN");
+ consumeMethodInvocationPrimary();
+ break ;
+
+ case 318 : // System.out.println("MethodInvocation ::= super DOT Identifier LPAREN ArgumentListopt RPAREN");
+ consumeMethodInvocationSuper();
+ break ;
+
+ case 319 : // System.out.println("ArrayAccess ::= Name LBRACKET Expression RBRACKET");
+ consumeArrayAccess(true);
+ break ;
+
+ case 320 : // System.out.println("ArrayAccess ::= PrimaryNoNewArray LBRACKET Expression RBRACKET");
+ consumeArrayAccess(false);
+ break ;
+
+ case 322 : // System.out.println("PostfixExpression ::= Name");
+ consumePostfixExpression();
+ break ;
+
+ case 325 : // System.out.println("PostIncrementExpression ::= PostfixExpression PLUS_PLUS");
+ consumeUnaryExpression(OperatorExpression.PLUS,true);
+ break ;
+
+ case 326 : // System.out.println("PostDecrementExpression ::= PostfixExpression MINUS_MINUS");
+ consumeUnaryExpression(OperatorExpression.MINUS,true);
+ break ;
+
+ case 327 : // System.out.println("PushPosition ::=");
+ consumePushPosition();
+ break ;
+
+ case 330 : // System.out.println("UnaryExpression ::= PLUS PushPosition UnaryExpression");
+ consumeUnaryExpression(OperatorExpression.PLUS);
+ break ;
+
+ case 331 : // System.out.println("UnaryExpression ::= MINUS PushPosition UnaryExpression");
+ consumeUnaryExpression(OperatorExpression.MINUS);
+ break ;
+
+ case 333 : // System.out.println("PreIncrementExpression ::= PLUS_PLUS PushPosition UnaryExpression");
+ consumeUnaryExpression(OperatorExpression.PLUS,false);
+ break ;
+
+ case 334 : // System.out.println("PreDecrementExpression ::= MINUS_MINUS PushPosition UnaryExpression");
+ consumeUnaryExpression(OperatorExpression.MINUS,false);
+ break ;
+
+ case 336 : // System.out.println("UnaryExpressionNotPlusMinus ::= TWIDDLE PushPosition UnaryExpression");
+ consumeUnaryExpression(OperatorExpression.TWIDDLE);
+ break ;
+
+ case 337 : // System.out.println("UnaryExpressionNotPlusMinus ::= NOT PushPosition UnaryExpression");
+ consumeUnaryExpression(OperatorExpression.NOT);
+ break ;
+
+ case 339 : // System.out.println("CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN UnaryExpression");
+ consumeCastExpression();
+ break ;
+
+ case 340 : // System.out.println("CastExpression ::= PushLPAREN Name Dims PushRPAREN UnaryExpressionNotPlusMinus");
+ consumeCastExpression();
+ break ;
+
+ case 341 : // System.out.println("CastExpression ::= PushLPAREN Expression PushRPAREN UnaryExpressionNotPlusMinus");
+ consumeCastExpressionLL1();
+ break ;
+
+ case 343 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression MULTIPLY UnaryExpression");
+ consumeBinaryExpression(OperatorExpression.MULTIPLY);
+ break ;
+
+ case 344 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression DIVIDE UnaryExpression");
+ consumeBinaryExpression(OperatorExpression.DIVIDE);
+ break ;
+
+ case 345 : // System.out.println("MultiplicativeExpression ::= MultiplicativeExpression REMAINDER UnaryExpression");
+ consumeBinaryExpression(OperatorExpression.REMAINDER);
+ break ;
+
+ case 347 : // System.out.println("AdditiveExpression ::= AdditiveExpression PLUS MultiplicativeExpression");
+ consumeBinaryExpression(OperatorExpression.PLUS);
+ break ;
+
+ case 348 : // System.out.println("AdditiveExpression ::= AdditiveExpression MINUS MultiplicativeExpression");
+ consumeBinaryExpression(OperatorExpression.MINUS);
+ break ;
+
+ case 350 : // System.out.println("ShiftExpression ::= ShiftExpression LEFT_SHIFT AdditiveExpression");
+ consumeBinaryExpression(OperatorExpression.LEFT_SHIFT);
+ break ;
+
+ case 351 : // System.out.println("ShiftExpression ::= ShiftExpression RIGHT_SHIFT AdditiveExpression");
+ consumeBinaryExpression(OperatorExpression.RIGHT_SHIFT);
+ break ;
+
+ case 352 : // System.out.println("ShiftExpression ::= ShiftExpression UNSIGNED_RIGHT_SHIFT AdditiveExpression");
+ consumeBinaryExpression(OperatorExpression.UNSIGNED_RIGHT_SHIFT);
+ break ;
+
+ case 354 : // System.out.println("RelationalExpression ::= RelationalExpression LESS ShiftExpression");
+ consumeBinaryExpression(OperatorExpression.LESS);
+ break ;
+
+ case 355 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER ShiftExpression");
+ consumeBinaryExpression(OperatorExpression.GREATER);
+ break ;
+
+ case 356 : // System.out.println("RelationalExpression ::= RelationalExpression LESS_EQUAL ShiftExpression");
+ consumeBinaryExpression(OperatorExpression.LESS_EQUAL);
+ break ;
+
+ case 357 : // System.out.println("RelationalExpression ::= RelationalExpression GREATER_EQUAL ShiftExpression");
+ consumeBinaryExpression(OperatorExpression.GREATER_EQUAL);
+ break ;
+
+ case 358 : // System.out.println("RelationalExpression ::= RelationalExpression instanceof ReferenceType");
+ consumeInstanceOfExpression(OperatorExpression.INSTANCEOF);
+ break ;
+
+ case 360 : // System.out.println("EqualityExpression ::= EqualityExpression EQUAL_EQUAL RelationalExpression");
+ consumeEqualityExpression(OperatorExpression.EQUAL_EQUAL);
+ break ;
+
+ case 361 : // System.out.println("EqualityExpression ::= EqualityExpression NOT_EQUAL RelationalExpression");
+ consumeEqualityExpression(OperatorExpression.NOT_EQUAL);
+ break ;
+
+ case 363 : // System.out.println("AndExpression ::= AndExpression AND EqualityExpression");
+ consumeBinaryExpression(OperatorExpression.AND);
+ break ;
+
+ case 365 : // System.out.println("ExclusiveOrExpression ::= ExclusiveOrExpression XOR AndExpression");
+ consumeBinaryExpression(OperatorExpression.XOR);
+ break ;
+
+ case 367 : // System.out.println("InclusiveOrExpression ::= InclusiveOrExpression OR ExclusiveOrExpression");
+ consumeBinaryExpression(OperatorExpression.OR);
+ break ;
+
+ case 369 : // System.out.println("ConditionalAndExpression ::= ConditionalAndExpression AND_AND InclusiveOrExpression");
+ consumeBinaryExpression(OperatorExpression.AND_AND);
+ break ;
+
+ case 371 : // System.out.println("ConditionalOrExpression ::= ConditionalOrExpression OR_OR ConditionalAndExpression");
+ consumeBinaryExpression(OperatorExpression.OR_OR);
+ break ;
+
+ case 373 : // System.out.println("ConditionalExpression ::= ConditionalOrExpression QUESTION Expression COLON...");
+ consumeConditionalExpression(OperatorExpression.QUESTIONCOLON) ;
+ break ;
+
+ case 376 : // System.out.println("Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression");
+ consumeAssignment();
+ break ;
+
+ case 378 : // System.out.println("Assignment ::= InvalidArrayInitializerAssignement");
+ ignoreExpressionAssignment();
+ break ;
+
+ case 379 : // System.out.println("LeftHandSide ::= Name");
+ consumeLeftHandSide();
+ break ;
+
+ case 382 : // System.out.println("AssignmentOperator ::= EQUAL");
+ consumeAssignmentOperator(EQUAL);
+ break ;
+
+ case 383 : // System.out.println("AssignmentOperator ::= MULTIPLY_EQUAL");
+ consumeAssignmentOperator(MULTIPLY);
+ break ;
+
+ case 384 : // System.out.println("AssignmentOperator ::= DIVIDE_EQUAL");
+ consumeAssignmentOperator(DIVIDE);
+ break ;
+
+ case 385 : // System.out.println("AssignmentOperator ::= REMAINDER_EQUAL");
+ consumeAssignmentOperator(REMAINDER);
+ break ;
+
+ case 386 : // System.out.println("AssignmentOperator ::= PLUS_EQUAL");
+ consumeAssignmentOperator(PLUS);
+ break ;
+
+ case 387 : // System.out.println("AssignmentOperator ::= MINUS_EQUAL");
+ consumeAssignmentOperator(MINUS);
+ break ;
+
+ case 388 : // System.out.println("AssignmentOperator ::= LEFT_SHIFT_EQUAL");
+ consumeAssignmentOperator(LEFT_SHIFT);
+ break ;
+
+ case 389 : // System.out.println("AssignmentOperator ::= RIGHT_SHIFT_EQUAL");
+ consumeAssignmentOperator(RIGHT_SHIFT);
+ break ;
+
+ case 390 : // System.out.println("AssignmentOperator ::= UNSIGNED_RIGHT_SHIFT_EQUAL");
+ consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT);
+ break ;
+
+ case 391 : // System.out.println("AssignmentOperator ::= AND_EQUAL");
+ consumeAssignmentOperator(AND);
+ break ;
+
+ case 392 : // System.out.println("AssignmentOperator ::= XOR_EQUAL");
+ consumeAssignmentOperator(XOR);
+ break ;
+
+ case 393 : // System.out.println("AssignmentOperator ::= OR_EQUAL");
+ consumeAssignmentOperator(OR);
+ break ;
+
+ case 400 : // System.out.println("Expressionopt ::=");
+ consumeEmptyExpression();
+ break ;
+
+ case 404 : // System.out.println("ImportDeclarationsopt ::=");
+ consumeEmptyImportDeclarationsopt();
+ break ;
+
+ case 405 : // System.out.println("ImportDeclarationsopt ::= ImportDeclarations");
+ consumeImportDeclarationsopt();
+ break ;
+
+ case 406 : // System.out.println("TypeDeclarationsopt ::=");
+ consumeEmptyTypeDeclarationsopt();
+ break ;
+
+ case 407 : // System.out.println("TypeDeclarationsopt ::= TypeDeclarations");
+ consumeTypeDeclarationsopt();
+ break ;
+
+ case 408 : // System.out.println("ClassBodyDeclarationsopt ::=");
+ consumeEmptyClassBodyDeclarationsopt();
+ break ;
+
+ case 409 : // System.out.println("ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations");
+ consumeClassBodyDeclarationsopt();
+ break ;
+
+ case 410 : // System.out.println("Modifiersopt ::=");
+ consumeDefaultModifiers();
+ break ;
+
+ case 411 : // System.out.println("Modifiersopt ::= Modifiers");
+ consumeModifiers();
+ break ;
+
+ case 412 : // System.out.println("BlockStatementsopt ::=");
+ consumeEmptyBlockStatementsopt();
+ break ;
+
+ case 414 : // System.out.println("Dimsopt ::=");
+ consumeEmptyDimsopt();
+ break ;
+
+ case 416 : // System.out.println("ArgumentListopt ::=");
+ consumeEmptyArgumentListopt();
+ break ;
+
+ case 420 : // System.out.println("FormalParameterListopt ::=");
+ consumeFormalParameterListopt();
+ break ;
+
+ case 424 : // System.out.println("InterfaceMemberDeclarationsopt ::=");
+ consumeEmptyInterfaceMemberDeclarationsopt();
+ break ;
+
+ case 425 : // System.out.println("InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations");
+ consumeInterfaceMemberDeclarationsopt();
+ break ;
+
+ case 426 : // System.out.println("NestedType ::=");
+ consumeNestedType();
+ break ;
+
+ case 427 : // System.out.println("ForInitopt ::=");
+ consumeEmptyForInitopt();
+ break ;
+
+ case 429 : // System.out.println("ForUpdateopt ::=");
+ consumeEmptyForUpdateopt();
+ break ;
+
+ case 433 : // System.out.println("Catchesopt ::=");
+ consumeEmptyCatchesopt();
+ break ;
+
+ case 435 : // System.out.println("ArrayInitializeropt ::=");
+ consumeEmptyArrayInitializeropt();
+ break ;
+
+ }
+ }
+
+
+protected void consumeSimpleAssertStatement() {
+ // AssertStatement ::= 'assert' Expression ';'
+ expressionLengthPtr--;
+ pushOnAstStack(new AssertStatement(expressionStack[expressionPtr--], intStack[intPtr--]));
+}
+
+protected void consumeSingleTypeImportDeclaration() {
+ // SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+
+ ImportReference impt = (ImportReference) astStack[astPtr];
+ // flush annotations defined prior to import statements
+ impt.declarationEnd = endStatementPosition;
+ impt.declarationSourceEnd =
+ this.flushAnnotationsDefinedPriorTo(impt.declarationSourceEnd);
+
+ // recovery
+ if (currentElement != null) {
+ lastCheckPoint = impt.declarationSourceEnd + 1;
+ currentElement = currentElement.add(impt, 0);
+ lastIgnoredToken = -1;
+ restartRecovery = true;
+ // used to avoid branching back into the regular automaton
+ }
+}
+protected void consumeSingleTypeImportDeclarationName() {
+ // SingleTypeImportDeclarationName ::= 'import' Name
+ /* push an ImportRef build from the last name
+ stored in the identifier stack. */
+
+ ImportReference impt;
+ int length;
+ char[][] tokens = new char[length = identifierLengthStack[identifierLengthPtr--]][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = new ImportReference(tokens, positions, false));
+
+ if (currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //endPosition is just before the ;
+ impt.declarationSourceStart = intStack[intPtr--];
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = impt.declarationSourceEnd+1;
+ currentElement = currentElement.add(impt, 0);
+ lastIgnoredToken = -1;
+ 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 Break(null, intStack[intPtr--], endPosition));
+}
+protected void consumeStatementBreakWithLabel() {
+ // BreakStatement ::= 'break' Identifier ';'
+ // break pushs a position on intStack in case there is no label
+
+ pushOnAstStack(
+ new Break(
+ identifierStack[identifierPtr--],
+ intStack[intPtr--],
+ endPosition));
+ 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
+
+ astLengthPtr--;
+ 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 Continue(
+ null,
+ intStack[intPtr--],
+ endPosition));
+}
+protected void consumeStatementContinueWithLabel() {
+ // ContinueStatement ::= 'continue' Identifier ';'
+ // continue pushs a position on intStack in case there is no label
+
+ pushOnAstStack(
+ new Continue(
+ identifierStack[identifierPtr--],
+ intStack[intPtr--],
+ endPosition));
+ identifierLengthPtr--;
+}
+protected void consumeStatementDo() {
+ // DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'
+
+ //the 'while' pushes a value on intStack that we need to remove
+ intPtr--;
+
+ //optimize the push/pop
+ Statement action = (Statement) astStack[astPtr];
+ if (action instanceof EmptyStatement
+ && problemReporter.options.complianceLevel <= CompilerOptions.JDK1_3) {
+ expressionLengthPtr--;
+ astStack[astPtr] =
+ new DoStatement(
+ expressionStack[expressionPtr--],
+ null,
+ intStack[intPtr--],
+ endPosition);
+ } else {
+ expressionLengthPtr--;
+ astStack[astPtr] =
+ new DoStatement(
+ expressionStack[expressionPtr--],
+ action,
+ intStack[intPtr--],
+ endPosition);
+ }
+}
+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;
+ Statement action;
+ boolean scope = true;
+
+ //statements
+ astLengthPtr--; // we need to consume it
+ action = (Statement) astStack[astPtr--];
+ if (action instanceof EmptyStatement
+ && problemReporter.options.complianceLevel <= CompilerOptions.JDK1_3) {
+ action = null;
+ }
+
+ //updates are on the expresion stack
+ if ((length = expressionLengthStack[expressionLengthPtr--]) == 0) {
+ updates = null;
+ } else {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ updates = new Statement[length],
+ 0,
+ length);
+ }
+
+ if (expressionLengthStack[expressionLengthPtr--] != 0)
+ cond = expressionStack[expressionPtr--];
+
+ //inits may be on two different stacks
+ if ((length = astLengthStack[astLengthPtr--]) == 0) {
+ inits = null;
+ scope = false;
+ } else {
+ if (length == -1) { //on expressionStack
+ scope = false;
+ length = expressionLengthStack[expressionLengthPtr--];
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ inits = new Statement[length],
+ 0,
+ length);
+ } else { //on astStack
+ astPtr -= length;
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ inits = new Statement[length],
+ 0,
+ length);
+ }
+ };
+ if (action instanceof Block) {
+ pushOnAstStack(
+ new ForStatement(
+ inits,
+ cond,
+ updates,
+ action,
+ scope,
+ intStack[intPtr--],
+ endStatementPosition));
+ } else {
+ pushOnAstStack(
+ new ForStatement(
+ inits,
+ cond,
+ updates,
+ action,
+ scope,
+ intStack[intPtr--],
+ endPosition));
+ }
+}
+protected void consumeStatementIfNoElse() {
+ // IfThenStatement ::= 'if' '(' Expression ')' Statement
+
+ //optimize the push/pop
+ expressionLengthPtr--;
+ Statement thenStatement = (Statement) astStack[astPtr];
+ if (thenStatement instanceof Block) {
+ astStack[astPtr] =
+ new IfStatement(
+ expressionStack[expressionPtr--],
+ thenStatement,
+ intStack[intPtr--],
+ endStatementPosition);
+ } else if (thenStatement instanceof EmptyStatement) {
+ astStack[astPtr] =
+ new IfStatement(
+ expressionStack[expressionPtr--],
+ Block.None,
+ intStack[intPtr--],
+ endStatementPosition);
+ } else {
+ astStack[astPtr] =
+ new IfStatement(
+ expressionStack[expressionPtr--],
+ thenStatement,
+ intStack[intPtr--],
+ endStatementPosition);
+ }
+}
+protected void consumeStatementIfWithElse() {
+ // IfThenElseStatement ::= 'if' '(' Expression ')' StatementNoShortIf 'else' Statement
+ // IfThenElseStatementNoShortIf ::= 'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf
+
+ astLengthPtr--; // optimized {..., Then, Else } ==> {..., If }
+ expressionLengthPtr--;
+ //optimize the push/pop
+ Statement elseStatement = (Statement) astStack[astPtr--];
+ Statement thenStatement = (Statement) astStack[astPtr];
+ if (elseStatement instanceof EmptyStatement) {
+ elseStatement = Block.None;
+ }
+ if (thenStatement instanceof EmptyStatement) {
+ thenStatement = Block.None;
+ }
+ if (elseStatement instanceof Block) {
+ astStack[astPtr] =
+ new IfStatement(
+ expressionStack[expressionPtr--],
+ thenStatement,
+ elseStatement,
+ intStack[intPtr--],
+ endStatementPosition);
+ } else {
+ astStack[astPtr] =
+ new IfStatement(
+ expressionStack[expressionPtr--],
+ thenStatement,
+ elseStatement,
+ intStack[intPtr--],
+ endStatementPosition);
+ }
+}
+protected void consumeStatementLabel() {
+ // LabeledStatement ::= 'Identifier' ':' Statement
+ // LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf
+
+ //optimize push/pop
+
+ Statement stmt = (Statement) astStack[astPtr];
+ if (stmt instanceof EmptyStatement) {
+ astStack[astPtr] =
+ new LabeledStatement(
+ identifierStack[identifierPtr],
+ Block.None,
+ (int) (identifierPositionStack[identifierPtr--] >>> 32),
+ endStatementPosition);
+ } else {
+ astStack[astPtr] =
+ new LabeledStatement(
+ identifierStack[identifierPtr],
+ stmt,
+ (int) (identifierPositionStack[identifierPtr--] >>> 32),
+ endStatementPosition);
+ }
+ identifierLengthPtr--;
+}
+protected void consumeStatementReturn() {
+ // ReturnStatement ::= 'return' Expressionopt ';'
+ // return pushs a position on intStack in case there is no expression
+
+ if (expressionLengthStack[expressionLengthPtr--] != 0) {
+ pushOnAstStack(
+ new ReturnStatement(
+ expressionStack[expressionPtr--],
+ intStack[intPtr--],
+ endPosition)
+ );
+ } else {
+ pushOnAstStack(new ReturnStatement(null, intStack[intPtr--], 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 s = new SwitchStatement();
+ expressionLengthPtr--;
+ s.testExpression = expressionStack[expressionPtr--];
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ astPtr -= length;
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ s.statements = new Statement[length],
+ 0,
+ length);
+ }
+ s.explicitDeclarations = realBlockStack[realBlockPtr--];
+ pushOnAstStack(s);
+ intPtr--; // because of OpenBlock
+ s.sourceStart = intStack[intPtr--];
+ s.sourceEnd = endStatementPosition;
+}
+protected void consumeStatementSynchronized() {
+ // SynchronizedStatement ::= OnlySynchronized '(' Expression ')' Block
+ //optimize the push/pop
+
+ if (astLengthStack[astLengthPtr] == 0) {
+ astLengthStack[astLengthPtr] = 1;
+ expressionLengthPtr--;
+ astStack[++astPtr] =
+ new SynchronizedStatement(
+ expressionStack[expressionPtr--],
+ Block.None,
+ intStack[intPtr--],
+ endStatementPosition);
+ } else {
+ expressionLengthPtr--;
+ astStack[astPtr] =
+ new SynchronizedStatement(
+ expressionStack[expressionPtr--],
+ (Block) astStack[astPtr],
+ intStack[intPtr--],
+ endStatementPosition);
+ }
+ resetModifiers();
+}
+protected void consumeStatementThrow() {
+ // ThrowStatement ::= 'throw' Expression ';'
+ expressionLengthPtr--;
+ pushOnAstStack(new ThrowStatement(expressionStack[expressionPtr--], intStack[intPtr--]));
+}
+protected void consumeStatementTry(boolean withFinally) {
+ //TryStatement ::= 'try' Block Catches
+ //TryStatement ::= 'try' Block Catchesopt Finally
+
+ int length;
+ TryStatement tryStmt = new TryStatement();
+ //finally
+ if (withFinally) {
+ astLengthPtr--;
+ tryStmt.finallyBlock = (Block) astStack[astPtr--];
+ }
+ //catches are handle by two <argument-block> [see statementCatch]
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ if (length == 1) {
+ tryStmt.catchBlocks = new Block[] {(Block) astStack[astPtr--]};
+ tryStmt.catchArguments = new Argument[] {(Argument) astStack[astPtr--]};
+ } else {
+ Block[] bks = (tryStmt.catchBlocks = new Block[length]);
+ Argument[] args = (tryStmt.catchArguments = new Argument[length]);
+ while (length-- > 0) {
+ bks[length] = (Block) astStack[astPtr--];
+ args[length] = (Argument) astStack[astPtr--];
+ }
+ }
+ }
+ //try
+ astLengthPtr--;
+ tryStmt.tryBlock = (Block) astStack[astPtr--];
+
+ //positions
+ tryStmt.sourceEnd = endStatementPosition;
+ tryStmt.sourceStart = intStack[intPtr--];
+ pushOnAstStack(tryStmt);
+}
+protected void consumeStatementWhile() {
+ // WhileStatement ::= 'while' '(' Expression ')' Statement
+ // WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf
+
+ Statement action = (Statement) astStack[astPtr];
+ expressionLengthPtr--;
+ if (action instanceof Block) {
+ astStack[astPtr] =
+ new WhileStatement(
+ expressionStack[expressionPtr--],
+ action,
+ intStack[intPtr--],
+ endStatementPosition);
+ } else {
+ if (action instanceof EmptyStatement
+ && problemReporter.options.complianceLevel <= CompilerOptions.JDK1_3) {
+ astStack[astPtr] =
+ new WhileStatement(
+ expressionStack[expressionPtr--],
+ null,
+ intStack[intPtr--],
+ endPosition);
+ } else {
+ astStack[astPtr] =
+ new WhileStatement(
+ expressionStack[expressionPtr--],
+ action,
+ intStack[intPtr--],
+ endPosition);
+ }
+ }
+}
+protected void consumeStaticInitializer() {
+ // StaticInitializer ::= StaticOnly Block
+ //push an Initializer
+ //optimize the push/pop
+ Initializer initializer = new Initializer((Block) astStack[astPtr], AccStatic);
+ astStack[astPtr] = initializer;
+ initializer.sourceEnd = endStatementPosition;
+ initializer.declarationSourceEnd = flushAnnotationsDefinedPriorTo(endStatementPosition);
+ nestedMethod[nestedType] --;
+ initializer.declarationSourceStart = intStack[intPtr--];
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = initializer.declarationSourceEnd;
+ currentElement = currentElement.add(initializer, 0);
+ lastIgnoredToken = -1;
+ }
+}
+protected void consumeStaticOnly() {
+ // StaticOnly ::= 'static'
+ int savedModifiersSourceStart = modifiersSourceStart;
+ checkAnnotation(); // might update declaration source start
+ if (modifiersSourceStart >= savedModifiersSourceStart) {
+ modifiersSourceStart = savedModifiersSourceStart;
+ }
+ pushOnIntStack(
+ modifiersSourceStart >= 0 ? modifiersSourceStart : scanner.startPosition);
+ jumpOverMethodBody();
+ nestedMethod[nestedType]++;
+ resetModifiers();
+
+ // recovery
+ if (currentElement != null){
+ recoveredStaticInitializerStart = intStack[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 */
+ if (scanner.wasNonExternalizedStringLiteral) {
+ StringLiteral[] literals = this.scanner.nonNLSStrings;
+ // could not reproduce, but this is the only NPE
+ // added preventive null check see PR 9035
+ if (literals != null) {
+ for (int i = 0, max = literals.length; i < max; i++) {
+ problemReporter().nonExternalizedStringLiteral(literals[i]);
+ }
+ }
+ scanner.currentLine = null;
+ scanner.wasNonExternalizedStringLiteral = false;
+ }
+ // clear the commentPtr of the scanner in case we read something different from a modifier
+ switch(type) {
+// case TokenNameabstract :
+// case TokenNamestrictfp :
+// case TokenNamefinal :
+// case TokenNamenative :
+// case TokenNameprivate :
+// case TokenNameprotected :
+// case TokenNamepublic :
+// case TokenNametransient :
+// case TokenNamevolatile :
+ case TokenNamestatic :
+// case TokenNamesynchronized :
+ break;
+ default:
+ scanner.commentPtr = -1;
+ }
+ //System.out.println(scanner.toStringAction(type));
+ switch (type) {
+ case TokenNameIdentifier :
+ pushIdentifier();
+ if (scanner.useAssertAsAnIndentifier) {
+ long positions = identifierPositionStack[identifierPtr];
+ problemReporter().useAssertAsAnIdentifier((int) (positions >>> 32), (int) positions);
+ }
+ scanner.commentPtr = -1;
+ break;
+// case TokenNameinterface :
+// adjustInterfaceModifiers();
+// //'class' is pushing two int (positions) on the stack ==> 'interface' needs to do it too....
+// pushOnIntStack(scanner.startPosition);
+// pushOnIntStack(scanner.currentPosition - 1);
+// scanner.commentPtr = -1;
+// 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 = scanner.startPosition;
+// checkAndSetModifiers(AccSynchronized);
+// break;
+// //==============================
+// case TokenNamevoid :
+// pushIdentifier(-T_void);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// 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(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+// case TokenNamebyte :
+// pushIdentifier(-T_byte);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+// case TokenNamechar :
+// pushIdentifier(-T_char);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+// case TokenNamedouble :
+// pushIdentifier(-T_double);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+// case TokenNamefloat :
+// pushIdentifier(-T_float);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+// case TokenNameint :
+// pushIdentifier(-T_int);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+// case TokenNamelong :
+// pushIdentifier(-T_long);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+// case TokenNameshort :
+// pushIdentifier(-T_short);
+// pushOnIntStack(scanner.currentPosition - 1);
+// pushOnIntStack(scanner.startPosition);
+// scanner.commentPtr = -1;
+// break;
+ //==============================
+ case TokenNameIntegerLiteral :
+ pushOnExpressionStack(
+ new IntLiteral(
+ scanner.getCurrentTokenSource(),
+ scanner.startPosition,
+ scanner.currentPosition - 1));
+ scanner.commentPtr = -1;
+ break;
+ case TokenNameLongLiteral :
+ pushOnExpressionStack(
+ new LongLiteral(
+ scanner.getCurrentTokenSource(),
+ scanner.startPosition,
+ scanner.currentPosition - 1));
+ scanner.commentPtr = -1;
+ break;
+ case TokenNameFloatingPointLiteral :
+ pushOnExpressionStack(
+ new FloatLiteral(
+ scanner.getCurrentTokenSource(),
+ scanner.startPosition,
+ scanner.currentPosition - 1));
+ scanner.commentPtr = -1;
+ break;
+ case TokenNameDoubleLiteral :
+ pushOnExpressionStack(
+ new DoubleLiteral(
+ scanner.getCurrentTokenSource(),
+ scanner.startPosition,
+ scanner.currentPosition - 1));
+ scanner.commentPtr = -1;
+ break;
+ case TokenNameCharacterLiteral :
+ pushOnExpressionStack(
+ new CharLiteral(
+ scanner.getCurrentTokenSource(),
+ scanner.startPosition,
+ scanner.currentPosition - 1));
+ scanner.commentPtr = -1;
+ break;
+ case TokenNameStringLiteral :
+ StringLiteral stringLiteral = new StringLiteral(
+ scanner.getCurrentTokenSourceString(),
+ scanner.startPosition,
+ scanner.currentPosition - 1);
+ pushOnExpressionStack(stringLiteral);
+ scanner.commentPtr = -1;
+ break;
+ case TokenNamefalse :
+ pushOnExpressionStack(
+ new FalseLiteral(scanner.startPosition, scanner.currentPosition - 1));
+ scanner.commentPtr = -1;
+ break;
+ case TokenNametrue :
+ pushOnExpressionStack(
+ new TrueLiteral(scanner.startPosition, scanner.currentPosition - 1));
+ break;
+ case TokenNamenull :
+ pushOnExpressionStack(
+ new NullLiteral(scanner.startPosition, scanner.currentPosition - 1));
+ break;
+ //============================
+// case TokenNamesuper :
+// case TokenNamethis :
+// endPosition = scanner.currentPosition - 1;
+// pushOnIntStack(scanner.startPosition);
+// break;
+// case TokenNameassert :
+// case TokenNameimport :
+// case TokenNamepackage :
+// case TokenNamethrow :
+ case TokenNamenew :
+ case TokenNamedo :
+ case TokenNameif :
+ case TokenNamefor :
+ case TokenNameswitch :
+// case TokenNametry :
+ case TokenNamewhile :
+ case TokenNamebreak :
+ case TokenNamecontinue :
+ case TokenNamereturn :
+ case TokenNamecase :
+ pushOnIntStack(scanner.startPosition);
+ break;
+ case TokenNameclass :
+ pushOnIntStack(scanner.currentPosition - 1);
+ pushOnIntStack(scanner.startPosition);
+ break;
+ case TokenNamedefault :
+ pushOnIntStack(scanner.startPosition);
+ pushOnIntStack(scanner.currentPosition - 1);
+ break;
+ //let extra semantic action decide when to push
+ case TokenNameRBRACKET :
+ case TokenNamePLUS :
+ case TokenNameMINUS :
+ case TokenNameNOT :
+ case TokenNameTWIDDLE :
+ endPosition = scanner.startPosition;
+ break;
+ case TokenNamePLUS_PLUS :
+ case TokenNameMINUS_MINUS :
+ endPosition = scanner.startPosition;
+ endStatementPosition = scanner.currentPosition - 1;
+ break;
+ case TokenNameRBRACE:
+ case TokenNameSEMICOLON :
+ endStatementPosition = scanner.currentPosition - 1;
+ endPosition = 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 :
+ rParenPos = scanner.currentPosition - 1; // position of the end of right parenthesis (in case of unicode \u0029) lex00101
+ break;
+ case TokenNameLPAREN :
+ lParenPos = 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 = astLengthStack[astLengthPtr--]) != 0) {
+ astPtr -= length;
+ System.arraycopy(astStack, astPtr + 1, compilationUnit.types = new TypeDeclaration[length], 0, length);
+ }
+}
+protected void consumeTypeImportOnDemandDeclaration() {
+ // TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'
+
+ ImportReference impt = (ImportReference) astStack[astPtr];
+ // flush annotations defined prior to import statements
+ impt.declarationEnd = endStatementPosition;
+ impt.declarationSourceEnd =
+ this.flushAnnotationsDefinedPriorTo(impt.declarationSourceEnd);
+
+ // recovery
+ if (currentElement != null) {
+ lastCheckPoint = impt.declarationSourceEnd + 1;
+ currentElement = currentElement.add(impt, 0);
+ restartRecovery = true;
+ 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 = identifierLengthStack[identifierLengthPtr--]][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(identifierPositionStack, identifierPtr + 1, positions, 0, length);
+ pushOnAstStack(impt = new ImportReference(tokens, positions, true));
+
+ if (currentToken == TokenNameSEMICOLON){
+ impt.declarationSourceEnd = scanner.currentPosition - 1;
+ } else {
+ impt.declarationSourceEnd = impt.sourceEnd;
+ }
+ impt.declarationEnd = impt.declarationSourceEnd;
+ //endPosition is just before the ;
+ impt.declarationSourceStart = intStack[intPtr--];
+
+ // recovery
+ if (currentElement != null){
+ lastCheckPoint = impt.declarationSourceEnd+1;
+ currentElement = currentElement.add(impt, 0);
+ lastIgnoredToken = -1;
+ 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 = expressionStack[expressionPtr];
+ if (op == MINUS) {
+ if ((exp instanceof IntLiteral) && (((IntLiteral) exp).mayRepresentMIN_VALUE())) {
+ r = expressionStack[expressionPtr] = new IntLiteralMinValue();
+ } else {
+ if ((exp instanceof LongLiteral) && (((LongLiteral) exp).mayRepresentMIN_VALUE())) {
+ r = expressionStack[expressionPtr] = new LongLiteralMinValue();
+ } else {
+ r = expressionStack[expressionPtr] = new UnaryExpression(exp, op);
+ }
+ }
+ } else {
+ r = expressionStack[expressionPtr] = new UnaryExpression(exp, op);
+ }
+ r.sourceStart = intStack[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 = expressionStack[expressionPtr];
+ if (leftHandSide instanceof Reference) {
+ // ++foo()++ is unvalid
+ if (post) {
+ expressionStack[expressionPtr] =
+ new PostfixExpression(
+ leftHandSide,
+ IntLiteral.One,
+ op,
+ endStatementPosition);
+ } else {
+ expressionStack[expressionPtr] =
+ new PrefixExpression(
+ leftHandSide,
+ IntLiteral.One,
+ op,
+ intStack[intPtr--]);
+ }
+ } else {
+ //the ++ or the -- is NOT taken into account if code gen proceeds
+ if (!post) {
+ intPtr--;
+ }
+ problemReporter().invalidUnaryExpression(leftHandSide);
+ }
+}
+protected void consumeVariableDeclarators() {
+ // VariableDeclarators ::= VariableDeclarators ',' VariableDeclarator
+ optimizedConcatNodeLists();
+}
+protected void consumeVariableInitializers() {
+ // VariableInitializers ::= VariableInitializers ',' VariableInitializer
+ concatExpressionLists();
+}
+protected TypeReference copyDims(TypeReference typeRef, int dim) {
+ return typeRef.copyDims(dim);
+}
+protected FieldDeclaration createFieldDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+ return new FieldDeclaration(null, name, sourceStart, sourceEnd);
+}
+
+protected LocalDeclaration createLocalDeclaration(Expression initialization, char[] name, int sourceStart, int sourceEnd) {
+ return new LocalDeclaration(null, name, sourceStart, sourceEnd);
+}
+
+public CompilationUnitDeclaration dietParse(ICompilationUnit sourceUnit, CompilationResult compilationResult) {
+
+ CompilationUnitDeclaration parsedUnit;
+ boolean old = diet;
+ try {
+ diet = true;
+ parsedUnit = parse(sourceUnit, compilationResult);
+ }
+ finally {
+ 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 = astStack[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) astStack[astPtr];
+ if (size1 != 0)
+ typeDecl.fields = new FieldDeclaration[size1];
+ if (size2 != 0)
+ typeDecl.methods = new AbstractMethodDeclaration[size2];
+ if (size3 != 0)
+ typeDecl.memberTypes = new MemberTypeDeclaration[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(
+ astStack,
+ astPtr + start + 1,
+ typeDecl.fields,
+ size1 - length2,
+ length2);
+ break;
+ case 3 :
+ size2 += (length2 = end - start);
+ System.arraycopy(
+ astStack,
+ astPtr + start + 1,
+ typeDecl.methods,
+ size2 - length2,
+ length2);
+ break;
+ case 4 :
+ size3 += (length2 = end - start);
+ System.arraycopy(
+ astStack,
+ 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 (currentElement != null){
+ 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(compilationUnit);
+ System.out.println("----------------------------------"); //$NON-NLS-1$
+ }
+ } else {
+ if (diet & VERBOSE_RECOVERY){
+ System.out.print(Util.bind("parser.regularParse")); //$NON-NLS-1$
+ System.out.println("--------------------------"); //$NON-NLS-1$
+ System.out.println(compilationUnit);
+ System.out.println("----------------------------------"); //$NON-NLS-1$
+ }
+ }
+ if (scanner.recordLineSeparator) {
+ compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
+ }
+ return compilationUnit;
+}
+/*
+ * Flush annotations defined prior to a given positions.
+ *
+ * Note: annotations are stacked in syntactical order
+ *
+ * Either answer given <position>, or the end position of a comment line
+ * immediately following the <position> (same line)
+ *
+ * e.g.
+ * void foo(){
+ * } // end of method foo
+ */
+
+public int flushAnnotationsDefinedPriorTo(int position) {
+
+ int lastAnnotationIndex = scanner.commentPtr;
+ if (lastAnnotationIndex < 0) return position; // no comment
+
+ // compute the index of the first obsolete comment
+ int index = lastAnnotationIndex;
+ int validCount = 0;
+ while (index >= 0){
+ int commentEnd = 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 = -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 (scanner.getLineNumber(position) == scanner.getLineNumber(immediateCommentEnd)){
+ position = immediateCommentEnd;
+ validCount--; // flush this comment
+ index++;
+ }
+ }
+ }
+ // position can be located in the middle of a line break
+ // this is a bug on Windows platform only.
+ // http://dev.eclipse.org/bugs/show_bug.cgi?id=10557
+ char[] source = scanner.source;
+
+ if ((position < source.length)
+ && (source[position] == '\r')
+ && ((position + 1) < source.length)
+ && (source[position + 1] == '\n')) {
+ position++;
+ }
+ if (index < 0) return position; // no obsolete comment
+
+ if (validCount > 0){ // move valid comment infos, overriding obsolete comment infos
+ System.arraycopy(scanner.commentStarts, index + 1, scanner.commentStarts, 0, validCount);
+ System.arraycopy(scanner.commentStops, index + 1, scanner.commentStops, 0, validCount);
+ }
+ 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 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 = scanner.commentPtr; i <= max; i++){
+ // javadoc only (non javadoc comment have negative end positions.)
+ if (scanner.commentStops[i] > 0){
+ javadocCount++;
+ }
+ }
+ if (javadocCount == 0) return null;
+
+ int[] positions = new int[2*javadocCount];
+ int index = 0;
+ for (int i = 0, max = scanner.commentPtr; i <= max; i++){
+ // javadoc only (non javadoc comment have negative end positions.)
+ if (scanner.commentStops[i] > 0){
+ positions[index++] = scanner.commentStarts[i];
+ positions[index++] = scanner.commentStops[i]-1; //stop is one over
+ }
+ }
+ return positions;
+}
+ protected 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.
+ }
+
+ //real parse of the method....
+ this.scanner.setSource(
+ unit.compilationResult.compilationUnit.getContents());
+ if (unit.types != null) {
+ for (int i = unit.types.length; --i >= 0;)
+ unit.types[i].parseMethod(this, unit);
+ }
+ }
+protected TypeReference getTypeReference(int dim) { /* build a Reference on a variable that may be qualified or not
+This variable is a type reference and dim will be its dimensions*/
+
+ int length;
+ TypeReference ref;
+ if ((length = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ if (dim == 0) {
+ ref =
+ new SingleTypeReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ } else {
+ ref =
+ new ArrayTypeReference(
+ identifierStack[identifierPtr],
+ dim,
+ identifierPositionStack[identifierPtr--]);
+ ref.sourceEnd = endPosition;
+ }
+ } else {
+ if (length < 0) { //flag for precompiled type reference on base types
+ ref = TypeReference.baseTypeReference(-length, dim);
+ ref.sourceStart = intStack[intPtr--];
+ if (dim == 0) {
+ ref.sourceEnd = intStack[intPtr--];
+ } else {
+ intPtr--;
+ ref.sourceEnd = endPosition;
+ }
+ } else { //Qualified variable reference
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ long[] positions = new long[length];
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ System.arraycopy(
+ identifierPositionStack,
+ identifierPtr + 1,
+ positions,
+ 0,
+ length);
+ if (dim == 0) {
+ ref = new QualifiedTypeReference(tokens, positions);
+ } else {
+ ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
+ ref.sourceEnd = endPosition;
+ }
+ }
+ };
+ 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 = identifierLengthStack[identifierLengthPtr--]) == 1)
+ // single variable reference
+ ref =
+ new SingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[identifierPtr--]);
+ else
+ //Qualified variable reference
+ {
+ char[][] tokens = new char[length][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ ref =
+ new QualifiedNameReference(tokens,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
+ (int) identifierPositionStack[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 = identifierLengthStack[identifierLengthPtr--]) == 1) {
+ // single variable reference
+ ref =
+ new SingleNameReference(
+ identifierStack[identifierPtr],
+ identifierPositionStack[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][];
+ identifierPtr -= length;
+ System.arraycopy(identifierStack, identifierPtr + 1, tokens, 0, length);
+ ref = new QualifiedNameReference(
+ tokens,
+ (int) (identifierPositionStack[identifierPtr + 1] >> 32), // sourceStart
+ (int) identifierPositionStack[identifierPtr + length]); // sourceEnd
+ ref.bits &= ~AstNode.RestrictiveFlagMASK;
+ ref.bits |= LOCAL | FIELD;
+ return ref;
+}
+public void goForBlockStatementsOrMethodHeaders() {
+ //tells the scanner to go for block statements or method headers parsing
+
+ firstToken = TokenNameMULTIPLY;
+ scanner.recordLineSeparator = false;
+}
+public void goForClassBodyDeclarations() {
+ //tells the scanner to go for any body declarations parsing
+
+ firstToken = TokenNameAND;
+ scanner.recordLineSeparator = true;
+}
+public void goForCompilationUnit(){
+ //tells the scanner to go for compilation unit parsing
+
+ firstToken = TokenNamePLUS_PLUS ;
+ scanner.linePtr = -1;
+ scanner.recordLineSeparator = true;
+ scanner.currentLine= null;
+ scanner.lines= new ArrayList();
+}
+public void goForConstructorBody(){
+ //tells the scanner to go for compilation unit parsing
+
+ firstToken = TokenNameEQUAL_EQUAL ;
+ scanner.recordLineSeparator = false;
+}
+public void goForExpression() {
+ //tells the scanner to go for an expression parsing
+
+ firstToken = TokenNameREMAINDER;
+ scanner.recordLineSeparator = false;
+}
+public void goForFieldDeclaration(){
+ //tells the scanner to go for field declaration parsing
+
+ firstToken = TokenNameAND_AND ;
+ scanner.recordLineSeparator = true;
+}
+public void goForGenericMethodDeclaration(){
+ //tells the scanner to go for generic method declarations parsing
+
+ firstToken = TokenNameDIVIDE;
+ scanner.recordLineSeparator = true;
+}
+public void goForHeaders(){
+ //tells the scanner to go for headers only parsing
+
+ firstToken = TokenNameUNSIGNED_RIGHT_SHIFT;
+ scanner.recordLineSeparator = true;
+}
+public void goForImportDeclaration(){
+ //tells the scanner to go for import declaration parsing
+
+ firstToken = TokenNameOR_OR ;
+ scanner.recordLineSeparator = true;
+}
+public void goForInitializer(){
+ //tells the scanner to go for initializer parsing
+
+ firstToken = TokenNameRIGHT_SHIFT ;
+ scanner.recordLineSeparator = false;
+}
+public void goForMethodBody(){
+ //tells the scanner to go for method body parsing
+
+ firstToken = TokenNameMINUS_MINUS ;
+ scanner.recordLineSeparator = false;
+}
+public void goForPackageDeclaration() {
+ //tells the scanner to go for package declaration parsing
+
+ firstToken = TokenNameQUESTION;
+ scanner.recordLineSeparator = true;
+}
+public void goForTypeDeclaration() {
+ //tells the scanner to go for type (interface or class) declaration parsing
+
+ firstToken = TokenNamePLUS;
+ scanner.recordLineSeparator = true;
+}
+public final static void grammar(){
+/*
+--main options
+%options ACTION, AN=JavaAction.java, GP=java,
+%options FILE-PREFIX=java, ESCAPE=$, PREFIX=TokenName, OUTPUT-SIZE=125 ,
+%options NOGOTO-DEFAULT, SINGLE-PRODUCTIONS, LALR=1 , TABLE=TIME ,
+
+--error recovering options.....
+%options ERROR_MAPS
+
+--grammar understanding options
+%options first follow
+%options TRACE=FULL ,
+%options VERBOSE
+
+--Usefull macros helping reading/writing semantic actions
+$Define
+$putCase
+/. case $rule_number : // System.out.println("$rule_text");
+ ./
+
+$break
+/.
+ break ;
+./
+
+-- here it starts really ------------------------------------------
+$Terminals
+
+ Identifier
+
+ abstract assert boolean break byte case catch char class
+ continue default do double else extends false final finally float
+ for if implements import instanceof int
+ interface long native new null package private
+ protected public return short static strictfp super switch
+ synchronized this throw throws transient true try void
+ volatile while
+
+ IntegerLiteral
+ LongLiteral
+ FloatingPointLiteral
+ DoubleLiteral
+ CharacterLiteral
+ StringLiteral
+
+ PLUS_PLUS
+ MINUS_MINUS
+ EQUAL_EQUAL
+ LESS_EQUAL
+ GREATER_EQUAL
+ NOT_EQUAL
+ LEFT_SHIFT
+ RIGHT_SHIFT
+ UNSIGNED_RIGHT_SHIFT
+ PLUS_EQUAL
+ MINUS_EQUAL
+ MULTIPLY_EQUAL
+ DIVIDE_EQUAL
+ AND_EQUAL
+ OR_EQUAL
+ XOR_EQUAL
+ REMAINDER_EQUAL
+ LEFT_SHIFT_EQUAL
+ RIGHT_SHIFT_EQUAL
+ UNSIGNED_RIGHT_SHIFT_EQUAL
+ OR_OR
+ AND_AND
+ PLUS
+ MINUS
+ NOT
+ REMAINDER
+ XOR
+ AND
+ MULTIPLY
+ OR
+ TWIDDLE
+ DIVIDE
+ GREATER
+ LESS
+ LPAREN
+ RPAREN
+ LBRACE
+ RBRACE
+ LBRACKET
+ RBRACKET
+ SEMICOLON
+ QUESTION
+ COLON
+ COMMA
+ DOT
+ EQUAL
+
+-- BodyMarker
+
+$Alias
+
+ '++' ::= PLUS_PLUS
+ '--' ::= MINUS_MINUS
+ '==' ::= EQUAL_EQUAL
+ '<=' ::= LESS_EQUAL
+ '>=' ::= GREATER_EQUAL
+ '!=' ::= NOT_EQUAL
+ '<<' ::= LEFT_SHIFT
+ '>>' ::= RIGHT_SHIFT
+ '>>>' ::= UNSIGNED_RIGHT_SHIFT
+ '+=' ::= PLUS_EQUAL
+ '-=' ::= MINUS_EQUAL
+ '*=' ::= MULTIPLY_EQUAL
+ '/=' ::= DIVIDE_EQUAL
+ '&=' ::= AND_EQUAL
+ '|=' ::= OR_EQUAL
+ '^=' ::= XOR_EQUAL
+ '%=' ::= REMAINDER_EQUAL
+ '<<=' ::= LEFT_SHIFT_EQUAL
+ '>>=' ::= RIGHT_SHIFT_EQUAL
+ '>>>=' ::= UNSIGNED_RIGHT_SHIFT_EQUAL
+ '||' ::= OR_OR
+ '&&' ::= AND_AND
+
+ '+' ::= PLUS
+ '-' ::= MINUS
+ '!' ::= NOT
+ '%' ::= REMAINDER
+ '^' ::= XOR
+ '&' ::= AND
+ '*' ::= MULTIPLY
+ '|' ::= OR
+ '~' ::= TWIDDLE
+ '/' ::= DIVIDE
+ '>' ::= GREATER
+ '<' ::= LESS
+ '(' ::= LPAREN
+ ')' ::= RPAREN
+ '{' ::= LBRACE
+ '}' ::= RBRACE
+ '[' ::= LBRACKET
+ ']' ::= RBRACKET
+ ';' ::= SEMICOLON
+ '?' ::= QUESTION
+ ':' ::= COLON
+ ',' ::= COMMA
+ '.' ::= DOT
+ '=' ::= EQUAL
+
+$Start
+ Goal
+
+$Rules
+
+/. // This method is part of an automatic generation : do NOT edit-modify
+protected void consumeRule(int act) {
+ switch ( act ) {
+./
+
+
+
+Goal ::= '++' CompilationUnit
+Goal ::= '--' MethodBody
+Goal ::= '==' ConstructorBody
+-- Initializer
+Goal ::= '>>' StaticInitializer
+Goal ::= '>>' Initializer
+-- error recovery
+Goal ::= '>>>' Headers
+Goal ::= '*' BlockStatements
+Goal ::= '*' MethodPushModifiersHeader
+Goal ::= '*' CatchHeader
+-- JDOM
+Goal ::= '&&' FieldDeclaration
+Goal ::= '||' ImportDeclaration
+Goal ::= '?' PackageDeclaration
+Goal ::= '+' TypeDeclaration
+Goal ::= '/' GenericMethodDeclaration
+Goal ::= '&' ClassBodyDeclaration
+-- code snippet
+Goal ::= '%' Expression
+-- completion parser
+Goal ::= '!' ConstructorBlockStatementsopt
+Goal ::= '~' BlockStatementsopt
+
+Literal -> IntegerLiteral
+Literal -> LongLiteral
+Literal -> FloatingPointLiteral
+Literal -> DoubleLiteral
+Literal -> CharacterLiteral
+Literal -> StringLiteral
+Literal -> null
+Literal -> BooleanLiteral
+BooleanLiteral -> true
+BooleanLiteral -> false
+
+-------------------------------------------------------------
+-------------------------------------------------------------
+--a Type results in both a push of its dimension(s) and its name(s).
+
+Type ::= PrimitiveType
+ /.$putCase consumePrimitiveType(); $break ./
+Type -> ReferenceType
+
+PrimitiveType -> NumericType
+NumericType -> IntegralType
+NumericType -> FloatingPointType
+
+PrimitiveType -> 'boolean'
+PrimitiveType -> 'void'
+IntegralType -> 'byte'
+IntegralType -> 'short'
+IntegralType -> 'int'
+IntegralType -> 'long'
+IntegralType -> 'char'
+FloatingPointType -> 'float'
+FloatingPointType -> 'double'
+
+ReferenceType ::= ClassOrInterfaceType
+/.$putCase consumeReferenceType(); $break ./
+ReferenceType -> ArrayType -- here a push of dimensions is done, that explains the two previous push 0
+
+ClassOrInterfaceType -> Name
+
+--
+-- These rules have been rewritten to avoid some conflicts introduced
+-- by adding the 1.1 features
+--
+-- ArrayType ::= PrimitiveType '[' ']'
+-- ArrayType ::= Name '[' ']'
+-- ArrayType ::= ArrayType '[' ']'
+--
+
+ArrayType ::= PrimitiveType Dims
+ArrayType ::= Name Dims
+
+ClassType -> ClassOrInterfaceType
+
+
+--------------------------------------------------------------
+--------------------------------------------------------------
+
+Name -> SimpleName
+Name -> QualifiedName
+
+SimpleName -> 'Identifier'
+
+QualifiedName ::= Name '.' SimpleName
+/.$putCase consumeQualifiedName(); $break ./
+
+CompilationUnit ::= EnterCompilationUnit PackageDeclarationopt ImportDeclarationsopt TypeDeclarationsopt
+/.$putCase consumeCompilationUnit(); $break ./
+
+EnterCompilationUnit ::= $empty
+/.$putCase consumeEnterCompilationUnit(); $break ./
+
+Headers -> Header
+Headers ::= Headers Header
+
+Header -> ImportDeclaration
+Header -> PackageDeclaration
+Header -> ClassHeader
+Header -> InterfaceHeader
+Header -> StaticInitializer
+Header -> MethodHeader
+Header -> ConstructorHeader
+Header -> FieldDeclaration
+Header -> AllocationHeader
+
+CatchHeader ::= 'catch' '(' FormalParameter ')' '{'
+/.$putCase consumeCatchHeader(); $break ./
+
+ImportDeclarations -> ImportDeclaration
+ImportDeclarations ::= ImportDeclarations ImportDeclaration
+/.$putCase consumeImportDeclarations(); $break ./
+
+TypeDeclarations -> TypeDeclaration
+TypeDeclarations ::= TypeDeclarations TypeDeclaration
+/.$putCase consumeTypeDeclarations(); $break ./
+
+PackageDeclaration ::= PackageDeclarationName ';'
+/.$putCase consumePackageDeclaration(); $break ./
+
+PackageDeclarationName ::= 'package' Name
+/.$putCase consumePackageDeclarationName(); $break ./
+
+ImportDeclaration -> SingleTypeImportDeclaration
+ImportDeclaration -> TypeImportOnDemandDeclaration
+
+SingleTypeImportDeclaration ::= SingleTypeImportDeclarationName ';'
+/.$putCase consumeSingleTypeImportDeclaration(); $break ./
+
+SingleTypeImportDeclarationName ::= 'import' Name
+/.$putCase consumeSingleTypeImportDeclarationName(); $break ./
+
+TypeImportOnDemandDeclaration ::= TypeImportOnDemandDeclarationName ';'
+/.$putCase consumeTypeImportOnDemandDeclaration(); $break ./
+
+TypeImportOnDemandDeclarationName ::= 'import' Name '.' '*'
+/.$putCase consumeTypeImportOnDemandDeclarationName(); $break ./
+
+TypeDeclaration -> ClassDeclaration
+TypeDeclaration -> InterfaceDeclaration
+-- this declaration in part of a list od declaration and we will
+-- use and optimized list length calculation process
+-- thus we decrement the number while it will be incremend.....
+TypeDeclaration ::= ';'
+/. $putCase consumeEmptyTypeDeclaration(); $break ./
+
+--18.7 Only in the LALR(1) Grammar
+
+Modifiers ::= Modifier
+Modifiers ::= Modifiers Modifier
+
+Modifier -> 'public'
+Modifier -> 'protected'
+Modifier -> 'private'
+Modifier -> 'static'
+Modifier -> 'abstract'
+Modifier -> 'final'
+Modifier -> 'native'
+Modifier -> 'synchronized'
+Modifier -> 'transient'
+Modifier -> 'volatile'
+Modifier -> 'strictfp'
+
+--18.8 Productions from 8: Class Declarations
+--ClassModifier ::=
+-- 'abstract'
+-- | 'final'
+-- | 'public'
+--18.8.1 Productions from 8.1: Class Declarations
+
+ClassDeclaration ::= ClassHeader ClassBody
+/.$putCase consumeClassDeclaration(); $break ./
+
+ClassHeader ::= ClassHeaderName ClassHeaderExtendsopt ClassHeaderImplementsopt
+/.$putCase consumeClassHeader(); $break ./
+
+ClassHeaderName ::= Modifiersopt 'class' 'Identifier'
+/.$putCase consumeClassHeaderName(); $break ./
+
+ClassHeaderExtends ::= 'extends' ClassType
+/.$putCase consumeClassHeaderExtends(); $break ./
+
+ClassHeaderImplements ::= 'implements' InterfaceTypeList
+/.$putCase consumeClassHeaderImplements(); $break ./
+
+InterfaceTypeList -> InterfaceType
+InterfaceTypeList ::= InterfaceTypeList ',' InterfaceType
+/.$putCase consumeInterfaceTypeList(); $break ./
+
+InterfaceType ::= ClassOrInterfaceType
+/.$putCase consumeInterfaceType(); $break ./
+
+ClassBody ::= '{' ClassBodyDeclarationsopt '}'
+
+ClassBodyDeclarations ::= ClassBodyDeclaration
+ClassBodyDeclarations ::= ClassBodyDeclarations ClassBodyDeclaration
+/.$putCase consumeClassBodyDeclarations(); $break ./
+
+ClassBodyDeclaration -> ClassMemberDeclaration
+ClassBodyDeclaration -> StaticInitializer
+ClassBodyDeclaration -> ConstructorDeclaration
+--1.1 feature
+ClassBodyDeclaration ::= Diet NestedMethod Block
+/.$putCase consumeClassBodyDeclaration(); $break ./
+Diet ::= $empty
+/.$putCase consumeDiet(); $break./
+
+Initializer ::= Diet NestedMethod Block
+/.$putCase consumeClassBodyDeclaration(); $break ./
+
+ClassMemberDeclaration -> FieldDeclaration
+ClassMemberDeclaration -> MethodDeclaration
+--1.1 feature
+ClassMemberDeclaration -> ClassDeclaration
+--1.1 feature
+ClassMemberDeclaration -> InterfaceDeclaration
+
+-- Empty declarations are not valid Java ClassMemberDeclarations.
+-- However, since the current (2/14/97) Java compiler accepts them
+-- (in fact, some of the official tests contain this erroneous
+-- syntax)
+
+GenericMethodDeclaration -> MethodDeclaration
+GenericMethodDeclaration -> ConstructorDeclaration
+
+ClassMemberDeclaration ::= ';'
+/.$putCase consumeEmptyClassMemberDeclaration(); $break./
+
+--18.8.2 Productions from 8.3: Field Declarations
+--VariableModifier ::=
+-- 'public'
+-- | 'protected'
+-- | 'private'
+-- | 'static'
+-- | 'final'
+-- | 'transient'
+-- | 'volatile'
+
+FieldDeclaration ::= Modifiersopt Type VariableDeclarators ';'
+/.$putCase consumeFieldDeclaration(); $break ./
+
+VariableDeclarators -> VariableDeclarator
+VariableDeclarators ::= VariableDeclarators ',' VariableDeclarator
+/.$putCase consumeVariableDeclarators(); $break ./
+
+VariableDeclarator ::= VariableDeclaratorId EnterVariable ExitVariableWithoutInitialization
+
+VariableDeclarator ::= VariableDeclaratorId EnterVariable '=' ForceNoDiet VariableInitializer RestoreDiet ExitVariableWithInitialization
+
+EnterVariable ::= $empty
+/.$putCase consumeEnterVariable(); $break ./
+
+ExitVariableWithInitialization ::= $empty
+/.$putCase consumeExitVariableWithInitialization(); $break ./
+
+ExitVariableWithoutInitialization ::= $empty
+/.$putCase consumeExitVariableWithoutInitialization(); $break ./
+
+ForceNoDiet ::= $empty
+/.$putCase consumeForceNoDiet(); $break ./
+RestoreDiet ::= $empty
+/.$putCase consumeRestoreDiet(); $break ./
+
+VariableDeclaratorId ::= 'Identifier' Dimsopt
+
+VariableInitializer -> Expression
+VariableInitializer -> ArrayInitializer
+
+--18.8.3 Productions from 8.4: Method Declarations
+--MethodModifier ::=
+-- 'public'
+-- | 'protected'
+-- | 'private'
+-- | 'static'
+-- | 'abstract'
+-- | 'final'
+-- | 'native'
+-- | 'synchronized'
+--
+
+MethodDeclaration -> AbstractMethodDeclaration
+MethodDeclaration ::= MethodHeader MethodBody
+/.$putCase // set to true to consume a method with a body
+ consumeMethodDeclaration(true); $break ./
+
+AbstractMethodDeclaration ::= MethodHeader ';'
+/.$putCase // set to false to consume a method without body
+ consumeMethodDeclaration(false); $break ./
+
+MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims MethodHeaderThrowsClauseopt
+/.$putCase consumeMethodHeader(); $break ./
+
+MethodPushModifiersHeader ::= MethodPushModifiersHeaderName MethodHeaderParameters MethodHeaderExtendedDims MethodHeaderThrowsClauseopt
+/.$putCase consumeMethodHeader(); $break ./
+
+MethodPushModifiersHeaderName ::= Modifiers Type PushModifiers 'Identifier' '('
+/.$putCase consumeMethodPushModifiersHeaderName(); $break ./
+
+MethodPushModifiersHeaderName ::= Type PushModifiers 'Identifier' '('
+/.$putCase consumeMethodPushModifiersHeaderName(); $break ./
+
+MethodHeaderName ::= Modifiersopt Type 'Identifier' '('
+/.$putCase consumeMethodHeaderName(); $break ./
+
+MethodHeaderParameters ::= FormalParameterListopt ')'
+/.$putCase consumeMethodHeaderParameters(); $break ./
+
+MethodHeaderExtendedDims ::= Dimsopt
+/.$putCase consumeMethodHeaderExtendedDims(); $break ./
+
+MethodHeaderThrowsClause ::= 'throws' ClassTypeList
+/.$putCase consumeMethodHeaderThrowsClause(); $break ./
+
+ConstructorHeader ::= ConstructorHeaderName MethodHeaderParameters MethodHeaderThrowsClauseopt
+/.$putCase consumeConstructorHeader(); $break ./
+
+ConstructorHeaderName ::= Modifiersopt 'Identifier' '('
+/.$putCase consumeConstructorHeaderName(); $break ./
+
+FormalParameterList -> FormalParameter
+FormalParameterList ::= FormalParameterList ',' FormalParameter
+/.$putCase consumeFormalParameterList(); $break ./
+
+--1.1 feature
+FormalParameter ::= Modifiersopt Type VariableDeclaratorId
+/.$putCase // the boolean is used to know if the modifiers should be reset
+ consumeFormalParameter(); $break ./
+
+ClassTypeList -> ClassTypeElt
+ClassTypeList ::= ClassTypeList ',' ClassTypeElt
+/.$putCase consumeClassTypeList(); $break ./
+
+ClassTypeElt ::= ClassType
+/.$putCase consumeClassTypeElt(); $break ./
+
+
+MethodBody ::= NestedMethod '{' BlockStatementsopt '}'
+/.$putCase consumeMethodBody(); $break ./
+
+NestedMethod ::= $empty
+/.$putCase consumeNestedMethod(); $break ./
+
+--18.8.4 Productions from 8.5: Static Initializers
+
+StaticInitializer ::= StaticOnly Block
+/.$putCase consumeStaticInitializer(); $break./
+
+StaticOnly ::= 'static'
+/.$putCase consumeStaticOnly(); $break ./
+
+--18.8.5 Productions from 8.6: Constructor Declarations
+--ConstructorModifier ::=
+-- 'public'
+-- | 'protected'
+-- | 'private'
+--
+--
+ConstructorDeclaration ::= ConstructorHeader ConstructorBody
+/.$putCase consumeConstructorDeclaration() ; $break ./
+
+-- These rules are added to be able to parse constructors with no body
+ConstructorDeclaration ::= ConstructorHeader ';'
+/.$putCase consumeInvalidConstructorDeclaration() ; $break ./
+
+-- the rules ExplicitConstructorInvocationopt has been expanded
+-- in the rule below in order to make the grammar lalr(1).
+-- ConstructorBody ::= '{' ExplicitConstructorInvocationopt BlockStatementsopt '}'
+-- Other inlining has occured into the next rule too....
+
+ConstructorBody ::= NestedMethod '{' ConstructorBlockStatementsopt '}'
+/.$putCase consumeConstructorBody(); $break ./
+
+ConstructorBlockStatementsopt -> BlockStatementsopt
+
+ConstructorBlockStatementsopt -> ExplicitConstructorInvocation
+
+ConstructorBlockStatementsopt ::= ExplicitConstructorInvocation BlockStatements
+/.$putCase consumeConstructorBlockStatements(); $break ./
+
+ExplicitConstructorInvocation ::= 'this' '(' ArgumentListopt ')' ';'
+/.$putCase consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.This); $break ./
+
+ExplicitConstructorInvocation ::= 'super' '(' ArgumentListopt ')' ';'
+/.$putCase consumeExplicitConstructorInvocation(0,ExplicitConstructorCall.Super); $break ./
+
+--1.1 feature
+ExplicitConstructorInvocation ::= Primary '.' 'super' '(' ArgumentListopt ')' ';'
+/.$putCase consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.Super); $break ./
+
+--1.1 feature
+ExplicitConstructorInvocation ::= Name '.' 'super' '(' ArgumentListopt ')' ';'
+/.$putCase consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.Super); $break ./
+
+--1.1 feature
+ExplicitConstructorInvocation ::= Primary '.' 'this' '(' ArgumentListopt ')' ';'
+/.$putCase consumeExplicitConstructorInvocation(1, ExplicitConstructorCall.This); $break ./
+
+--1.1 feature
+ExplicitConstructorInvocation ::= Name '.' 'this' '(' ArgumentListopt ')' ';'
+/.$putCase consumeExplicitConstructorInvocation(2, ExplicitConstructorCall.This); $break ./
+
+--18.9 Productions from 9: Interface Declarations
+
+--18.9.1 Productions from 9.1: Interface Declarations
+--InterfaceModifier ::=
+-- 'public'
+-- | 'abstract'
+--
+InterfaceDeclaration ::= InterfaceHeader InterfaceBody
+/.$putCase consumeInterfaceDeclaration(); $break ./
+
+InterfaceHeader ::= InterfaceHeaderName InterfaceHeaderExtendsopt
+/.$putCase consumeInterfaceHeader(); $break ./
+
+InterfaceHeaderName ::= Modifiersopt 'interface' 'Identifier'
+/.$putCase consumeInterfaceHeaderName(); $break ./
+
+-- This rule will be used to accept inner local interface and then report a relevant error message
+InvalidInterfaceDeclaration -> InterfaceHeader InterfaceBody
+
+InterfaceHeaderExtends ::= 'extends' InterfaceTypeList
+/.$putCase consumeInterfaceHeaderExtends(); $break ./
+
+InterfaceBody ::= '{' InterfaceMemberDeclarationsopt '}'
+
+InterfaceMemberDeclarations -> InterfaceMemberDeclaration
+InterfaceMemberDeclarations ::= InterfaceMemberDeclarations InterfaceMemberDeclaration
+/.$putCase consumeInterfaceMemberDeclarations(); $break ./
+
+--same as for class members
+InterfaceMemberDeclaration ::= ';'
+/.$putCase consumeEmptyInterfaceMemberDeclaration(); $break ./
+
+-- This rule is added to be able to parse non abstract method inside interface and then report a relevent error message
+InvalidMethodDeclaration -> MethodHeader MethodBody
+
+InterfaceMemberDeclaration -> ConstantDeclaration
+InterfaceMemberDeclaration ::= InvalidMethodDeclaration
+/.$putCase ignoreMethodBody(); $break ./
+
+-- These rules are added to be able to parse constructors inside interface and then report a relevent error message
+InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody
+/.$putCase ignoreInvalidConstructorDeclaration(true); $break ./
+
+InvalidConstructorDeclaration ::= ConstructorHeader ';'
+/.$putCase ignoreInvalidConstructorDeclaration(false); $break ./
+
+InterfaceMemberDeclaration -> AbstractMethodDeclaration
+InterfaceMemberDeclaration -> InvalidConstructorDeclaration
+
+--1.1 feature
+InterfaceMemberDeclaration -> ClassDeclaration
+--1.1 feature
+InterfaceMemberDeclaration -> InterfaceDeclaration
+
+ConstantDeclaration -> FieldDeclaration
+
+ArrayInitializer ::= '{' ,opt '}'
+/.$putCase consumeEmptyArrayInitializer(); $break ./
+ArrayInitializer ::= '{' VariableInitializers '}'
+/.$putCase consumeArrayInitializer(); $break ./
+ArrayInitializer ::= '{' VariableInitializers , '}'
+/.$putCase consumeArrayInitializer(); $break ./
+
+VariableInitializers ::= VariableInitializer
+VariableInitializers ::= VariableInitializers ',' VariableInitializer
+/.$putCase consumeVariableInitializers(); $break ./
+
+Block ::= OpenBlock '{' BlockStatementsopt '}'
+/.$putCase consumeBlock(); $break ./
+OpenBlock ::= $empty
+/.$putCase consumeOpenBlock() ; $break ./
+
+BlockStatements -> BlockStatement
+BlockStatements ::= BlockStatements BlockStatement
+/.$putCase consumeBlockStatements() ; $break ./
+
+BlockStatement -> LocalVariableDeclarationStatement
+BlockStatement -> Statement
+--1.1 feature
+BlockStatement -> ClassDeclaration
+BlockStatement ::= InvalidInterfaceDeclaration
+/.$putCase ignoreInterfaceDeclaration(); $break ./
+
+LocalVariableDeclarationStatement ::= LocalVariableDeclaration ';'
+/.$putCase consumeLocalVariableDeclarationStatement(); $break ./
+
+LocalVariableDeclaration ::= Type PushModifiers VariableDeclarators
+/.$putCase consumeLocalVariableDeclaration(); $break ./
+
+-- 1.1 feature
+-- The modifiers part of this rule makes the grammar more permissive.
+-- The only modifier here is final. We put Modifiers to allow multiple modifiers
+-- This will require to check the validity of the modifier
+
+LocalVariableDeclaration ::= Modifiers Type PushModifiers VariableDeclarators
+/.$putCase consumeLocalVariableDeclaration(); $break ./
+
+PushModifiers ::= $empty
+/.$putCase consumePushModifiers(); $break ./
+
+Statement -> StatementWithoutTrailingSubstatement
+Statement -> LabeledStatement
+Statement -> IfThenStatement
+Statement -> IfThenElseStatement
+Statement -> WhileStatement
+Statement -> ForStatement
+
+StatementNoShortIf -> StatementWithoutTrailingSubstatement
+StatementNoShortIf -> LabeledStatementNoShortIf
+StatementNoShortIf -> IfThenElseStatementNoShortIf
+StatementNoShortIf -> WhileStatementNoShortIf
+StatementNoShortIf -> ForStatementNoShortIf
+
+StatementWithoutTrailingSubstatement -> AssertStatement
+StatementWithoutTrailingSubstatement -> Block
+StatementWithoutTrailingSubstatement -> EmptyStatement
+StatementWithoutTrailingSubstatement -> ExpressionStatement
+StatementWithoutTrailingSubstatement -> SwitchStatement
+StatementWithoutTrailingSubstatement -> DoStatement
+StatementWithoutTrailingSubstatement -> BreakStatement
+StatementWithoutTrailingSubstatement -> ContinueStatement
+StatementWithoutTrailingSubstatement -> ReturnStatement
+StatementWithoutTrailingSubstatement -> SynchronizedStatement
+StatementWithoutTrailingSubstatement -> ThrowStatement
+StatementWithoutTrailingSubstatement -> TryStatement
+
+EmptyStatement ::= ';'
+/.$putCase consumeEmptyStatement(); $break ./
+
+LabeledStatement ::= 'Identifier' ':' Statement
+/.$putCase consumeStatementLabel() ; $break ./
+
+LabeledStatementNoShortIf ::= 'Identifier' ':' StatementNoShortIf
+/.$putCase consumeStatementLabel() ; $break ./
+
+ExpressionStatement ::= StatementExpression ';'
+/. $putCase consumeExpressionStatement(); $break ./
+
+StatementExpression ::= Assignment
+StatementExpression ::= PreIncrementExpression
+StatementExpression ::= PreDecrementExpression
+StatementExpression ::= PostIncrementExpression
+StatementExpression ::= PostDecrementExpression
+StatementExpression ::= MethodInvocation
+StatementExpression ::= ClassInstanceCreationExpression
+
+IfThenStatement ::= 'if' '(' Expression ')' Statement
+/.$putCase consumeStatementIfNoElse(); $break ./
+
+IfThenElseStatement ::= 'if' '(' Expression ')' StatementNoShortIf 'else' Statement
+/.$putCase consumeStatementIfWithElse(); $break ./
+
+IfThenElseStatementNoShortIf ::= 'if' '(' Expression ')' StatementNoShortIf 'else' StatementNoShortIf
+/.$putCase consumeStatementIfWithElse(); $break ./
+
+SwitchStatement ::= 'switch' OpenBlock '(' Expression ')' SwitchBlock
+/.$putCase consumeStatementSwitch() ; $break ./
+
+SwitchBlock ::= '{' '}'
+/.$putCase consumeEmptySwitchBlock() ; $break ./
+
+SwitchBlock ::= '{' SwitchBlockStatements '}'
+SwitchBlock ::= '{' SwitchLabels '}'
+SwitchBlock ::= '{' SwitchBlockStatements SwitchLabels '}'
+/.$putCase consumeSwitchBlock() ; $break ./
+
+SwitchBlockStatements -> SwitchBlockStatement
+SwitchBlockStatements ::= SwitchBlockStatements SwitchBlockStatement
+/.$putCase consumeSwitchBlockStatements() ; $break ./
+
+SwitchBlockStatement ::= SwitchLabels BlockStatements
+/.$putCase consumeSwitchBlockStatement() ; $break ./
+
+SwitchLabels -> SwitchLabel
+SwitchLabels ::= SwitchLabels SwitchLabel
+/.$putCase consumeSwitchLabels() ; $break ./
+
+SwitchLabel ::= 'case' ConstantExpression ':'
+/. $putCase consumeCaseLabel(); $break ./
+
+SwitchLabel ::= 'default' ':'
+/. $putCase consumeDefaultLabel(); $break ./
+
+WhileStatement ::= 'while' '(' Expression ')' Statement
+/.$putCase consumeStatementWhile() ; $break ./
+
+WhileStatementNoShortIf ::= 'while' '(' Expression ')' StatementNoShortIf
+/.$putCase consumeStatementWhile() ; $break ./
+
+DoStatement ::= 'do' Statement 'while' '(' Expression ')' ';'
+/.$putCase consumeStatementDo() ; $break ./
+
+ForStatement ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' Statement
+/.$putCase consumeStatementFor() ; $break ./
+ForStatementNoShortIf ::= 'for' '(' ForInitopt ';' Expressionopt ';' ForUpdateopt ')' StatementNoShortIf
+/.$putCase consumeStatementFor() ; $break ./
+
+--the minus one allows to avoid a stack-to-stack transfer
+ForInit ::= StatementExpressionList
+/.$putCase consumeForInit() ; $break ./
+ForInit -> LocalVariableDeclaration
+
+ForUpdate -> StatementExpressionList
+
+StatementExpressionList -> StatementExpression
+StatementExpressionList ::= StatementExpressionList ',' StatementExpression
+/.$putCase consumeStatementExpressionList() ; $break ./
+
+-- 1.4 feature
+AssertStatement ::= 'assert' Expression ';'
+/.$putCase consumeSimpleAssertStatement() ; $break ./
+
+AssertStatement ::= 'assert' Expression ':' Expression ';'
+/.$putCase consumeAssertStatement() ; $break ./
+
+BreakStatement ::= 'break' ';'
+/.$putCase consumeStatementBreak() ; $break ./
+
+BreakStatement ::= 'break' Identifier ';'
+/.$putCase consumeStatementBreakWithLabel() ; $break ./
+
+ContinueStatement ::= 'continue' ';'
+/.$putCase consumeStatementContinue() ; $break ./
+
+ContinueStatement ::= 'continue' Identifier ';'
+/.$putCase consumeStatementContinueWithLabel() ; $break ./
+
+ReturnStatement ::= 'return' Expressionopt ';'
+/.$putCase consumeStatementReturn() ; $break ./
+
+ThrowStatement ::= 'throw' Expression ';'
+/.$putCase consumeStatementThrow();
+$break ./
+
+SynchronizedStatement ::= OnlySynchronized '(' Expression ')' Block
+/.$putCase consumeStatementSynchronized(); $break ./
+OnlySynchronized ::= 'synchronized'
+/.$putCase consumeOnlySynchronized(); $break ./
+
+
+TryStatement ::= 'try' Block Catches
+/.$putCase consumeStatementTry(false); $break ./
+TryStatement ::= 'try' Block Catchesopt Finally
+/.$putCase consumeStatementTry(true); $break ./
+
+Catches -> CatchClause
+Catches ::= Catches CatchClause
+/.$putCase consumeCatches(); $break ./
+
+CatchClause ::= 'catch' '(' FormalParameter ')' Block
+/.$putCase consumeStatementCatch() ; $break ./
+
+Finally ::= 'finally' Block
+
+--18.12 Productions from 14: Expressions
+
+--for source positionning purpose
+PushLPAREN ::= '('
+/.$putCase consumeLeftParen(); $break ./
+PushRPAREN ::= ')'
+/.$putCase consumeRightParen(); $break ./
+
+Primary -> PrimaryNoNewArray
+Primary -> ArrayCreationExpression
+
+PrimaryNoNewArray -> Literal
+PrimaryNoNewArray ::= 'this'
+/.$putCase consumePrimaryNoNewArrayThis(); $break ./
+
+PrimaryNoNewArray ::= PushLPAREN Expression PushRPAREN
+/.$putCase consumePrimaryNoNewArray(); $break ./
+
+PrimaryNoNewArray -> ClassInstanceCreationExpression
+PrimaryNoNewArray -> FieldAccess
+--1.1 feature
+PrimaryNoNewArray ::= Name '.' 'this'
+/.$putCase consumePrimaryNoNewArrayNameThis(); $break ./
+PrimaryNoNewArray ::= Name '.' 'super'
+/.$putCase consumePrimaryNoNewArrayNameSuper(); $break ./
+
+--1.1 feature
+--PrimaryNoNewArray ::= Type '.' 'class'
+--inline Type in the previous rule in order to make the grammar LL1 instead
+-- of LL2. The result is the 3 next rules.
+PrimaryNoNewArray ::= Name '.' 'class'
+/.$putCase consumePrimaryNoNewArrayName(); $break ./
+
+PrimaryNoNewArray ::= ArrayType '.' 'class'
+/.$putCase consumePrimaryNoNewArrayArrayType(); $break ./
+
+PrimaryNoNewArray ::= PrimitiveType '.' 'class'
+/.$putCase consumePrimaryNoNewArrayPrimitiveType(); $break ./
+
+PrimaryNoNewArray -> MethodInvocation
+PrimaryNoNewArray -> ArrayAccess
+
+--1.1 feature
+--
+-- In Java 1.0 a ClassBody could not appear at all in a
+-- ClassInstanceCreationExpression.
+--
+
+AllocationHeader ::= 'new' ClassType '(' ArgumentListopt ')'
+/.$putCase consumeAllocationHeader(); $break ./
+
+ClassInstanceCreationExpression ::= 'new' ClassType '(' ArgumentListopt ')' ClassBodyopt
+/.$putCase consumeClassInstanceCreationExpression(); $break ./
+--1.1 feature
+
+ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
+/.$putCase consumeClassInstanceCreationExpressionQualified() ; $break ./
+
+--1.1 feature
+ClassInstanceCreationExpression ::= ClassInstanceCreationExpressionName 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
+/.$putCase consumeClassInstanceCreationExpressionQualified() ; $break ./
+
+ClassInstanceCreationExpressionName ::= Name '.'
+/.$putCase consumeClassInstanceCreationExpressionName() ; $break ./
+
+ClassBodyopt ::= $empty --test made using null as contents
+/.$putCase consumeClassBodyopt(); $break ./
+ClassBodyopt ::= EnterAnonymousClassBody ClassBody
+
+EnterAnonymousClassBody ::= $empty
+/.$putCase consumeEnterAnonymousClassBody(); $break ./
+
+ArgumentList ::= Expression
+ArgumentList ::= ArgumentList ',' Expression
+/.$putCase consumeArgumentList(); $break ./
+
+--Thess rules are re-written in order to be ll1
+--ArrayCreationExpression ::= 'new' ArrayType ArrayInitializer
+--ArrayCreationExpression ::= 'new' PrimitiveType DimExprs Dimsopt
+--ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimExprs Dimsopt
+--DimExprs ::= DimExpr
+--DimExprs ::= DimExprs DimExpr
+
+ArrayCreationExpression ::= 'new' PrimitiveType DimWithOrWithOutExprs ArrayInitializeropt
+/.$putCase consumeArrayCreationExpression(); $break ./
+ArrayCreationExpression ::= 'new' ClassOrInterfaceType DimWithOrWithOutExprs ArrayInitializeropt
+/.$putCase consumeArrayCreationExpression(); $break ./
+
+DimWithOrWithOutExprs ::= DimWithOrWithOutExpr
+DimWithOrWithOutExprs ::= DimWithOrWithOutExprs DimWithOrWithOutExpr
+/.$putCase consumeDimWithOrWithOutExprs(); $break ./
+
+DimWithOrWithOutExpr ::= '[' Expression ']'
+DimWithOrWithOutExpr ::= '[' ']'
+/. $putCase consumeDimWithOrWithOutExpr(); $break ./
+-- -----------------------------------------------
+
+Dims ::= DimsLoop
+/. $putCase consumeDims(); $break ./
+DimsLoop -> OneDimLoop
+DimsLoop ::= DimsLoop OneDimLoop
+OneDimLoop ::= '[' ']'
+/. $putCase consumeOneDimLoop(); $break ./
+
+FieldAccess ::= Primary '.' 'Identifier'
+/.$putCase consumeFieldAccess(false); $break ./
+
+FieldAccess ::= 'super' '.' 'Identifier'
+/.$putCase consumeFieldAccess(true); $break ./
+
+MethodInvocation ::= Name '(' ArgumentListopt ')'
+/.$putCase consumeMethodInvocationName(); $break ./
+
+MethodInvocation ::= Primary '.' 'Identifier' '(' ArgumentListopt ')'
+/.$putCase consumeMethodInvocationPrimary(); $break ./
+
+MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'
+/.$putCase consumeMethodInvocationSuper(); $break ./
+
+ArrayAccess ::= Name '[' Expression ']'
+/.$putCase consumeArrayAccess(true); $break ./
+ArrayAccess ::= PrimaryNoNewArray '[' Expression ']'
+/.$putCase consumeArrayAccess(false); $break ./
+
+PostfixExpression -> Primary
+PostfixExpression ::= Name
+/.$putCase consumePostfixExpression(); $break ./
+PostfixExpression -> PostIncrementExpression
+PostfixExpression -> PostDecrementExpression
+
+PostIncrementExpression ::= PostfixExpression '++'
+/.$putCase consumeUnaryExpression(OperatorExpression.PLUS,true); $break ./
+
+PostDecrementExpression ::= PostfixExpression '--'
+/.$putCase consumeUnaryExpression(OperatorExpression.MINUS,true); $break ./
+
+--for source managment purpose
+PushPosition ::= $empty
+ /.$putCase consumePushPosition(); $break ./
+
+UnaryExpression -> PreIncrementExpression
+UnaryExpression -> PreDecrementExpression
+UnaryExpression ::= '+' PushPosition UnaryExpression
+/.$putCase consumeUnaryExpression(OperatorExpression.PLUS); $break ./
+UnaryExpression ::= '-' PushPosition UnaryExpression
+/.$putCase consumeUnaryExpression(OperatorExpression.MINUS); $break ./
+UnaryExpression -> UnaryExpressionNotPlusMinus
+
+PreIncrementExpression ::= '++' PushPosition UnaryExpression
+/.$putCase consumeUnaryExpression(OperatorExpression.PLUS,false); $break ./
+
+PreDecrementExpression ::= '--' PushPosition UnaryExpression
+/.$putCase consumeUnaryExpression(OperatorExpression.MINUS,false); $break ./
+
+UnaryExpressionNotPlusMinus -> PostfixExpression
+UnaryExpressionNotPlusMinus ::= '~' PushPosition UnaryExpression
+/.$putCase consumeUnaryExpression(OperatorExpression.TWIDDLE); $break ./
+UnaryExpressionNotPlusMinus ::= '!' PushPosition UnaryExpression
+/.$putCase consumeUnaryExpression(OperatorExpression.NOT); $break ./
+UnaryExpressionNotPlusMinus -> CastExpression
+
+CastExpression ::= PushLPAREN PrimitiveType Dimsopt PushRPAREN UnaryExpression
+/.$putCase consumeCastExpression(); $break ./
+ CastExpression ::= PushLPAREN Name Dims PushRPAREN UnaryExpressionNotPlusMinus
+/.$putCase consumeCastExpression(); $break ./
+-- Expression is here only in order to make the grammar LL1
+CastExpression ::= PushLPAREN Expression PushRPAREN UnaryExpressionNotPlusMinus
+/.$putCase consumeCastExpressionLL1(); $break ./
+
+MultiplicativeExpression -> UnaryExpression
+MultiplicativeExpression ::= MultiplicativeExpression '*' UnaryExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.MULTIPLY); $break ./
+MultiplicativeExpression ::= MultiplicativeExpression '/' UnaryExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.DIVIDE); $break ./
+MultiplicativeExpression ::= MultiplicativeExpression '%' UnaryExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.REMAINDER); $break ./
+
+AdditiveExpression -> MultiplicativeExpression
+AdditiveExpression ::= AdditiveExpression '+' MultiplicativeExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.PLUS); $break ./
+AdditiveExpression ::= AdditiveExpression '-' MultiplicativeExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.MINUS); $break ./
+
+ShiftExpression -> AdditiveExpression
+ShiftExpression ::= ShiftExpression '<<' AdditiveExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.LEFT_SHIFT); $break ./
+ShiftExpression ::= ShiftExpression '>>' AdditiveExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.RIGHT_SHIFT); $break ./
+ShiftExpression ::= ShiftExpression '>>>' AdditiveExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.UNSIGNED_RIGHT_SHIFT); $break ./
+
+RelationalExpression -> ShiftExpression
+RelationalExpression ::= RelationalExpression '<' ShiftExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.LESS); $break ./
+RelationalExpression ::= RelationalExpression '>' ShiftExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.GREATER); $break ./
+RelationalExpression ::= RelationalExpression '<=' ShiftExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.LESS_EQUAL); $break ./
+RelationalExpression ::= RelationalExpression '>=' ShiftExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.GREATER_EQUAL); $break ./
+RelationalExpression ::= RelationalExpression 'instanceof' ReferenceType
+/.$putCase consumeInstanceOfExpression(OperatorExpression.INSTANCEOF); $break ./
+
+EqualityExpression -> RelationalExpression
+EqualityExpression ::= EqualityExpression '==' RelationalExpression
+/.$putCase consumeEqualityExpression(OperatorExpression.EQUAL_EQUAL); $break ./
+EqualityExpression ::= EqualityExpression '!=' RelationalExpression
+/.$putCase consumeEqualityExpression(OperatorExpression.NOT_EQUAL); $break ./
+
+AndExpression -> EqualityExpression
+AndExpression ::= AndExpression '&' EqualityExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.AND); $break ./
+
+ExclusiveOrExpression -> AndExpression
+ExclusiveOrExpression ::= ExclusiveOrExpression '^' AndExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.XOR); $break ./
+
+InclusiveOrExpression -> ExclusiveOrExpression
+InclusiveOrExpression ::= InclusiveOrExpression '|' ExclusiveOrExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.OR); $break ./
+
+ConditionalAndExpression -> InclusiveOrExpression
+ConditionalAndExpression ::= ConditionalAndExpression '&&' InclusiveOrExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.AND_AND); $break ./
+
+ConditionalOrExpression -> ConditionalAndExpression
+ConditionalOrExpression ::= ConditionalOrExpression '||' ConditionalAndExpression
+/.$putCase consumeBinaryExpression(OperatorExpression.OR_OR); $break ./
+
+ConditionalExpression -> ConditionalOrExpression
+ConditionalExpression ::= ConditionalOrExpression '?' Expression ':' ConditionalExpression
+/.$putCase consumeConditionalExpression(OperatorExpression.QUESTIONCOLON) ; $break ./
+
+AssignmentExpression -> ConditionalExpression
+AssignmentExpression -> Assignment
+
+Assignment ::= LeftHandSide AssignmentOperator AssignmentExpression
+/.$putCase consumeAssignment(); $break ./
+
+-- this rule is added to parse an array initializer in a assigment and then report a syntax error knowing the exact senario
+InvalidArrayInitializerAssignement ::= LeftHandSide AssignmentOperator ArrayInitializer
+Assignment ::= InvalidArrayInitializerAssignement
+/.$putcase ignoreExpressionAssignment();$break ./
+
+LeftHandSide ::= Name
+/.$putCase consumeLeftHandSide(); $break ./
+LeftHandSide -> FieldAccess
+LeftHandSide -> ArrayAccess
+
+AssignmentOperator ::= '='
+/.$putCase consumeAssignmentOperator(EQUAL); $break ./
+AssignmentOperator ::= '*='
+/.$putCase consumeAssignmentOperator(MULTIPLY); $break ./
+AssignmentOperator ::= '/='
+/.$putCase consumeAssignmentOperator(DIVIDE); $break ./
+AssignmentOperator ::= '%='
+/.$putCase consumeAssignmentOperator(REMAINDER); $break ./
+AssignmentOperator ::= '+='
+/.$putCase consumeAssignmentOperator(PLUS); $break ./
+AssignmentOperator ::= '-='
+/.$putCase consumeAssignmentOperator(MINUS); $break ./
+AssignmentOperator ::= '<<='
+/.$putCase consumeAssignmentOperator(LEFT_SHIFT); $break ./
+AssignmentOperator ::= '>>='
+/.$putCase consumeAssignmentOperator(RIGHT_SHIFT); $break ./
+AssignmentOperator ::= '>>>='
+/.$putCase consumeAssignmentOperator(UNSIGNED_RIGHT_SHIFT); $break ./
+AssignmentOperator ::= '&='
+/.$putCase consumeAssignmentOperator(AND); $break ./
+AssignmentOperator ::= '^='
+/.$putCase consumeAssignmentOperator(XOR); $break ./
+AssignmentOperator ::= '|='
+/.$putCase consumeAssignmentOperator(OR); $break ./
+
+Expression -> AssignmentExpression
+
+ConstantExpression -> Expression
+
+-- The following rules are for optional nonterminals.
+--
+
+PackageDeclarationopt -> $empty
+PackageDeclarationopt -> PackageDeclaration
+
+ClassHeaderExtendsopt ::= $empty
+ClassHeaderExtendsopt -> ClassHeaderExtends
+
+Expressionopt ::= $empty
+/.$putCase consumeEmptyExpression(); $break ./
+Expressionopt -> Expression
+
+
+---------------------------------------------------------------------------------------
+--
+-- The rules below are for optional terminal symbols. An optional comma,
+-- is only used in the context of an array initializer - It is a
+-- "syntactic sugar" that otherwise serves no other purpose. By contrast,
+-- an optional identifier is used in the definition of a break and
+-- continue statement. When the identifier does not appear, a NULL
+-- is produced. When the identifier is present, the user should use the
+-- corresponding TOKEN(i) method. See break statement as an example.
+--
+---------------------------------------------------------------------------------------
+
+,opt -> $empty
+,opt -> ,
+
+ImportDeclarationsopt ::= $empty
+/.$putCase consumeEmptyImportDeclarationsopt(); $break ./
+ImportDeclarationsopt ::= ImportDeclarations
+/.$putCase consumeImportDeclarationsopt(); $break ./
+
+
+TypeDeclarationsopt ::= $empty
+/.$putCase consumeEmptyTypeDeclarationsopt(); $break ./
+TypeDeclarationsopt ::= TypeDeclarations
+/.$putCase consumeTypeDeclarationsopt(); $break ./
+
+ClassBodyDeclarationsopt ::= $empty
+/.$putCase consumeEmptyClassBodyDeclarationsopt(); $break ./
+ClassBodyDeclarationsopt ::= NestedType ClassBodyDeclarations
+/.$putCase consumeClassBodyDeclarationsopt(); $break ./
+
+Modifiersopt ::= $empty
+/. $putCase consumeDefaultModifiers(); $break ./
+Modifiersopt ::= Modifiers
+/.$putCase consumeModifiers(); $break ./
+
+BlockStatementsopt ::= $empty
+/.$putCase consumeEmptyBlockStatementsopt(); $break ./
+BlockStatementsopt -> BlockStatements
+
+Dimsopt ::= $empty
+/. $putCase consumeEmptyDimsopt(); $break ./
+Dimsopt -> Dims
+
+ArgumentListopt ::= $empty
+/. $putCase consumeEmptyArgumentListopt(); $break ./
+ArgumentListopt -> ArgumentList
+
+MethodHeaderThrowsClauseopt ::= $empty
+MethodHeaderThrowsClauseopt -> MethodHeaderThrowsClause
+
+FormalParameterListopt ::= $empty
+/.$putcase consumeFormalParameterListopt(); $break ./
+FormalParameterListopt -> FormalParameterList
+
+ClassHeaderImplementsopt ::= $empty
+ClassHeaderImplementsopt -> ClassHeaderImplements
+
+InterfaceMemberDeclarationsopt ::= $empty
+/. $putCase consumeEmptyInterfaceMemberDeclarationsopt(); $break ./
+InterfaceMemberDeclarationsopt ::= NestedType InterfaceMemberDeclarations
+/. $putCase consumeInterfaceMemberDeclarationsopt(); $break ./
+
+NestedType ::= $empty
+/.$putCase consumeNestedType(); $break./
+
+ForInitopt ::= $empty
+/. $putCase consumeEmptyForInitopt(); $break ./
+ForInitopt -> ForInit
+
+ForUpdateopt ::= $empty
+/. $putCase consumeEmptyForUpdateopt(); $break ./
+ ForUpdateopt -> ForUpdate
+
+InterfaceHeaderExtendsopt ::= $empty
+InterfaceHeaderExtendsopt -> InterfaceHeaderExtends
+
+Catchesopt ::= $empty
+/. $putCase consumeEmptyCatchesopt(); $break ./
+Catchesopt -> Catches
+
+ArrayInitializeropt ::= $empty
+/. $putCase consumeEmptyArrayInitializeropt(); $break ./
+ArrayInitializeropt -> ArrayInitializer
+
+/. }
+} ./
+
+---------------------------------------------------------------------------------------
+
+$names
+
+-- BodyMarker ::= '"class Identifier { ... MethodHeader "'
+
+-- void ::= 'void'
+
+PLUS_PLUS ::= '++'
+MINUS_MINUS ::= '--'
+EQUAL_EQUAL ::= '=='
+LESS_EQUAL ::= '<='
+GREATER_EQUAL ::= '>='
+NOT_EQUAL ::= '!='
+LEFT_SHIFT ::= '<<'
+RIGHT_SHIFT ::= '>>'
+UNSIGNED_RIGHT_SHIFT ::= '>>>'
+PLUS_EQUAL ::= '+='
+MINUS_EQUAL ::= '-='
+MULTIPLY_EQUAL ::= '*='
+DIVIDE_EQUAL ::= '/='
+AND_EQUAL ::= '&='
+OR_EQUAL ::= '|='
+XOR_EQUAL ::= '^='
+REMAINDER_EQUAL ::= '%='
+LEFT_SHIFT_EQUAL ::= '<<='
+RIGHT_SHIFT_EQUAL ::= '>>='
+UNSIGNED_RIGHT_SHIFT_EQUAL ::= '>>>='
+OR_OR ::= '||'
+AND_AND ::= '&&'
+
+PLUS ::= '+'
+MINUS ::= '-'
+NOT ::= '!'
+REMAINDER ::= '%'
+XOR ::= '^'
+AND ::= '&'
+MULTIPLY ::= '*'
+OR ::= '|'
+TWIDDLE ::= '~'
+DIVIDE ::= '/'
+GREATER ::= '>'
+LESS ::= '<'
+LPAREN ::= '('
+RPAREN ::= ')'
+LBRACE ::= '{'
+RBRACE ::= '}'
+LBRACKET ::= '['
+RBRACKET ::= ']'
+SEMICOLON ::= ';'
+QUESTION ::= '?'
+COLON ::= ':'
+COMMA ::= ','
+DOT ::= '.'
+EQUAL ::= '='
+
+$end
+-- need a carriage return after the $end
+*/
+}
+protected void ignoreExpressionAssignment() {
+ // Assignment ::= InvalidArrayInitializerAssignement
+ // encoded operator would be: intStack[intPtr]
+ intPtr--;
+ ArrayInitializer arrayInitializer = (ArrayInitializer) expressionStack[expressionPtr--];
+ 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 = astLengthStack[astLengthPtr--]) != 0) {
+ //there are length declarations
+ //dispatch according to the type of the declarations
+ dispatchDeclarationInto(length);
+ }
+
+ flushAnnotationsDefinedPriorTo(endStatementPosition);
+
+ // report the problem and continue parsing
+ TypeDeclaration typeDecl = (TypeDeclaration) astStack[astPtr];
+ typeDecl.bodyEnd = endStatementPosition;
+ problemReporter().cannotDeclareLocalInterface(typeDecl.name, typeDecl.sourceStart, typeDecl.sourceEnd);
+
+ // mark fields and initializer with local type mark if needed
+ markFieldsWithLocalType(typeDecl);
+
+ // remove the ast node created in interface header
+ astPtr--;
+ // Don't create an astnode for this inner interface, but have to push
+ // a 0 on the astLengthStack to be consistent with the reduction made
+ // at the end of the method:
+ // public void parse(MethodDeclaration md, CompilationUnitDeclaration unit)
+ pushOnAstLengthStack(0);
+}
+protected void ignoreInvalidConstructorDeclaration(boolean hasBody) {
+ // InvalidConstructorDeclaration ::= ConstructorHeader ConstructorBody ==> true
+ // InvalidConstructorDeclaration ::= ConstructorHeader ';' ==> false
+
+ /*
+ astStack : modifiers arguments throws statements
+ identifierStack : name
+ ==>
+ astStack : MethodDeclaration
+ identifierStack :
+ */
+
+ //must provide a default constructor call when needed
+
+ if (hasBody) {
+ // pop the position of the { (body of the method) pushed in block decl
+ intPtr--;
+ }
+
+ //statements
+ if (hasBody) {
+ realBlockPtr--;
+ }
+
+ int length;
+ if (hasBody && ((length = astLengthStack[astLengthPtr--]) != 0)) {
+ astPtr -= length;
+ }
+}
+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
+ intPtr--;
+ // retrieve end position of method declarator
+
+ //statements
+ realBlockPtr--;
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ astPtr -= length;
+ }
+
+ //watch for } that could be given as a unicode ! ( u007D is '}' )
+ MethodDeclaration md = (MethodDeclaration) astStack[astPtr];
+ md.bodyEnd = endPosition;
+ md.declarationSourceEnd = flushAnnotationsDefinedPriorTo(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....
+ astPtr = -1;
+ astLengthPtr = -1;
+ expressionPtr = -1;
+ expressionLengthPtr = -1;
+ identifierPtr = -1;
+ identifierLengthPtr = -1;
+ intPtr = -1;
+ nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
+ variablesCounter[nestedType] = 0;
+ dimensions = 0 ;
+ realBlockPtr = -1;
+ compilationUnit = null;
+ referenceContext = null;
+ endStatementPosition = 0;
+
+ //remove objects from stack too, while the same parser/compiler couple is
+ //re-used between two compilations ....
+
+ int astLength = astStack.length;
+ if (noAstNodes.length < astLength){
+ noAstNodes = new AstNode[astLength];
+ //System.out.println("Resized AST stacks : "+ astLength);
+
+ }
+ System.arraycopy(noAstNodes, 0, astStack, 0, astLength);
+
+ int expressionLength = expressionStack.length;
+ if (noExpressions.length < expressionLength){
+ noExpressions = new Expression[expressionLength];
+ //System.out.println("Resized EXPR stacks : "+ expressionLength);
+ }
+ System.arraycopy(noExpressions, 0, expressionStack, 0, expressionLength);
+
+ // reset scanner state
+ scanner.commentPtr = -1;
+ scanner.eofPosition = Integer.MAX_VALUE;
+
+ resetModifiers();
+
+ // recovery
+ lastCheckPoint = -1;
+ currentElement = null;
+ restartRecovery = false;
+ hasReportedError = false;
+ recoveredStaticInitializerStart = 0;
+ lastIgnoredToken = -1;
+ lastErrorEndPosition = -1;
+ listLength = 0;
+}
+public void initializeScanner(){
+ this.scanner = new Scanner(false, false, this.problemReporter.options.getNonExternalizedStringLiteralSeverity() != ProblemSeverities.Ignore , this.assertMode);
+}
+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$
+ symbol_index = readTable(prefix + (++i) + ".rsc"); //$NON-NLS-1$
+ action = lhs;
+}
+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 (diet && (dietInt == 0))
+ scanner.diet = true;
+}
+protected void markCurrentMethodWithLocalType() {
+ 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 TypeDeclaration) { // mark type for now: all fields 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 markFieldsWithLocalType(TypeDeclaration type) {
+ if (type.fields == null || (type.bits & AstNode.HasLocalTypeMASK) == 0) return;
+ for (int i = 0, length = type.fields.length; i < length; i++) {
+ type.fields[i].bits |= AstNode.HasLocalTypeMASK;
+ }
+}
+/*
+ * Move checkpoint location (current implementation is moving it by one token)
+ *
+ * Answers true if successfully moved checkpoint (i.e. did not attempt to move it
+ * beyond end of file).
+ */
+protected boolean moveRecoveryCheckpoint() {
+
+ int pos = lastCheckPoint;
+ /* reset scanner, and move checkpoint by one token */
+ scanner.startPosition = pos;
+ scanner.currentPosition = pos;
+ scanner.diet = false; // quit jumping over method bodies
+
+ /* if about to restart, then no need to shift token */
+ if (restartRecovery){
+ lastIgnoredToken = -1;
+ return true;
+ }
+
+ /* protect against shifting on an invalid token */
+ lastIgnoredToken = nextIgnoredToken;
+ nextIgnoredToken = -1;
+ do {
+ try {
+ nextIgnoredToken = scanner.getNextToken();
+ if(scanner.currentPosition == scanner.startPosition){
+ scanner.currentPosition++; // on fake completion identifier
+ nextIgnoredToken = -1;
+ }
+
+ } catch(InvalidInputException e){
+ pos = scanner.currentPosition;
+ }
+ } while (nextIgnoredToken < 0);
+
+ if (nextIgnoredToken == TokenNameEOF) { // no more recovery after this point
+ if (currentToken == TokenNameEOF) { // already tried one iteration on EOF
+ return false;
+ }
+ }
+ lastCheckPoint = scanner.currentPosition;
+
+ /* reset scanner again to previous checkpoint location*/
+ scanner.startPosition = pos;
+ scanner.currentPosition = pos;
+ scanner.commentPtr = -1;
+
+ return true;
+
+/*
+ The following implementation moves the checkpoint location by one line:
+
+ int pos = lastCheckPoint;
+ // reset scanner, and move checkpoint by one token
+ scanner.startPosition = pos;
+ scanner.currentPosition = pos;
+ scanner.diet = false; // quit jumping over method bodies
+
+ // if about to restart, then no need to shift token
+ if (restartRecovery){
+ lastIgnoredToken = -1;
+ return true;
+ }
+
+ // protect against shifting on an invalid token
+ lastIgnoredToken = nextIgnoredToken;
+ nextIgnoredToken = -1;
+
+ boolean wasTokenizingWhiteSpace = scanner.tokenizeWhiteSpace;
+ scanner.tokenizeWhiteSpace = true;
+ checkpointMove:
+ do {
+ try {
+ nextIgnoredToken = scanner.getNextToken();
+ switch(nextIgnoredToken){
+ case Scanner.TokenNameWHITESPACE :
+ if(scanner.getLineNumber(scanner.startPosition)
+ == scanner.getLineNumber(scanner.currentPosition)){
+ nextIgnoredToken = -1;
+ }
+ break;
+ case TokenNameSEMICOLON :
+ case TokenNameLBRACE :
+ case TokenNameRBRACE :
+ break;
+ case TokenNameIdentifier :
+ if(scanner.currentPosition == scanner.startPosition){
+ scanner.currentPosition++; // on fake completion identifier
+ }
+ default:
+ nextIgnoredToken = -1;
+ break;
+ case TokenNameEOF :
+ break checkpointMove;
+ }
+ } catch(InvalidInputException e){
+ pos = scanner.currentPosition;
+ }
+ } while (nextIgnoredToken < 0);
+ scanner.tokenizeWhiteSpace = wasTokenizingWhiteSpace;
+
+ if (nextIgnoredToken == TokenNameEOF) { // no more recovery after this point
+ if (currentToken == TokenNameEOF) { // already tried one iteration on EOF
+ return false;
+ }
+ }
+ lastCheckPoint = scanner.currentPosition;
+
+ // reset scanner again to previous checkpoint location
+ scanner.startPosition = pos;
+ scanner.currentPosition = pos;
+ scanner.commentPtr = -1;
+
+ return true;
+*/
+}
+protected MessageSend newMessageSend() {
+ // '(' ArgumentListopt ')'
+ // the arguments are on the expression stack
+
+ MessageSend m = new MessageSend();
+ int length;
+ if ((length = expressionLengthStack[expressionLengthPtr--]) != 0) {
+ expressionPtr -= length;
+ System.arraycopy(
+ expressionStack,
+ expressionPtr + 1,
+ m.arguments = new Expression[length],
+ 0,
+ length);
+ };
+ return m;
+}
+protected static int ntAction(int state, int sym) {
+ return 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.
+ */
+
+ astLengthStack[--astLengthPtr]++;
+}
+protected static int original_state(int state) {
+ return -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() {
+
+ hasReportedError = false;
+ int act = START_STATE;
+ stateStackTop = -1;
+ currentToken = getFirstToken();
+ ProcessTerminals : for (;;) {
+ try {
+ stack[++stateStackTop] = act;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = stack.length;
+ int oldStack[] = stack;
+ stack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldStack, 0, stack, 0, oldStackLength);
+ stack[stateStackTop] = act;
+ };
+
+ act = tAction(act, currentToken);
+
+ if (act == ERROR_ACTION || restartRecovery) {
+ int errorPos = scanner.currentPosition;
+ if (!hasReportedError){
+ this.reportSyntaxError(ERROR_ACTION, currentToken, stateStackTop);
+ hasReportedError = true;
+ }
+ if (resumeOnSyntaxError()) {
+ if (act == ERROR_ACTION) lastErrorEndPosition = errorPos;
+ act = START_STATE;
+ stateStackTop = -1;
+ currentToken = getFirstToken();
+ continue ProcessTerminals;
+ } else {
+ act = ERROR_ACTION;
+ } break ProcessTerminals;
+ }
+ if (act <= NUM_RULES)
+ stateStackTop--;
+ else
+ if (act > ERROR_ACTION) { /* shift-reduce */
+ consumeToken(currentToken);
+ if (currentElement != null) this.recoveryTokenCheck();
+ try{
+ currentToken = scanner.getNextToken();
+ } catch(InvalidInputException e){
+ if (!hasReportedError){
+ this.problemReporter().scannerError(this, e.getMessage());
+ hasReportedError = true;
+ }
+ lastCheckPoint = scanner.currentPosition;
+ restartRecovery = true;
+ }
+ act -= ERROR_ACTION;
+ } else
+ if (act < ACCEPT_ACTION) { /* shift */
+ consumeToken(currentToken);
+ if (currentElement != null) this.recoveryTokenCheck();
+ try{
+ currentToken = scanner.getNextToken();
+ } catch(InvalidInputException e){
+ if (!hasReportedError){
+ this.problemReporter().scannerError(this, e.getMessage());
+ hasReportedError = true;
+ }
+ lastCheckPoint = scanner.currentPosition;
+ restartRecovery = true;
+ }
+ continue ProcessTerminals;
+ } else
+ break ProcessTerminals;
+
+ ProcessNonTerminals : do { /* reduce */
+ consumeRule(act);
+ stateStackTop -= (rhs[act] - 1);
+ act = ntAction(stack[stateStackTop], lhs[act]);
+ } while (act <= NUM_RULES);
+ }
+ endParse(act);
+}
+// A P I
+
+public void parse(ConstructorDeclaration cd, CompilationUnitDeclaration unit) {
+ //only parse the method body of cd
+ //fill out its statements
+
+ //convert bugs into parse error
+
+ initialize();
+ goForConstructorBody();
+ nestedMethod[nestedType]++;
+
+ referenceContext = cd;
+ compilationUnit = unit;
+
+ scanner.resetTo(cd.sourceEnd + 1, cd.declarationSourceEnd);
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ lastAct = ERROR_ACTION;
+ } finally {
+ nestedMethod[nestedType]--;
+ }
+
+ if (lastAct == ERROR_ACTION) {
+ initialize();
+ return;
+ }
+
+ //statements
+ cd.explicitDeclarations = realBlockStack[realBlockPtr--];
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) != 0) {
+ astPtr -= length;
+ if (astStack[astPtr + 1] instanceof ExplicitConstructorCall)
+ //avoid a isSomeThing that would only be used here BUT what is faster between two alternatives ?
+ {
+ System.arraycopy(
+ astStack,
+ astPtr + 2,
+ cd.statements = new Statement[length - 1],
+ 0,
+ length - 1);
+ cd.constructorCall = (ExplicitConstructorCall) astStack[astPtr + 1];
+ } else { //need to add explicitly the super();
+ System.arraycopy(
+ astStack,
+ astPtr + 1,
+ cd.statements = new Statement[length],
+ 0,
+ length);
+ cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+ }
+ } else {
+ cd.constructorCall = SuperReference.implicitSuperConstructorCall();
+ }
+
+ if (cd.constructorCall.sourceEnd == 0) {
+ cd.constructorCall.sourceEnd = cd.sourceEnd;
+ cd.constructorCall.sourceStart = cd.sourceStart;
+ }
+}
+// A P I
+
+public void parse(
+ Initializer ini,
+ TypeDeclaration type,
+ CompilationUnitDeclaration unit) {
+ //only parse the method body of md
+ //fill out method statements
+
+ //convert bugs into parse error
+
+ initialize();
+ goForInitializer();
+ nestedMethod[nestedType]++;
+
+ referenceContext = type;
+ compilationUnit = unit;
+
+ scanner.resetTo(ini.sourceStart, ini.sourceEnd); // just on the beginning {
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ lastAct = ERROR_ACTION;
+ } finally {
+ nestedMethod[nestedType]--;
+ }
+
+ if (lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ ini.block = ((Initializer) astStack[astPtr]).block;
+
+ // mark initializer with local type if one was found during parsing
+ if ((type.bits & AstNode.HasLocalTypeMASK) != 0) {
+ ini.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();
+ goForMethodBody();
+ nestedMethod[nestedType]++;
+
+ referenceContext = md;
+ compilationUnit = unit;
+
+ scanner.resetTo(md.sourceEnd + 1, md.declarationSourceEnd);
+ // reset the scanner to parser from { down to }
+ try {
+ parse();
+ } catch (AbortCompilation ex) {
+ lastAct = ERROR_ACTION;
+ } finally {
+ nestedMethod[nestedType]--;
+ }
+
+ if (lastAct == ERROR_ACTION) {
+ return;
+ }
+
+ //refill statements
+ md.explicitDeclarations = realBlockStack[realBlockPtr--];
+ int length;
+ if ((length = astLengthStack[astLengthPtr--]) != 0)
+ System.arraycopy(
+ astStack,
+ (astPtr -= length) + 1,
+ md.statements = new Statement[length],
+ 0,
+ length);
+}
+// A P I
+
+public CompilationUnitDeclaration parse(
+ ICompilationUnit sourceUnit,
+ CompilationResult compilationResult) {
+ // parses a compilation unit and manages error handling (even bugs....)
+
+ CompilationUnitDeclaration unit;
+ try {
+ /* automaton initialization */
+ initialize();
+ goForCompilationUnit();
+
+ /* scanner initialization */
+ scanner.setSource(sourceUnit.getContents());
+
+ /* unit creation */
+ referenceContext =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter,
+ compilationResult,
+ scanner.source.length);
+ /* run automaton */
+ parse();
+ } finally {
+ unit = compilationUnit;
+ compilationUnit = null; // reset parser
+ }
+ return unit;
+}
+// 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();
+
+ /* scanner initialization */
+ scanner.setSource(sourceUnit.getContents());
+ scanner.resetTo(start, end);
+ /* unit creation */
+ referenceContext =
+ compilationUnit =
+ new CompilationUnitDeclaration(
+ problemReporter,
+ compilationResult,
+ scanner.source.length);
+ /* run automaton */
+ parse();
+ } finally {
+ unit = compilationUnit;
+ compilationUnit = null; // reset parser
+ }
+ return unit;
+}
+/**
+ * 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.
+ */
+public ProblemReporter problemReporter(){
+ if (scanner.recordLineSeparator) {
+ compilationUnit.compilationResult.lineSeparatorPositions = scanner.getLineEnds();
+ }
+ problemReporter.referenceContext = referenceContext;
+ return 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 */
+
+ try {
+ identifierStack[++identifierPtr] = scanner.getCurrentIdentifierSource();
+ identifierPositionStack[identifierPtr] =
+ (((long) scanner.startPosition) << 32) + (scanner.currentPosition - 1);
+ } catch (IndexOutOfBoundsException e) {
+ /*---stack reallaocation (identifierPtr is correct)---*/
+ int oldStackLength = identifierStack.length;
+ char[][] oldStack = identifierStack;
+ identifierStack = new char[oldStackLength + 20][];
+ System.arraycopy(oldStack, 0, identifierStack, 0, oldStackLength);
+ identifierStack[identifierPtr] = scanner.getCurrentTokenSource();
+ /*identifier position stack*/
+ long[] oldPos = identifierPositionStack;
+ identifierPositionStack = new long[oldStackLength + 20];
+ System.arraycopy(oldPos, 0, identifierPositionStack, 0, oldStackLength);
+ identifierPositionStack[identifierPtr] =
+ (((long) scanner.startPosition) << 32) + (scanner.currentPosition - 1);
+ };
+
+ try {
+ identifierLengthStack[++identifierLengthPtr] = 1;
+ } catch (IndexOutOfBoundsException e) {
+ /*---stack reallocation (identifierLengthPtr is correct)---*/
+ int oldStackLength = identifierLengthStack.length;
+ int oldStack[] = identifierLengthStack;
+ identifierLengthStack = new int[oldStackLength + 10];
+ System.arraycopy(oldStack, 0, identifierLengthStack, 0, oldStackLength);
+ identifierLengthStack[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 */
+
+ try {
+ identifierLengthStack[++identifierLengthPtr] = flag;
+ } catch (IndexOutOfBoundsException e) {
+ /*---stack reallaocation (identifierLengthPtr is correct)---*/
+ int oldStackLength = identifierLengthStack.length;
+ int oldStack[] = identifierLengthStack;
+ identifierLengthStack = new int[oldStackLength + 10];
+ System.arraycopy(oldStack, 0, identifierLengthStack, 0, oldStackLength);
+ identifierLengthStack[identifierLengthPtr] = flag;
+ };
+
+}
+protected void pushOnAstLengthStack(int pos) {
+ try {
+ astLengthStack[++astLengthPtr] = pos;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = astLengthStack.length;
+ int[] oldPos = astLengthStack;
+ astLengthStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
+ astLengthStack[astLengthPtr] = pos;
+ }
+}
+protected void pushOnAstStack(AstNode node) {
+ /*add a new obj on top of the ast stack
+ astPtr points on the top*/
+
+ try {
+ astStack[++astPtr] = node;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = astStack.length;
+ AstNode[] oldStack = astStack;
+ astStack = new AstNode[oldStackLength + AstStackIncrement];
+ System.arraycopy(oldStack, 0, astStack, 0, oldStackLength);
+ astPtr = oldStackLength;
+ astStack[astPtr] = node;
+ }
+
+ try {
+ astLengthStack[++astLengthPtr] = 1;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = astLengthStack.length;
+ int[] oldPos = astLengthStack;
+ astLengthStack = new int[oldStackLength + AstStackIncrement];
+ System.arraycopy(oldPos, 0, astLengthStack, 0, oldStackLength);
+ astLengthStack[astLengthPtr] = 1;
+ }
+}
+protected void pushOnExpressionStack(Expression expr) {
+
+ try {
+ expressionStack[++expressionPtr] = expr;
+ } catch (IndexOutOfBoundsException e) {
+ //expressionPtr is correct
+ int oldStackLength = expressionStack.length;
+ Expression[] oldStack = expressionStack;
+ expressionStack = new Expression[oldStackLength + ExpressionStackIncrement];
+ System.arraycopy(oldStack, 0, expressionStack, 0, oldStackLength);
+ expressionStack[expressionPtr] = expr;
+ }
+
+ try {
+ expressionLengthStack[++expressionLengthPtr] = 1;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = expressionLengthStack.length;
+ int[] oldPos = expressionLengthStack;
+ expressionLengthStack = new int[oldStackLength + ExpressionStackIncrement];
+ System.arraycopy(oldPos, 0, expressionLengthStack, 0, oldStackLength);
+ expressionLengthStack[expressionLengthPtr] = 1;
+ }
+}
+protected void pushOnExpressionStackLengthStack(int pos) {
+ try {
+ expressionLengthStack[++expressionLengthPtr] = pos;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = expressionLengthStack.length;
+ int[] oldPos = expressionLengthStack;
+ expressionLengthStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldPos, 0, expressionLengthStack, 0, oldStackLength);
+ expressionLengthStack[expressionLengthPtr] = pos;
+ }
+}
+protected void pushOnIntStack(int pos) {
+
+ try {
+ intStack[++intPtr] = pos;
+ } catch (IndexOutOfBoundsException e) {
+ //intPtr is correct
+ int oldStackLength = intStack.length;
+ int oldStack[] = intStack;
+ intStack = new int[oldStackLength + StackIncrement];
+ System.arraycopy(oldStack, 0, intStack, 0, oldStackLength);
+ intStack[intPtr] = pos;
+ }
+}
+protected static char[] readTable(String filename) throws java.io.IOException {
+
+ //files are located at Parser.class directory
+
+ InputStream stream = new BufferedInputStream(Parser.class.getResourceAsStream(filename));
+ if (stream == null) {
+ throw new java.io.IOException(Util.bind("parser.missingFile",filename)); //$NON-NLS-1$
+ }
+ byte[] bytes = null;
+ try {
+ bytes = Util.getInputStreamAsByteArray(stream, -1);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+
+ //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;
+}
+/* Token check performed on every token shift once having entered
+ * recovery mode.
+ */
+public void recoveryTokenCheck() {
+ switch (currentToken) {
+ case TokenNameLBRACE : {
+ RecoveredElement newElement =
+ currentElement.updateOnOpeningBrace(scanner.currentPosition - 1);
+ lastCheckPoint = scanner.currentPosition;
+ if (newElement != null){ // null means nothing happened
+ restartRecovery = true; // opening brace detected
+ currentElement = newElement;
+ }
+ break;
+ }
+ case TokenNameRBRACE : {
+ endPosition = this.flushAnnotationsDefinedPriorTo(scanner.currentPosition - 1);
+ RecoveredElement newElement =
+ currentElement.updateOnClosingBrace(scanner.startPosition, scanner.currentPosition -1);
+ lastCheckPoint = scanner.currentPosition;
+ if (newElement != currentElement){
+ currentElement = newElement;
+ }
+ }
+ }
+}
+protected void reportSyntaxError(int act, int currentKind, int stateStackTop) {
+
+ /* remember current scanner position */
+ int startPos = scanner.startPosition;
+ int currentPos = scanner.currentPosition;
+
+ String[] expectings;
+ String tokenName = name[symbol_index[currentKind]];
+
+ //fetch all "accurate" possible terminals that could recover the error
+ int start, end = start = asi(stack[stateStackTop]);
+ while (asr[end] != 0)
+ end++;
+ int length = end - start;
+ expectings = new String[length];
+ if (length != 0) {
+ char[] indexes = new char[length];
+ System.arraycopy(asr, start, indexes, 0, length);
+ for (int i = 0; i < length; i++) {
+ expectings[i] = name[symbol_index[indexes[i]]];
+ }
+ }
+
+ //if the pb is an EOF, try to tell the user that they are some
+ if (tokenName.equals(UNEXPECTED_EOF)) {
+ if (!this.checkAndReportBracketAnomalies(problemReporter())) {
+ char[] tokenSource;
+ try {
+ tokenSource = this.scanner.getCurrentTokenSource();
+ } catch (Exception e) {
+ tokenSource = new char[] {};
+ }
+ problemReporter().parseError(
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1,
+ tokenSource,
+ tokenName,
+ expectings);
+ }
+ } else { //the next test is HEAVILY grammar DEPENDENT.
+ if ((length == 2)
+ && (tokenName.equals(";")) //$NON-NLS-1$
+ && (expectings[0] == "++") //$NON-NLS-1$
+ && (expectings[1] == "--") //$NON-NLS-1$
+ && (expressionPtr > -1)) {
+ // the ; is not the expected token ==> it ends a statement when an expression is not ended
+ problemReporter().invalidExpressionAsStatement(expressionStack[expressionPtr]);
+ } else {
+ char[] tokenSource;
+ try {
+ tokenSource = this.scanner.getCurrentTokenSource();
+ } catch (Exception e) {
+ tokenSource = new char[] {};
+ }
+ problemReporter().parseError(
+ this.scanner.startPosition,
+ this.scanner.currentPosition - 1,
+ tokenSource,
+ tokenName,
+ expectings);
+ this.checkAndReportBracketAnomalies(problemReporter());
+ }
+ }
+ /* reset scanner where it was */
+ scanner.startPosition = startPos;
+ scanner.currentPosition = currentPos;
+}
+protected void resetModifiers() {
+ modifiers = AccDefault;
+ modifiersSourceStart = -1; // <-- see comment into modifiersFlag(int)
+ scanner.commentPtr = -1;
+}
+/*
+ * Reset context so as to resume to regular parse loop
+ */
+protected void resetStacks() {
+
+ astPtr = -1;
+ astLengthPtr = -1;
+ expressionPtr = -1;
+ expressionLengthPtr = -1;
+ identifierPtr = -1;
+ identifierLengthPtr = -1;
+ intPtr = -1;
+ nestedMethod[nestedType = 0] = 0; // need to reset for further reuse
+ variablesCounter[nestedType] = 0;
+ dimensions = 0 ;
+ realBlockStack[realBlockPtr = 0] = 0;
+ recoveredStaticInitializerStart = 0;
+ listLength = 0;
+}
+/*
+ * 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 internal stacks
+ this.resetStacks();
+
+ /* attempt to move checkpoint location */
+ if (!this.moveRecoveryCheckpoint()) return false;
+
+ // only look for headers
+ if (referenceContext instanceof CompilationUnitDeclaration){
+ goForHeaders();
+ 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 (currentElement == null){
+ currentElement =
+ this.buildInitialRecoveryState(); // build some recovered elements
+ }
+ /* do not investigate deeper in recovery when no recovered element */
+ if (currentElement == null) return false;
+
+ /* manual forced recovery restart - after headers */
+ if (restartRecovery){
+ 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();
+}
+protected static int tAction(int state, int sym) {
+ return action[check(state + sym) == sym ? state + sym : state];
+}
+public String toString() {
+
+ String s = "identifierStack : char[][] = {"; //$NON-NLS-1$
+ for (int i = 0; i <= identifierPtr; i++) {
+ s = s + "\"" + String.valueOf(identifierStack[i]) + "\","; //$NON-NLS-1$ //$NON-NLS-2$
+ };
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "identierLengthStack : int[] = {"; //$NON-NLS-1$
+ for (int i = 0; i <= identifierLengthPtr; i++) {
+ s = s + identifierLengthStack[i] + ","; //$NON-NLS-1$
+ };
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "astLengthStack : int[] = {"; //$NON-NLS-1$
+ for (int i = 0; i <= astLengthPtr; i++) {
+ s = s + astLengthStack[i] + ","; //$NON-NLS-1$
+ };
+ s = s + "}\n"; //$NON-NLS-1$
+ s = s + "astPtr : int = " + String.valueOf(astPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ s = s + "intStack : int[] = {"; //$NON-NLS-1$
+ for (int i = 0; i <= intPtr; i++) {
+ s = s + intStack[i] + ","; //$NON-NLS-1$
+ };
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "expressionLengthStack : int[] = {"; //$NON-NLS-1$
+ for (int i = 0; i <= expressionLengthPtr; i++) {
+ s = s + expressionLengthStack[i] + ","; //$NON-NLS-1$
+ };
+ s = s + "}\n"; //$NON-NLS-1$
+
+ s = s + "expressionPtr : int = " + String.valueOf(expressionPtr) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$
+
+ s = s + "\n\n\n----------------Scanner--------------\n" + 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 */
+ 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 + astStack[astPtr - variableDeclaratorsCounter + 1].sourceStart;
+ for (int i = 0; i < variableDeclaratorsCounter - 1; i++) {
+ //last one is special(see below)
+ field = (FieldDeclaration) astStack[astPtr - i - 1];
+ field.endPart1Position = endTypeDeclarationPosition;
+ field.endPart2Position = -1 + astStack[astPtr - i].sourceStart;
+ }
+ //last one
+ (field = (FieldDeclaration) astStack[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 = intStack[intPtr--];
+ exp.sourceStart = intStack[intPtr--];
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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 = 307,
+ MAX_NAME_LENGTH = 36,
+ NUM_STATES = 591,
+ NT_OFFSET = 308,
+ SCOPE_UBOUND = -1,
+ SCOPE_SIZE = 0,
+ LA_STATE_OFFSET = 16966,
+ MAX_LA = 1,
+ NUM_RULES = 436,
+ NUM_TERMINALS = 105,
+ NUM_NON_TERMINALS = 203,
+ NUM_SYMBOLS = 308,
+ START_STATE = 12260,
+ EOFT_SYMBOL = 158,
+ EOLT_SYMBOL = 158,
+ ACCEPT_ACTION = 16965,
+ ERROR_ACTION = 16966;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal block structure for parsing recovery
+ */
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypes;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class RecoveredBlock extends RecoveredStatement implements CompilerModifiers, ITerminalSymbols, 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 bracketBalance) {
+
+ /* do not consider a nested block starting passed the block end (if set)
+ it must be belonging to an enclosing block */
+ if (blockDeclaration.sourceEnd != 0
+ && nestedBlockDeclaration.sourceStart > blockDeclaration.sourceEnd){
+ return this.parent.add(nestedBlockDeclaration, bracketBalance);
+ }
+
+ RecoveredBlock element = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalance);
+
+ // if we have a pending Argument, promote it into the new block
+ if (pendingArgument != null){
+ element.attach(pendingArgument);
+ pendingArgument = null;
+ }
+ this.attach(element);
+ if (nestedBlockDeclaration.sourceEnd == 0) return element;
+ return this;
+}
+/*
+ * Record a local declaration
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance) {
+ return this.add(localDeclaration, bracketBalance, false);
+}
+/*
+ * Record a local declaration
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance, 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 (blockDeclaration.sourceEnd != 0
+ && localDeclaration.declarationSourceStart > blockDeclaration.sourceEnd){
+
+ if (delegatedByParent){
+ return this; //ignore
+ } else {
+ return this.parent.add(localDeclaration, bracketBalance);
+ }
+ }
+
+ RecoveredLocalVariable element = new RecoveredLocalVariable(localDeclaration, this, bracketBalance);
+
+ if (localDeclaration instanceof Argument){
+ pendingArgument = element;
+ return this;
+ }
+
+ this.attach(element);
+ if (localDeclaration.declarationSourceEnd == 0) return element;
+ return this;
+}
+/*
+ * Record a statement declaration
+ */
+public RecoveredElement add(Statement statement, int bracketBalance) {
+ return this.add(statement, bracketBalance, false);
+}
+
+/*
+ * Record a statement declaration
+ */
+public RecoveredElement add(Statement statement, int bracketBalance, boolean delegatedByParent) {
+
+ /* do not consider a nested block starting passed the block end (if set)
+ it must be belonging to an enclosing block */
+ if (blockDeclaration.sourceEnd != 0
+ && statement.sourceStart > blockDeclaration.sourceEnd){
+
+ if (delegatedByParent){
+ return this; //ignore
+ } else {
+ return this.parent.add(statement, bracketBalance);
+ }
+ }
+
+ RecoveredStatement element = new RecoveredStatement(statement, this, bracketBalance);
+ this.attach(element);
+ if (statement.sourceEnd == 0) return element;
+ return this;
+}
+/*
+ * Addition of a type to an initializer (act like inside method body)
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
+ return this.add(typeDeclaration, bracketBalance, false);
+}
+/*
+ * Addition of a type to an initializer (act like inside method body)
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance, boolean delegatedByParent) {
+
+ /* do not consider a type starting passed the block end (if set)
+ it must be belonging to an enclosing block */
+ if (blockDeclaration.sourceEnd != 0
+ && typeDeclaration.declarationSourceStart > blockDeclaration.sourceEnd){
+ if (delegatedByParent){
+ return this; //ignore
+ } else {
+ return this.parent.add(typeDeclaration, bracketBalance);
+ }
+ }
+
+ RecoveredStatement element = new RecoveredType(typeDeclaration, this, bracketBalance);
+ this.attach(element);
+ if (typeDeclaration.declarationSourceEnd == 0) return element;
+ return this;
+}
+/*
+ * Attach a recovered statement
+ */
+void attach(RecoveredStatement recoveredStatement) {
+
+ if (statements == null) {
+ statements = new RecoveredStatement[5];
+ statementCount = 0;
+ } else {
+ if (statementCount == statements.length) {
+ System.arraycopy(
+ statements,
+ 0,
+ (statements = new RecoveredStatement[2 * statementCount]),
+ 0,
+ statementCount);
+ }
+ }
+ statements[statementCount++] = recoveredStatement;
+}
+/*
+ * Answer the associated parsed structure
+ */
+public AstNode parseTree(){
+ return blockDeclaration;
+}
+public String toString(int tab) {
+ StringBuffer result = new StringBuffer(tabString(tab));
+ result.append("Recovered block:\n"); //$NON-NLS-1$
+ result.append(blockDeclaration.toString(tab + 1));
+ 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 (!preserveContent || statementCount == 0) return null;
+
+ Statement[] updatedStatements = new Statement[statementCount];
+ int updatedCount = 0;
+
+ // only collect the non-null updated statements
+ for (int i = 0; i < statementCount; i++){
+ Statement updatedStatement = statements[i].updatedStatement();
+ if (updatedStatement != null){
+ updatedStatements[updatedCount++] = updatedStatement;
+ }
+ }
+ if (updatedCount == 0) return null; // not interesting block
+
+ // resize statement collection if necessary
+ if (updatedCount != statementCount){
+ blockDeclaration.statements = new Statement[updatedCount];
+ System.arraycopy(updatedStatements, 0, blockDeclaration.statements, 0, updatedCount);
+ } else {
+ blockDeclaration.statements = updatedStatements;
+ }
+
+ return 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 ((--bracketBalance <= 0) && (parent != null)){
+ this.updateSourceEndIfNecessary(braceEnd);
+
+ /* if the block is the method body, then it closes the method too */
+ RecoveredMethod method = enclosingMethod();
+ if (method != null && method.methodBody == this){
+ return parent.updateOnClosingBrace(braceStart, braceEnd);
+ }
+ RecoveredInitializer initializer = enclosingInitializer();
+ if (initializer != null && initializer.initializerBody == this){
+ return parent.updateOnClosingBrace(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 currentPosition){
+
+ // 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 || statementCount == 0) return null;
+
+ Statement[] updatedStatements = new Statement[statementCount];
+ int updatedCount = 0;
+
+ // only collect the non-null updated statements
+ for (int i = 0; i < statementCount; i++){
+ Statement updatedStatement = statements[i].updatedStatement();
+ if (updatedStatement != null){
+ updatedStatements[updatedCount++] = updatedStatement;
+ }
+ }
+ if (updatedCount == 0) return null; // not interesting block
+
+ // resize statement collection if necessary
+ if (updatedCount != statementCount){
+ blockDeclaration.statements = new Statement[updatedCount];
+ System.arraycopy(updatedStatements, 0, blockDeclaration.statements, 0, updatedCount);
+ } else {
+ blockDeclaration.statements = updatedStatements;
+ }
+
+ return blockDeclaration;
+}
+
+/*
+ * Record a field declaration
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+
+ /* 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, bracketBalance);
+ }
+
+ /* do not consider a local variable starting passed the block end (if set)
+ it must be belonging to an enclosing block */
+ if (blockDeclaration.sourceEnd != 0
+ && fieldDeclaration.declarationSourceStart > blockDeclaration.sourceEnd){
+ return this.parent.add(fieldDeclaration, bracketBalance);
+ }
+
+ // 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal structure for parsing recovery
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.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 bracketBalance) {
+
+ /* default behavior is to delegate recording to parent if any */
+ if (parent == null) {
+ return this; // ignore
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(methodDeclaration.declarationSourceStart - 1));
+ return this.parent.add(methodDeclaration, bracketBalance);
+ }
+}
+/*
+ * Record a nested block declaration
+ */
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalance) {
+
+ /* default behavior is to delegate recording to parent if any */
+ if (parent == null) {
+ return this; // ignore
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(nestedBlockDeclaration.sourceStart - 1));
+ return this.parent.add(nestedBlockDeclaration, bracketBalance);
+ }
+}
+/*
+ * Record a field declaration
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+
+ /* default behavior is to delegate recording to parent if any */
+ if (parent == null) {
+ return this; // ignore
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(fieldDeclaration.declarationSourceStart - 1));
+ return this.parent.add(fieldDeclaration, bracketBalance);
+ }
+}
+/*
+ * Record an import reference
+ */
+public RecoveredElement add(ImportReference importReference, int bracketBalance){
+
+ /* default behavior is to delegate recording to parent if any */
+ if (parent == null) {
+ return this; // ignore
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(importReference.declarationSourceStart - 1));
+ return this.parent.add(importReference, bracketBalance);
+ }
+}
+/*
+ * Record a local declaration
+ */
+public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalance) {
+
+ /* default behavior is to delegate recording to parent if any */
+ if (parent == null) {
+ return this; // ignore
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));
+ return this.parent.add(localDeclaration, bracketBalance);
+ }
+}
+/*
+ * Record a statement
+ */
+public RecoveredElement add(Statement statement, int bracketBalance) {
+
+ /* default behavior is to delegate recording to parent if any */
+ if (parent == null) {
+ return this; // ignore
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(statement.sourceStart - 1));
+ return this.parent.add(statement, bracketBalance);
+ }
+}
+/*
+ * Record a type declaration
+ */
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance){
+
+ /* default behavior is to delegate recording to parent if any */
+ if (parent == null) {
+ return this; // ignore
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));
+ return this.parent.add(typeDeclaration, bracketBalance);
+ }
+}
+/*
+ * 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(){
+}
+/*
+ * A closing brace got consumed, might have closed the current element,
+ * in which case both the currentElement is exited
+ */
+public RecoveredElement updateOnClosingBrace(int braceStart, int braceEnd){
+ if ((--bracketBalance <= 0) && (parent != null)){
+ this.updateSourceEndIfNecessary(braceEnd);
+ return parent;
+ }
+ 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){
+
+ if (bracketBalance++ == 0){
+ this.updateBodyStart(braceEnd + 1);
+ return this;
+ }
+ return null; // no update is necessary
+}
+/*
+ * Final update the corresponding parse node
+ */
+public void updateParseTree(){
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int sourceEnd){
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal field structure for parsing recovery
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ArrayTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.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 bracketBalance) {
+
+ if (this.alreadyCompletedFieldInitialization || !(statement instanceof Expression)) {
+ return super.add(statement, bracketBalance);
+ } 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 bracketBalance) {
+
+ if (this.alreadyCompletedFieldInitialization
+ || !(typeDeclaration instanceof AnonymousLocalTypeDeclaration)
+ || (this.fieldDeclaration.declarationSourceEnd != 0 && typeDeclaration.sourceStart > this.fieldDeclaration.declarationSourceEnd)) {
+ return super.add(typeDeclaration, bracketBalance);
+ } 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, bracketBalance);
+ 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$
+ buffer.append(fieldDeclaration.toString(tab + 1));
+ 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 =
+ ((AnonymousLocalTypeDeclaration)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;
+ }
+ 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 currentPosition){
+ 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(currentPosition - 1);
+ return this.parent.updateOnOpeningBrace(currentPosition);
+}
+public void updateParseTree(){
+ this.updatedFieldDeclaration();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int sourceEnd){
+ if (this.fieldDeclaration.declarationSourceEnd == 0) {
+ this.fieldDeclaration.declarationSourceEnd = sourceEnd;
+ this.fieldDeclaration.declarationEnd = sourceEnd;
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal import structure for parsing recovery
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.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 sourceEnd){
+ if (this.importReference.declarationSourceEnd == 0) {
+ this.importReference.declarationSourceEnd = sourceEnd;
+ this.importReference.declarationEnd = sourceEnd;
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal initializer structure for parsing recovery
+ */
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypes;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class RecoveredInitializer extends RecoveredField implements CompilerModifiers, ITerminalSymbols, 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 bracketBalance) {
+
+ /* 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
+ } else {
+ return this.parent.add(nestedBlockDeclaration, bracketBalance);
+ }
+ }
+ /* consider that if the opening brace was not found, it is there */
+ if (!foundOpeningBrace){
+ foundOpeningBrace = true;
+ this.bracketBalance++;
+ }
+
+ initializerBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalance);
+ if (nestedBlockDeclaration.sourceEnd == 0) return initializerBody;
+ return this;
+}
+/*
+ * Record a field declaration (act like inside method body)
+ */
+public RecoveredElement add(FieldDeclaration newFieldDeclaration, int bracketBalance) {
+
+ /* 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
+ } else {
+ this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(newFieldDeclaration.declarationSourceStart - 1));
+ return this.parent.add(newFieldDeclaration, bracketBalance);
+ }
+ }
+
+ /* 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
+ } else {
+ return this.parent.add(newFieldDeclaration, bracketBalance);
+ }
+ }
+ // 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 bracketBalance) {
+
+ /* 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
+ } else {
+ return this.parent.add(localDeclaration, bracketBalance);
+ }
+ }
+ /* method body should have been created */
+ Block block = new Block(0);
+ block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
+ RecoveredElement element = this.add(block, 1);
+ return element.add(localDeclaration, bracketBalance);
+}
+/*
+ * Record a statement - regular method should have been created a block body
+ */
+public RecoveredElement add(Statement statement, int bracketBalance) {
+
+ /* 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
+ } else {
+ return this.parent.add(statement, bracketBalance);
+ }
+ }
+ /* initializer body should have been created */
+ Block block = new Block(0);
+ block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
+ RecoveredElement element = this.add(block, 1);
+ return element.add(statement, bracketBalance);
+}
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
+
+ /* 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
+ } else {
+ return this.parent.add(typeDeclaration, bracketBalance);
+ }
+ }
+ if (typeDeclaration instanceof LocalTypeDeclaration){
+ /* method body should have been created */
+ Block block = new Block(0);
+ block.sourceStart = ((Initializer)fieldDeclaration).bodyStart;
+ RecoveredElement element = this.add(block, 1);
+ return element.add(typeDeclaration, bracketBalance);
+ }
+ 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, bracketBalance);
+ 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$
+ result.append(this.fieldDeclaration.toString(tab + 1));
+ 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(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 currentPosition){
+ bracketBalance++;
+ return this; // request to restart
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int sourceEnd){
+ if (this.fieldDeclaration.declarationSourceEnd == 0) {
+ this.fieldDeclaration.sourceEnd = sourceEnd;
+ this.fieldDeclaration.declarationSourceEnd = sourceEnd;
+ this.fieldDeclaration.declarationEnd = sourceEnd;
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal local variable structure for parsing recovery
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.ArrayTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.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;
+}
+/*
+ * 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.toString(tab + 1); //$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 currentPosition){
+ 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(currentPosition - 1);
+ return this.parent.updateOnOpeningBrace(currentPosition);
+}
+public void updateParseTree(){
+ this.updatedStatement();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int sourceEnd){
+ if (this.localDeclaration.declarationSourceEnd == 0) {
+ this.localDeclaration.declarationSourceEnd = sourceEnd;
+ this.localDeclaration.declarationEnd = sourceEnd;
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ExplicitConstructorCall;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.ast.SuperReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.BaseTypes;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+/**
+ * Internal method structure for parsing recovery
+ */
+
+public class RecoveredMethod extends RecoveredElement implements CompilerModifiers, ITerminalSymbols, 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 bracketBalance) {
+
+ /* 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, bracketBalance);
+ }
+ }
+ /* consider that if the opening brace was not found, it is there */
+ if (!foundOpeningBrace){
+ foundOpeningBrace = true;
+ this.bracketBalance++;
+ }
+
+ methodBody = new RecoveredBlock(nestedBlockDeclaration, this, bracketBalance);
+ if (nestedBlockDeclaration.sourceEnd == 0) return methodBody;
+ return this;
+}
+/*
+ * Record a field declaration
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+
+ /* 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, bracketBalance);
+ }
+ }
+ /* 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, bracketBalance);
+ }
+ }
+ /* 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 bracketBalance) {
+
+ /* 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, bracketBalance);
+ }
+ }
+ 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, bracketBalance);
+ }
+ return methodBody.add(localDeclaration, bracketBalance, true);
+}
+/*
+ * Record a statement - regular method should have been created a block body
+ */
+public RecoveredElement add(Statement statement, int 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
+ && statement.sourceStart > methodDeclaration.declarationSourceEnd){
+
+ if (this.parent == null) {
+ return this; // ignore
+ } else {
+ return this.parent.add(statement, bracketBalance);
+ }
+ }
+ 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, bracketBalance);
+ }
+ return methodBody.add(statement, bracketBalance, true);
+}
+public RecoveredElement add(TypeDeclaration typeDeclaration, int 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
+ && typeDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd){
+
+ if (this.parent == null) {
+ return this; // ignore
+ } else {
+ return this.parent.add(typeDeclaration, bracketBalance);
+ }
+ }
+ if (typeDeclaration instanceof LocalTypeDeclaration){
+ if (methodBody == null){
+ Block block = new Block(0);
+ block.sourceStart = methodDeclaration.bodyStart;
+ this.add(block, 1);
+ }
+ return methodBody.add(typeDeclaration, bracketBalance, true);
+ }
+ 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, bracketBalance);
+ 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$
+ result.append(this.methodDeclaration.toString(tab + 1));
+ 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 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(braceEnd);
+}
+public void updateParseTree(){
+ this.updatedMethodDeclaration();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int sourceEnd){
+ if (this.methodDeclaration.declarationSourceEnd == 0) {
+ this.methodDeclaration.declarationSourceEnd = sourceEnd;
+ this.methodDeclaration.bodyEnd = sourceEnd;
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal statement structure for parsing recovery
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+
+public class RecoveredStatement extends RecoveredElement {
+
+ public Statement statement;
+ boolean alreadyCompletedLocalInitialization;
+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.toString(tab + 1); //$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 sourceEnd){
+ if (this.statement.sourceEnd == 0)
+ this.statement.sourceEnd = sourceEnd;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.Block;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Initializer;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.MemberTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Statement;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
+
+/**
+ * Internal type structure for parsing recovery
+ */
+
+public class RecoveredType extends RecoveredStatement implements ITerminalSymbols, 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 bracketBalance) {
+
+ /* do not consider a method starting passed the type end (if set)
+ it must be belonging to an enclosing type */
+ if (typeDeclaration.declarationSourceEnd != 0
+ && methodDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
+ return this.parent.add(methodDeclaration, bracketBalance);
+ }
+
+ 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, bracketBalance, 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 bracketBalance) {
+ int modifiers = AccDefault;
+ if(this.parser().recoveredStaticInitializerStart != 0) {
+ modifiers = AccStatic;
+ }
+ return this.add(new Initializer(nestedBlockDeclaration, modifiers), bracketBalance);
+}
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+
+ /* do not consider a field starting passed the type end (if set)
+ it must be belonging to an enclosing type */
+ if (typeDeclaration.declarationSourceEnd != 0
+ && fieldDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd) {
+ return this.parent.add(fieldDeclaration, bracketBalance);
+ }
+ 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, bracketBalance)
+ : new RecoveredInitializer(fieldDeclaration, this, bracketBalance);
+ 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 bracketBalance) {
+
+ /* do not consider a type starting passed the type end (if set)
+ it must be belonging to an enclosing type */
+ if (typeDeclaration.declarationSourceEnd != 0
+ && memberTypeDeclaration.declarationSourceStart > typeDeclaration.declarationSourceEnd){
+ return this.parent.add(memberTypeDeclaration, bracketBalance);
+ }
+
+ if (memberTypeDeclaration instanceof AnonymousLocalTypeDeclaration){
+ if (this.methodCount > 0) {
+ // add it to the last method body
+ RecoveredMethod lastMethod = this.methods[this.methodCount-1];
+ lastMethod.methodDeclaration.bodyEnd = 0; // reopen method
+ lastMethod.methodDeclaration.declarationSourceEnd = 0; // reopen method
+ lastMethod.bracketBalance++; // expect one closing brace
+ return lastMethod.add(typeDeclaration, bracketBalance);
+ } 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, bracketBalance);
+ 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 instanceof AnonymousLocalTypeDeclaration) {
+ result.append(tabString(tab));
+ result.append(" "); //$NON-NLS-1$
+ }
+ result.append(typeDeclaration.toString(tab + 1));
+ 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 instanceof AnonymousLocalTypeDeclaration
+ && !this.preserveContent){
+ return null;
+ }
+
+ TypeDeclaration updatedType = this.updatedTypeDeclaration();
+ if (updatedType instanceof AnonymousLocalTypeDeclaration){
+ /* in presence of an anonymous type, we want the full allocation expression */
+ return ((AnonymousLocalTypeDeclaration)updatedType).allocation;
+ }
+ return updatedType;
+}
+public TypeDeclaration updatedTypeDeclaration(){
+
+ /* update member types */
+ if (memberTypeCount > 0){
+ int existingCount = typeDeclaration.memberTypes == null ? 0 : typeDeclaration.memberTypes.length;
+ MemberTypeDeclaration[] memberTypeDeclarations = new MemberTypeDeclaration[existingCount + memberTypeCount];
+ if (existingCount > 0){
+ System.arraycopy(typeDeclaration.memberTypes, 0, memberTypeDeclarations, 0, existingCount);
+ }
+ // may need to update the declarationSourceEnd of the last type
+ if (memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd == 0){
+ int bodyEnd = bodyEnd();
+ memberTypes[memberTypeCount - 1].typeDeclaration.declarationSourceEnd = bodyEnd;
+ memberTypes[memberTypeCount - 1].typeDeclaration.bodyEnd = bodyEnd;
+ }
+ for (int i = 0; i < memberTypeCount; i++){
+ memberTypeDeclarations[existingCount + i] = (MemberTypeDeclaration)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 bodyEnd = bodyEnd();
+ methods[methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEnd;
+ methods[methodCount - 1].methodDeclaration.bodyEnd = bodyEnd;
+ }
+ 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) {// if was already reduced, then constructor
+ boolean insideFieldInitializer = false;
+ RecoveredElement parent = this.parent;
+ while (parent != null){
+ if (parent instanceof RecoveredField){
+ insideFieldInitializer = true;
+ break;
+ }
+ parent = parent.parent;
+ }
+ typeDeclaration.createsInternalConstructor(!parser().diet || insideFieldInitializer, true);
+ }
+ }
+ /* might need to cast itself into a MemberTypeDeclaration or a LocalTypeDeclaration */
+ TypeDeclaration newTypeDeclaration = null;
+ if ((typeDeclaration instanceof TypeDeclaration) && (parent instanceof RecoveredType)){
+ newTypeDeclaration = new MemberTypeDeclaration(typeDeclaration.compilationResult);
+ } else {
+ if ((typeDeclaration instanceof TypeDeclaration) && (parent instanceof RecoveredMethod)){
+ newTypeDeclaration = new LocalTypeDeclaration(typeDeclaration.compilationResult);
+ }
+ }
+ /* copy slots into new type */
+ if (newTypeDeclaration != null){
+ newTypeDeclaration.modifiers = typeDeclaration.modifiers;
+ newTypeDeclaration.modifiersSourceStart = typeDeclaration.modifiersSourceStart;
+ newTypeDeclaration.name = typeDeclaration.name;
+ newTypeDeclaration.superclass = typeDeclaration.superclass;
+ newTypeDeclaration.superInterfaces = typeDeclaration.superInterfaces;
+ newTypeDeclaration.fields = typeDeclaration.fields;
+ newTypeDeclaration.methods = typeDeclaration.methods;
+ newTypeDeclaration.memberTypes = typeDeclaration.memberTypes;
+ newTypeDeclaration.ignoreFurtherInvestigation = typeDeclaration.ignoreFurtherInvestigation;
+ newTypeDeclaration.maxFieldCount = typeDeclaration.maxFieldCount;
+ newTypeDeclaration.declarationSourceStart = typeDeclaration.declarationSourceStart;
+ newTypeDeclaration.declarationSourceEnd = typeDeclaration.declarationSourceEnd;
+ newTypeDeclaration.bodyEnd = typeDeclaration.bodyEnd;
+ newTypeDeclaration.bodyStart = typeDeclaration.bodyStart;
+ typeDeclaration = newTypeDeclaration;
+ }
+ 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(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 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;
+ }
+ return this.add(init, 1);
+ }
+ return super.updateOnOpeningBrace(braceEnd);
+}
+public void updateParseTree(){
+ this.updatedTypeDeclaration();
+}
+/*
+ * Update the declarationSourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int sourceEnd){
+ if (this.typeDeclaration.declarationSourceEnd == 0){
+ this.bodyEnd = 0;
+ this.typeDeclaration.declarationSourceEnd = sourceEnd;
+ this.typeDeclaration.bodyEnd = sourceEnd;
+ }
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Internal field structure for parsing recovery
+ */
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AnonymousLocalTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.AstNode;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.LocalTypeDeclaration;
+import net.sourceforge.phpdt.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 bracketBalance) {
+
+ /* attach it to last type - if any */
+ if (typeCount > 0){
+ RecoveredType type = this.types[typeCount -1];
+ type.bodyEnd = 0; // reset position
+ type.typeDeclaration.declarationSourceEnd = 0; // reset position
+ type.typeDeclaration.bodyEnd = 0;
+ return type.add(methodDeclaration, bracketBalance);
+ }
+ return this; // ignore
+}
+/*
+ * Record a field declaration: should be attached to last type
+ */
+public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalance) {
+
+ /* attach it to last type - if any */
+ if (typeCount > 0){
+ RecoveredType type = this.types[typeCount -1];
+ type.bodyEnd = 0; // reset position
+ type.typeDeclaration.declarationSourceEnd = 0; // reset position
+ type.typeDeclaration.bodyEnd = 0;
+ return type.add(fieldDeclaration, bracketBalance);
+ }
+ return this; // ignore
+}
+public RecoveredElement add(ImportReference importReference, int bracketBalance) {
+ if (imports == null) {
+ imports = new RecoveredImport[5];
+ importCount = 0;
+ } else {
+ if (importCount == imports.length) {
+ System.arraycopy(
+ imports,
+ 0,
+ (imports = new RecoveredImport[2 * importCount]),
+ 0,
+ importCount);
+ }
+ }
+ RecoveredImport element = new RecoveredImport(importReference, this, bracketBalance);
+ imports[importCount++] = element;
+
+ /* if import not finished, then import becomes current */
+ if (importReference.declarationSourceEnd == 0) return element;
+ return this;
+}
+public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalance) {
+
+ if (typeDeclaration instanceof AnonymousLocalTypeDeclaration){
+ 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, bracketBalance);
+ }
+ }
+ if (types == null) {
+ types = new RecoveredType[5];
+ typeCount = 0;
+ } else {
+ if (typeCount == types.length) {
+ System.arraycopy(
+ types,
+ 0,
+ (types = new RecoveredType[2 * typeCount]),
+ 0,
+ typeCount);
+ }
+ }
+ RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalance);
+ types[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 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$
+ result.append(unitDeclaration.toString(tab + 1));
+ 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 (importCount > 0){
+ ImportReference[] importRefences = new ImportReference[importCount];
+ for (int i = 0; i < importCount; i++){
+ importRefences[i] = imports[i].updatedImportReference();
+ }
+ unitDeclaration.imports = importRefences;
+ }
+ /* update types */
+ if (typeCount > 0){
+ int existingCount = unitDeclaration.types == null ? 0 : unitDeclaration.types.length;
+ TypeDeclaration[] typeDeclarations = new TypeDeclaration[existingCount + typeCount];
+ if (existingCount > 0){
+ System.arraycopy(unitDeclaration.types, 0, typeDeclarations, 0, existingCount);
+ }
+ // may need to update the declarationSourceEnd of the last type
+ if (types[typeCount - 1].typeDeclaration.declarationSourceEnd == 0){
+ types[typeCount - 1].typeDeclaration.declarationSourceEnd = unitDeclaration.sourceEnd;
+ types[typeCount - 1].typeDeclaration.bodyEnd = unitDeclaration.sourceEnd;
+ }
+ int actualCount = existingCount;
+ for (int i = 0; i < typeCount; i++){
+ TypeDeclaration typeDecl = types[i].updatedTypeDeclaration();
+ // filter out local types (12454)
+ if (!(typeDecl instanceof LocalTypeDeclaration)){
+ typeDeclarations[actualCount++] = typeDecl;
+ }
+ }
+ if (actualCount != typeCount){
+ System.arraycopy(
+ typeDeclarations,
+ 0,
+ typeDeclarations = new TypeDeclaration[existingCount+actualCount],
+ 0,
+ existingCount+actualCount);
+ }
+ unitDeclaration.types = typeDeclarations;
+ }
+ return unitDeclaration;
+}
+public void updateParseTree(){
+ this.updatedCompilationUnitDeclaration();
+}
+/*
+ * Update the sourceEnd of the corresponding parse node
+ */
+public void updateSourceEndIfNecessary(int sourceEnd){
+ if (this.unitDeclaration.sourceEnd == 0)
+ this.unitDeclaration.sourceEnd = sourceEnd;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import net.sourceforge.phpdt.core.compiler.IScanner;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.ast.StringLiteral;
+
+public class Scanner implements IScanner, ITerminalSymbols {
+
+ /* 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;
+ public boolean useAssertAsAnIndentifier = false;
+ //flag indicating if processed source contains occurrences of keyword assert
+ public boolean containsAssertKeyword = false;
+
+ public boolean recordLineSeparator;
+ 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;
+ public boolean tokenizeWhiteSpace;
+
+ //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 char[][] comments = new char[10][];
+ public int[] commentStops = new int[10];
+ public int[] commentStarts = new int[10];
+ public int commentPtr = -1; // no comment test with commentPtr value -1
+
+ //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
+ int currentLineNr = -1;
+ int previousLineNr = -1;
+ NLSLine currentLine = null;
+ List lines = new ArrayList();
+ 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 = true;
+ 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++) {
+ 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, false);
+ }
+ public Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace) {
+ this(tokenizeComments, tokenizeWhiteSpace, false);
+ }
+ public final boolean atEnd() {
+ // This code is not relevant if source is
+ // Only a part of the real stream input
+
+ return source.length == currentPosition;
+ }
+ public char[] getCurrentIdentifierSource() {
+ //return the token REAL source (aka unicodes are precomputed)
+
+ char[] result;
+ if (withoutUnicodePtr != 0)
+ //0 is used as a fast test flag so the real first char is in position 1
+ System.arraycopy(withoutUnicodeBuffer, 1, result = new char[withoutUnicodePtr], 0, withoutUnicodePtr);
+ else {
+ int length = currentPosition - startPosition;
+ 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(source, 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 (withoutUnicodePtr != 0)
+ // 0 is used as a fast test flag so the real first char is in position 1
+ System.arraycopy(withoutUnicodeBuffer, 1, result = new char[withoutUnicodePtr], 0, withoutUnicodePtr);
+ else {
+ int length;
+ System.arraycopy(source, startPosition, result = new char[length = currentPosition - 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 (withoutUnicodePtr != 0)
+ //0 is used as a fast test flag so the real first char is in position 1
+ System.arraycopy(withoutUnicodeBuffer, 2,
+ //2 is 1 (real start) + 1 (to jump over the ")
+ result = new char[withoutUnicodePtr - 2], 0, withoutUnicodePtr - 2);
+ else {
+ int length;
+ System.arraycopy(source, startPosition + 1, result = new char[length = currentPosition - startPosition - 2], 0, length);
+ }
+ return result;
+ }
+ 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 (lineEnds == null)
+ return -1;
+ if (lineNumber >= lineEnds.length)
+ return -1;
+ if (lineNumber <= 0)
+ return -1;
+
+ if (lineNumber == lineEnds.length - 1)
+ return eofPosition;
+ return lineEnds[lineNumber - 1]; // next line start one character behind the lineEnd of the previous line
+ }
+ /**
+ * 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 i.e. first line starts at character 0.
+ *
+ * In case the given line number is inconsistent, answers -1.
+ */
+ public final int getLineStart(int lineNumber) {
+
+ if (lineEnds == null)
+ return -1;
+ if (lineNumber >= lineEnds.length)
+ return -1;
+ if (lineNumber <= 0)
+ return -1;
+
+ if (lineNumber == 1)
+ return initialPosition;
+ return lineEnds[lineNumber - 2] + 1; // next line start one character behind the lineEnd of the previous line
+ }
+ 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
+
+ int temp = currentPosition;
+ try {
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1, c2, c3, c4;
+ int unicodeSize = 6;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ unicodeSize++;
+ }
+
+ if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15 || c1 < 0)
+ || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+ || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+ || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+ currentPosition = temp;
+ return false;
+ }
+
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ if (currentCharacter != testedChar) {
+ currentPosition = temp;
+ return false;
+ }
+ unicodeAsBackSlash = currentCharacter == '\\';
+
+ //need the unicode buffer
+ if (withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+ System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
+ }
+ //fill the buffer with the char
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+
+ } //-------------end unicode traitement--------------
+ else {
+ if (currentCharacter != testedChar) {
+ currentPosition = temp;
+ return false;
+ }
+ unicodeAsBackSlash = false;
+ if (withoutUnicodePtr != 0)
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ unicodeAsBackSlash = false;
+ 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
+
+ int temp = currentPosition;
+ try {
+ int result;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1, c2, c3, c4;
+ int unicodeSize = 6;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ unicodeSize++;
+ }
+
+ if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15 || c1 < 0)
+ || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+ || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+ || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+ currentPosition = temp;
+ return 2;
+ }
+
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ if (currentCharacter == testedChar1)
+ result = 0;
+ else if (currentCharacter == testedChar2)
+ result = 1;
+ else {
+ currentPosition = temp;
+ return -1;
+ }
+
+ //need the unicode buffer
+ if (withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+ System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
+ }
+ //fill the buffer with the char
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return result;
+ } //-------------end unicode traitement--------------
+ else {
+ if (currentCharacter == testedChar1)
+ result = 0;
+ else if (currentCharacter == testedChar2)
+ result = 1;
+ else {
+ currentPosition = temp;
+ return -1;
+ }
+
+ if (withoutUnicodePtr != 0)
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return result;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ currentPosition = temp;
+ return -1;
+ }
+ }
+ public final boolean getNextCharAsDigit() {
+ //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
+
+ int temp = currentPosition;
+ try {
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1, c2, c3, c4;
+ int unicodeSize = 6;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ unicodeSize++;
+ }
+
+ if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15 || c1 < 0)
+ || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+ || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+ || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+ currentPosition = temp;
+ return false;
+ }
+
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ if (!Character.isDigit(currentCharacter)) {
+ currentPosition = temp;
+ return false;
+ }
+
+ //need the unicode buffer
+ if (withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+ System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
+ }
+ //fill the buffer with the char
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+ } //-------------end unicode traitement--------------
+ else {
+ if (!Character.isDigit(currentCharacter)) {
+ currentPosition = temp;
+ return false;
+ }
+ if (withoutUnicodePtr != 0)
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ 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
+
+ int temp = currentPosition;
+ try {
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1, c2, c3, c4;
+ int unicodeSize = 6;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ unicodeSize++;
+ }
+
+ if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15 || c1 < 0)
+ || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+ || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+ || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+ currentPosition = temp;
+ return false;
+ }
+
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ if (Character.digit(currentCharacter, radix) == -1) {
+ currentPosition = temp;
+ return false;
+ }
+
+ //need the unicode buffer
+ if (withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+ System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
+ }
+ //fill the buffer with the char
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+ } //-------------end unicode traitement--------------
+ else {
+ if (Character.digit(currentCharacter, radix) == -1) {
+ currentPosition = temp;
+ return false;
+ }
+ if (withoutUnicodePtr != 0)
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ 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
+
+ int temp = currentPosition;
+ try {
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1, c2, c3, c4;
+ int unicodeSize = 6;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ unicodeSize++;
+ }
+
+ if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15 || c1 < 0)
+ || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+ || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+ || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+ currentPosition = temp;
+ return false;
+ }
+
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ if (!Character.isJavaIdentifierPart(currentCharacter)) {
+ currentPosition = temp;
+ return false;
+ }
+
+ //need the unicode buffer
+ if (withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+ System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
+ }
+ //fill the buffer with the char
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+ } //-------------end unicode traitement--------------
+ else {
+ if (!Character.isJavaIdentifierPart(currentCharacter)) {
+ currentPosition = temp;
+ return false;
+ }
+
+ if (withoutUnicodePtr != 0)
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ return true;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ currentPosition = temp;
+ return false;
+ }
+ }
+ public int getNextToken() throws InvalidInputException {
+
+ this.wasAcr = false;
+ if (diet) {
+ jumpOverMethodBody();
+ diet = false;
+ return currentPosition > source.length ? TokenNameEOF : TokenNameRBRACE;
+ }
+ try {
+ while (true) { //loop for jumping over comments
+ withoutUnicodePtr = 0;
+ //start with a new token (even comment written with unicode )
+
+ // ---------Consume white space and handles startPosition---------
+ int whiteStart = currentPosition;
+ boolean isWhiteSpace;
+ do {
+ startPosition = currentPosition;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ isWhiteSpace = jumpOverUnicodeWhiteSpace();
+ } else {
+ if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
+ checkNonExternalizeString();
+ if (recordLineSeparator) {
+ pushLineSeparator();
+ } else {
+ currentLine = null;
+ }
+ }
+ isWhiteSpace = (currentCharacter == ' ') || Character.isWhitespace(currentCharacter);
+ }
+ } while (isWhiteSpace);
+ if (tokenizeWhiteSpace && (whiteStart != currentPosition - 1)) {
+ // reposition scanner in case we are interested by spaces as tokens
+ currentPosition--;
+ startPosition = whiteStart;
+ return TokenNameWHITESPACE;
+ }
+ //little trick to get out in the middle of a source compuation
+ if (currentPosition > eofPosition)
+ return TokenNameEOF;
+
+ // ---------Identify the next token-------------
+
+ switch (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 (currentPosition + lookAhead == source.length)
+ break;
+ if (source[currentPosition + lookAhead] == '\n')
+ break;
+ if (source[currentPosition + lookAhead] == '\'') {
+ 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 (currentPosition + lookAhead == source.length)
+ break;
+ if (source[currentPosition + lookAhead] == '\n')
+ break;
+ if (source[currentPosition + lookAhead] == '\'') {
+ currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+ throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+ }
+ if (getNextChar('\\'))
+ scanEscapeCharacter();
+ else { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ }
+ 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 (currentPosition + lookAhead == source.length)
+ break;
+ if (source[currentPosition + lookAhead] == '\n')
+ break;
+ if (source[currentPosition + lookAhead] == '\'') {
+ currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+ throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
+ case '"' :
+ try {
+ // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+
+ while (currentCharacter != '"') {
+ /**** \r and \n are not valid in string literals ****/
+ if ((currentCharacter == '\n') || (currentCharacter == '\r')) {
+ // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
+ for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
+ if (currentPosition + lookAhead == source.length)
+ break;
+ if (source[currentPosition + lookAhead] == '\n')
+ break;
+ if (source[currentPosition + lookAhead] == '\"') {
+ currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+ throw new InvalidInputException(INVALID_CHAR_IN_STRING);
+ }
+ if (currentCharacter == '\\') {
+ int escapeSize = currentPosition;
+ boolean backSlashAsUnicodeInString = unicodeAsBackSlash;
+ //scanEscapeCharacter make a side effect on this value and we need the previous value few lines down this one
+ scanEscapeCharacter();
+ escapeSize = currentPosition - escapeSize;
+ if (withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ withoutUnicodePtr = currentPosition - escapeSize - 1 - startPosition;
+ System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ } else { //overwrite the / in the buffer
+ withoutUnicodeBuffer[withoutUnicodePtr] = currentCharacter;
+ if (backSlashAsUnicodeInString) { //there are TWO \ in the stream where only one is correct
+ withoutUnicodePtr--;
+ }
+ }
+ }
+ // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+
+ }
+ } catch (IndexOutOfBoundsException e) {
+ 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 (currentPosition + lookAhead == source.length)
+ break;
+ if (source[currentPosition + lookAhead] == '\n')
+ break;
+ if (source[currentPosition + lookAhead] == '\"') {
+ currentPosition += lookAhead + 1;
+ break;
+ }
+ }
+
+ }
+ throw e; // rethrow
+ }
+ if (checkNonExternalizedStringLiterals) { // check for presence of NLS tags //$NON-NLS-?$ where ? is an int.
+ if (currentLine == null) {
+ currentLine = new NLSLine();
+ lines.add(currentLine);
+ }
+ currentLine.add(new StringLiteral(getCurrentTokenSourceString(), startPosition, currentPosition - 1));
+ }
+ return TokenNameStringLiteral;
+ case '/' :
+ {
+ int test;
+ if ((test = getNextChar('/', '*')) == 0) { //line comment
+ int endPositionForLineComment = 0;
+ try { //get the next char
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c4 < 0) {
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ } else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+
+ //handle the \\u case manually into comment
+ if (currentCharacter == '\\') {
+ if (source[currentPosition] == '\\')
+ currentPosition++;
+ } //jump over the \\
+ boolean isUnicode = false;
+ while (currentCharacter != '\r' && currentCharacter != '\n') {
+ //get the next char
+ isUnicode = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ isUnicode = true;
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c4 < 0) {
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ } else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ //handle the \\u case manually into comment
+ if (currentCharacter == '\\') {
+ if (source[currentPosition] == '\\')
+ currentPosition++;
+ } //jump over the \\
+ }
+ if (isUnicode) {
+ endPositionForLineComment = currentPosition - 6;
+ } else {
+ endPositionForLineComment = currentPosition - 1;
+ }
+ recordComment(false);
+ if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
+ checkNonExternalizeString();
+ if (recordLineSeparator) {
+ if (isUnicode) {
+ pushUnicodeLineSeparator();
+ } else {
+ pushLineSeparator();
+ }
+ } else {
+ currentLine = null;
+ }
+ }
+ if (tokenizeComments) {
+ if (!isUnicode) {
+ currentPosition = endPositionForLineComment; // reset one character behind
+ }
+ return TokenNameCOMMENT_LINE;
+ }
+ } catch (IndexOutOfBoundsException e) { //an eof will them be generated
+ if (tokenizeComments) {
+ currentPosition--; // reset one character behind
+ return TokenNameCOMMENT_LINE;
+ }
+ }
+ break;
+ }
+ if (test > 0) { //traditional and annotation comment
+ boolean isJavadoc = false, star = false;
+ // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+
+ if (currentCharacter == '*') {
+ isJavadoc = true;
+ star = true;
+ }
+ if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
+ checkNonExternalizeString();
+ if (recordLineSeparator) {
+ pushLineSeparator();
+ } else {
+ currentLine = null;
+ }
+ }
+ try { //get the next char
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ getNextUnicodeChar();
+ }
+ //handle the \\u case manually into comment
+ if (currentCharacter == '\\') {
+ if (source[currentPosition] == '\\')
+ currentPosition++; //jump over the \\
+ }
+ // empty comment is not a javadoc /**/
+ if (currentCharacter == '/') {
+ isJavadoc = false;
+ }
+ //loop until end of comment */
+ while ((currentCharacter != '/') || (!star)) {
+ if ((currentCharacter == '\r') || (currentCharacter == '\n')) {
+ checkNonExternalizeString();
+ if (recordLineSeparator) {
+ pushLineSeparator();
+ } else {
+ currentLine = null;
+ }
+ }
+ star = currentCharacter == '*';
+ //get next char
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ getNextUnicodeChar();
+ }
+ //handle the \\u case manually into comment
+ if (currentCharacter == '\\') {
+ if (source[currentPosition] == '\\')
+ currentPosition++;
+ } //jump over the \\
+ }
+ recordComment(isJavadoc);
+ if (tokenizeComments) {
+ if (isJavadoc)
+ return TokenNameCOMMENT_JAVADOC;
+ return TokenNameCOMMENT_BLOCK;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ 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(currentCharacter))
+ return scanIdentifierOrKeyword();
+ if (Character.isDigit(currentCharacter))
+ return scanNumber(false);
+ return TokenNameERROR;
+ }
+ }
+ } //-----------------end switch while try--------------------
+ catch (IndexOutOfBoundsException e) {
+ }
+ return TokenNameEOF;
+ }
+ public final void getNextUnicodeChar() throws IndexOutOfBoundsException, 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
+
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0, unicodeSize = 6;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ unicodeSize++;
+ }
+
+ if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c4 < 0) {
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ } else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ //need the unicode buffer
+ if (withoutUnicodePtr == 0) {
+ //buffer all the entries that have been left aside....
+ withoutUnicodePtr = currentPosition - unicodeSize - startPosition;
+ System.arraycopy(source, startPosition, withoutUnicodeBuffer, 1, withoutUnicodePtr);
+ }
+ //fill the buffer with the char
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ unicodeAsBackSlash = currentCharacter == '\\';
+ }
+ /* 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 {
+ startPosition = currentPosition;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ isWhiteSpace = jumpOverUnicodeWhiteSpace();
+ } else {
+ if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+ pushLineSeparator();
+ isWhiteSpace = Character.isWhitespace(currentCharacter);
+ }
+ } while (isWhiteSpace);
+
+ // -------consume token until } is found---------
+ switch (currentCharacter) {
+ case '{' :
+ found++;
+ break;
+ case '}' :
+ found--;
+ if (found == 0)
+ return;
+ break;
+ case '\'' :
+ {
+ boolean test;
+ test = getNextChar('\\');
+ if (test) {
+ try {
+ scanEscapeCharacter();
+ } catch (InvalidInputException ex) {
+ };
+ } else {
+ try { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ } catch (InvalidInputException ex) {
+ };
+ }
+ getNextChar('\'');
+ break;
+ }
+ case '"' :
+ try {
+ try { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ } catch (InvalidInputException ex) {
+ };
+ while (currentCharacter != '"') {
+ if (currentCharacter == '\r') {
+ if (source[currentPosition] == '\n')
+ currentPosition++;
+ break; // the string cannot go further that the line
+ }
+ if (currentCharacter == '\n') {
+ break; // the string cannot go further that the line
+ }
+ if (currentCharacter == '\\') {
+ try {
+ scanEscapeCharacter();
+ } catch (InvalidInputException ex) {
+ };
+ }
+ try { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ } catch (InvalidInputException ex) {
+ };
+ }
+ } catch (IndexOutOfBoundsException e) {
+ return;
+ }
+ break;
+ case '/' :
+ {
+ int test;
+ if ((test = getNextChar('/', '*')) == 0) { //line comment
+ try {
+ //get the next char
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c4 < 0) { //error don't care of the value
+ currentCharacter = 'A';
+ } //something different from \n and \r
+ else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+
+ while (currentCharacter != '\r' && currentCharacter != '\n') {
+ //get the next char
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c4 < 0) { //error don't care of the value
+ currentCharacter = 'A';
+ } //something different from \n and \r
+ else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ }
+ if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+ pushLineSeparator();
+ } catch (IndexOutOfBoundsException e) {
+ } //an eof will them be generated
+ break;
+ }
+ if (test > 0) { //traditional and annotation comment
+ boolean star = false;
+ try { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ };
+ } catch (InvalidInputException ex) {
+ };
+ if (currentCharacter == '*') {
+ star = true;
+ }
+ if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+ pushLineSeparator();
+ try { //get the next char
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c4 < 0) { //error don't care of the value
+ currentCharacter = 'A';
+ } //something different from * and /
+ else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ //loop until end of comment */
+ while ((currentCharacter != '/') || (!star)) {
+ if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+ pushLineSeparator();
+ star = currentCharacter == '*';
+ //get next char
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ //-------------unicode traitement ------------
+ int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ }
+ if ((c1 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c1 < 0
+ || (c2 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c2 < 0
+ || (c3 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c3 < 0
+ || (c4 = Character.getNumericValue(source[currentPosition++])) > 15
+ || c4 < 0) { //error don't care of the value
+ currentCharacter = 'A';
+ } //something different from * and /
+ else {
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ }
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ return;
+ }
+ break;
+ }
+ break;
+ }
+
+ default :
+ if (Character.isJavaIdentifierStart(currentCharacter)) {
+ try {
+ scanIdentifierOrKeyword();
+ } catch (InvalidInputException ex) {
+ };
+ break;
+ }
+ if (Character.isDigit(currentCharacter)) {
+ try {
+ scanNumber(false);
+ } catch (InvalidInputException ex) {
+ };
+ break;
+ }
+ }
+ }
+ //-----------------end switch while try--------------------
+ } catch (IndexOutOfBoundsException e) {
+ } catch (InvalidInputException e) {
+ }
+ 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;
+ currentPosition++;
+ while (source[currentPosition] == 'u') {
+ currentPosition++;
+ unicodeSize++;
+ }
+
+ if (((c1 = Character.getNumericValue(source[currentPosition++])) > 15 || c1 < 0)
+ || ((c2 = Character.getNumericValue(source[currentPosition++])) > 15 || c2 < 0)
+ || ((c3 = Character.getNumericValue(source[currentPosition++])) > 15 || c3 < 0)
+ || ((c4 = Character.getNumericValue(source[currentPosition++])) > 15 || c4 < 0)) {
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ }
+
+ currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
+ if (recordLineSeparator && ((currentCharacter == '\r') || (currentCharacter == '\n')))
+ pushLineSeparator();
+ if (Character.isWhitespace(currentCharacter))
+ return true;
+
+ //buffer the new char which is not a white space
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ //withoutUnicodePtr == 1 is true here
+ return false;
+ } catch (IndexOutOfBoundsException e) {
+ throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
+ }
+ }
+ public final int[] getLineEnds() {
+ //return a bounded copy of this.lineEnds
+
+ int[] copy;
+ System.arraycopy(lineEnds, 0, copy = new int[linePtr + 1], 0, linePtr + 1);
+ return copy;
+ }
+
+ public char[] getSource() {
+ return this.source;
+ }
+ final char[] optimizedCurrentTokenSource1() {
+ //return always the same char[] build only once
+
+ //optimization at no speed cost of 99.5 % of the singleCharIdentifier
+ char charOne = source[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 = source[startPosition]) << 6) + (c1 = source[startPosition + 1])) % TableSize;
+ char[][] table = 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 = source[startPosition]) << 12) + ((c1 = source[startPosition + 1]) << 6) + (c2 = source[startPosition + 2]))
+ % TableSize;
+ char[][] table = 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 = source[startPosition])) << 18)
+ + ((c1 = source[startPosition + 1]) << 12)
+ + ((c2 = source[startPosition + 2]) << 6)
+ + (c3 = source[startPosition + 3]))
+ % TableSize;
+ char[][] table = 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 = source[startPosition])) << 24)
+ + (((long) (c1 = source[startPosition + 1])) << 18)
+ + ((c2 = source[startPosition + 2]) << 12)
+ + ((c3 = source[startPosition + 3]) << 6)
+ + (c4 = source[startPosition + 4]))
+ % TableSize;
+ char[][] table = 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 = source[startPosition])) << 32)
+ + (((long) (c1 = source[startPosition + 1])) << 24)
+ + (((long) (c2 = source[startPosition + 2])) << 18)
+ + ((c3 = source[startPosition + 3]) << 12)
+ + ((c4 = source[startPosition + 4]) << 6)
+ + (c5 = source[startPosition + 5]))
+ % TableSize;
+ char[][] table = 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;
+ }
+ public final void pushLineSeparator() throws InvalidInputException {
+ //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
+ currentLine = null;
+ }
+ //currentCharacter is at position currentPosition-1
+
+ // cr 000D
+ if (currentCharacter == '\r') {
+ int separatorPos = currentPosition - 1;
+ if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
+ return;
+ //System.out.println("CR-" + separatorPos);
+ try {
+ lineEnds[++linePtr] = separatorPos;
+ } catch (IndexOutOfBoundsException e) {
+ //linePtr value is correct
+ int oldLength = lineEnds.length;
+ int[] old = lineEnds;
+ lineEnds = new int[oldLength + INCREMENT];
+ System.arraycopy(old, 0, lineEnds, 0, oldLength);
+ lineEnds[linePtr] = separatorPos;
+ }
+ // look-ahead for merged cr+lf
+ try {
+ if (source[currentPosition] == '\n') {
+ //System.out.println("look-ahead LF-" + currentPosition);
+ lineEnds[linePtr] = currentPosition;
+ currentPosition++;
+ wasAcr = false;
+ } else {
+ wasAcr = true;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ wasAcr = true;
+ }
+ } else {
+ // lf 000A
+ if (currentCharacter == '\n') { //must merge eventual cr followed by lf
+ if (wasAcr && (lineEnds[linePtr] == (currentPosition - 2))) {
+ //System.out.println("merge LF-" + (currentPosition - 1));
+ lineEnds[linePtr] = currentPosition - 1;
+ } else {
+ int separatorPos = currentPosition - 1;
+ if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
+ return;
+ // System.out.println("LF-" + separatorPos);
+ try {
+ lineEnds[++linePtr] = separatorPos;
+ } catch (IndexOutOfBoundsException e) {
+ //linePtr value is correct
+ int oldLength = lineEnds.length;
+ int[] old = lineEnds;
+ lineEnds = new int[oldLength + INCREMENT];
+ System.arraycopy(old, 0, lineEnds, 0, oldLength);
+ lineEnds[linePtr] = separatorPos;
+ }
+ }
+ wasAcr = false;
+ }
+ }
+ }
+ public final void pushUnicodeLineSeparator() {
+ // isUnicode means that the \r or \n has been read as a unicode character
+
+ //see comment on isLineDelimiter(char) for the use of '\n' and '\r'
+
+ final int INCREMENT = 250;
+ //currentCharacter is at position currentPosition-1
+
+ if (this.checkNonExternalizedStringLiterals) {
+ // reinitialize the current line for non externalize strings purpose
+ currentLine = null;
+ }
+
+ // cr 000D
+ if (currentCharacter == '\r') {
+ int separatorPos = currentPosition - 6;
+ if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
+ return;
+ //System.out.println("CR-" + separatorPos);
+ try {
+ lineEnds[++linePtr] = separatorPos;
+ } catch (IndexOutOfBoundsException e) {
+ //linePtr value is correct
+ int oldLength = lineEnds.length;
+ int[] old = lineEnds;
+ lineEnds = new int[oldLength + INCREMENT];
+ System.arraycopy(old, 0, lineEnds, 0, oldLength);
+ lineEnds[linePtr] = separatorPos;
+ }
+ // look-ahead for merged cr+lf
+ if (source[currentPosition] == '\n') {
+ //System.out.println("look-ahead LF-" + currentPosition);
+ lineEnds[linePtr] = currentPosition;
+ currentPosition++;
+ wasAcr = false;
+ } else {
+ wasAcr = true;
+ }
+ } else {
+ // lf 000A
+ if (currentCharacter == '\n') { //must merge eventual cr followed by lf
+ if (wasAcr && (lineEnds[linePtr] == (currentPosition - 7))) {
+ //System.out.println("merge LF-" + (currentPosition - 1));
+ lineEnds[linePtr] = currentPosition - 6;
+ } else {
+ int separatorPos = currentPosition - 6;
+ if ((linePtr > 0) && (lineEnds[linePtr] >= separatorPos))
+ return;
+ // System.out.println("LF-" + separatorPos);
+ try {
+ lineEnds[++linePtr] = separatorPos;
+ } catch (IndexOutOfBoundsException e) {
+ //linePtr value is correct
+ int oldLength = lineEnds.length;
+ int[] old = lineEnds;
+ lineEnds = new int[oldLength + INCREMENT];
+ System.arraycopy(old, 0, lineEnds, 0, oldLength);
+ lineEnds[linePtr] = separatorPos;
+ }
+ }
+ wasAcr = false;
+ }
+ }
+ }
+ public final void recordComment(boolean isJavadoc) {
+
+ // a new annotation comment is recorded
+ try {
+ commentStops[++commentPtr] = isJavadoc ? currentPosition : -currentPosition;
+ } catch (IndexOutOfBoundsException e) {
+ int oldStackLength = commentStops.length;
+ int[] oldStack = commentStops;
+ commentStops = new int[oldStackLength + 30];
+ System.arraycopy(oldStack, 0, commentStops, 0, oldStackLength);
+ commentStops[commentPtr] = isJavadoc ? currentPosition : -currentPosition;
+ //grows the positions buffers too
+ int[] old = commentStarts;
+ commentStarts = new int[oldStackLength + 30];
+ System.arraycopy(old, 0, commentStarts, 0, oldStackLength);
+ }
+
+ //the buffer is of a correct size here
+ commentStarts[commentPtr] = startPosition;
+ }
+ public void resetTo(int begin, int end) {
+ //reset the scanner to a given position where it may rescan again
+
+ diet = false;
+ initialPosition = startPosition = currentPosition = begin;
+ eofPosition = end < Integer.MAX_VALUE ? end + 1 : end;
+ commentPtr = -1; // reset comment stack
+ }
+
+ 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 (unicodeAsBackSlash) {
+ // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ } else
+ currentCharacter = source[currentPosition++];
+ switch (currentCharacter) {
+ case 'b' :
+ currentCharacter = '\b';
+ break;
+ case 't' :
+ currentCharacter = '\t';
+ break;
+ case 'n' :
+ currentCharacter = '\n';
+ break;
+ case 'f' :
+ currentCharacter = '\f';
+ break;
+ case 'r' :
+ currentCharacter = '\r';
+ break;
+ case '\"' :
+ currentCharacter = '\"';
+ break;
+ case '\'' :
+ currentCharacter = '\'';
+ break;
+ case '\\' :
+ currentCharacter = '\\';
+ break;
+ default :
+ // -----------octal escape--------------
+ // OctalDigit
+ // OctalDigit OctalDigit
+ // ZeroToThree OctalDigit OctalDigit
+
+ int number = Character.getNumericValue(currentCharacter);
+ if (number >= 0 && number <= 7) {
+ boolean zeroToThreeNot = number > 3;
+ if (Character.isDigit(currentCharacter = source[currentPosition++])) {
+ int digit = Character.getNumericValue(currentCharacter);
+ if (digit >= 0 && digit <= 7) {
+ number = (number * 8) + digit;
+ if (Character.isDigit(currentCharacter = source[currentPosition++])) {
+ if (zeroToThreeNot) { // has read \NotZeroToThree OctalDigit Digit --> ignore last character
+ currentPosition--;
+ } else {
+ digit = Character.getNumericValue(currentCharacter);
+ if (digit >= 0 && digit <= 7) { // has read \ZeroToThree OctalDigit OctalDigit
+ number = (number * 8) + digit;
+ } else { // has read \ZeroToThree OctalDigit NonOctalDigit --> ignore last character
+ currentPosition--;
+ }
+ }
+ } else { // has read \OctalDigit NonDigit--> ignore last character
+ currentPosition--;
+ }
+ } else { // has read \OctalDigit NonOctalDigit--> ignore last character
+ currentPosition--;
+ }
+ } else { // has read \OctalDigit --> ignore last character
+ currentPosition--;
+ }
+ if (number > 255)
+ throw new InvalidInputException(INVALID_ESCAPE);
+ currentCharacter = (char) number;
+ } else
+ throw new InvalidInputException(INVALID_ESCAPE);
+ }
+ }
+ public int scanIdentifierOrKeyword() throws InvalidInputException {
+ //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
+ //disptach on the second char :-)...cool....but fast !
+ useAssertAsAnIndentifier = false;
+ while (getNextCharAsJavaIdentifierPart()) {
+ };
+
+ int index, length;
+ char[] data;
+ char firstLetter;
+ if (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 = currentPosition - startPosition) == 1)
+ return TokenNameIdentifier;
+ data = source;
+ index = startPosition;
+ } else {
+ if ((length = withoutUnicodePtr) == 1)
+ return TokenNameIdentifier;
+ data = withoutUnicodeBuffer;
+ index = 1;
+ }
+
+ firstLetter = data[index];
+ switch (firstLetter) {
+
+ case 'a' : // as and array
+ switch (length) {
+ case 2 : //as
+ if ((data[++index] == 's')) {
+ return TokenNameas;
+ } else {
+ return TokenNameIdentifier;
+ }
+ case 3 : //and
+ if ((data[++index] == 'n') && (data[++index] == 'd')) {
+ return TokenNameas;
+ } else {
+ return TokenNameIdentifier;
+ }
+ // case 5 :
+ // if ((data[++index] == 'r') && (data[++index] == 'r') && (data[++index] == 'a') && (data[++index] == 'y'))
+ // return TokenNamearray;
+ // else
+ // return TokenNameIdentifier;
+ default :
+ return TokenNameIdentifier;
+ }
+ case 'b' : //break
+ switch (length) {
+ case 5 :
+ if ((data[++index] == 'r') && (data[++index] == 'e') && (data[++index] == 'a') && (data[++index] == 'k'))
+ return TokenNamebreak;
+ else
+ return TokenNameIdentifier;
+ default :
+ return TokenNameIdentifier;
+ }
+
+ case 'c' : //case class continue
+ switch (length) {
+ case 4 :
+ if ((data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 'e'))
+ return TokenNamecase;
+ else
+ return TokenNameIdentifier;
+ case 5 :
+ if ((data[index] == 'l') && (data[++index] == 'a') && (data[++index] == 's') && (data[++index] == 's'))
+ return TokenNameclass;
+ 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' : //define default do
+ switch (length) {
+ case 2 :
+ if ((data[++index] == 'o'))
+ return TokenNamedo;
+ else
+ return TokenNameIdentifier;
+ case 6 :
+ if ((data[++index] == 'e')
+ && (data[++index] == 'f')
+ && (data[++index] == 'i')
+ && (data[++index] == 'n')
+ && (data[++index] == 'e'))
+ return TokenNamedefine;
+ 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' : //echo else elseif extends
+ switch (length) {
+ case 4 :
+ if ((data[++index] == 'c') && (data[++index] == 'h') && (data[++index] == 'o'))
+ return TokenNameecho;
+ else if ((data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
+ return TokenNameelse;
+ else
+ return TokenNameIdentifier;
+ case 5 : // endif
+ if ((data[++index] == 'n') && (data[++index] == 'd') && (data[++index] == 'i') && (data[++index] == 'f'))
+ return TokenNameendif;
+ else
+ return TokenNameIdentifier;
+ case 6 : // endfor
+ if ((data[++index] == 'n')
+ && (data[++index] == 'd')
+ && (data[++index] == 'f')
+ && (data[++index] == 'o')
+ && (data[++index] == 'r'))
+ return TokenNameendfor;
+ else if (
+ (data[++index] == 'l')
+ && (data[++index] == 's')
+ && (data[++index] == 'e')
+ && (data[++index] == 'i')
+ && (data[++index] == 'f'))
+ return TokenNameelseif;
+ 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;
+ case 8 : // endwhile
+ if ((data[++index] == 'n')
+ && (data[++index] == 'd')
+ && (data[++index] == 'w')
+ && (data[++index] == 'h')
+ && (data[++index] == 'i')
+ && (data[++index] == 'l')
+ && (data[++index] == 'e'))
+ return TokenNameendwhile;
+ else
+ return TokenNameIdentifier;
+ case 9 : // endswitch
+ if ((data[++index] == 'n')
+ && (data[++index] == 'd')
+ && (data[++index] == 's')
+ && (data[++index] == 'w')
+ && (data[++index] == 'i')
+ && (data[++index] == 't')
+ && (data[++index] == 'c')
+ && (data[++index] == 'h'))
+ return TokenNameendswitch;
+ else
+ return TokenNameIdentifier;
+ case 10 : // endforeach
+ if ((data[++index] == 'n')
+ && (data[++index] == 'd')
+ && (data[++index] == 'f')
+ && (data[++index] == 'o')
+ && (data[++index] == 'r')
+ && (data[++index] == 'e')
+ && (data[++index] == 'a')
+ && (data[++index] == 'c')
+ && (data[++index] == 'h'))
+ return TokenNameendforeach;
+ else
+ return TokenNameIdentifier;
+
+ default :
+ return TokenNameIdentifier;
+ }
+
+ case 'f' : //for false function
+ switch (length) {
+ case 3 :
+ if ((data[++index] == 'o') && (data[++index] == 'r'))
+ return TokenNamefor;
+ else
+ return TokenNameIdentifier;
+ case 5 :
+ if ((data[index] == 'a') && (data[++index] == 'l') && (data[++index] == 's') && (data[++index] == 'e'))
+ return TokenNamefalse;
+ else
+ return TokenNameIdentifier;
+ case 8 : // function
+ if ((data[index] == 'u')
+ && (data[++index] == 'n')
+ && (data[++index] == 'c')
+ && (data[++index] == 't')
+ && (data[++index] == 'i')
+ && (data[++index] == 'o')
+ && (data[++index] == 'n'))
+ return TokenNamefunction;
+ else
+ return TokenNameIdentifier;
+ default :
+ return TokenNameIdentifier;
+ }
+ case 'g' : //global
+ if (length == 6) {
+ if ((data[++index] == 'l')
+ && (data[++index] == 'o')
+ && (data[++index] == 'b')
+ && (data[++index] == 'a')
+ && (data[++index] == 'l')) {
+ return TokenNameglobal;
+ }
+ }
+ return TokenNameIdentifier;
+
+ case 'i' : //if int
+ 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 7 :
+ if ((data[++index] == 'n')
+ && (data[++index] == 'c')
+ && (data[++index] == 'l')
+ && (data[++index] == 'u')
+ && (data[++index] == 'd')
+ && (data[++index] == 'e'))
+ return TokenNameinclude;
+ else
+ return TokenNameIdentifier;
+ case 12 :
+ if ((data[++index] == 'n')
+ && (data[++index] == 'c')
+ && (data[++index] == 'l')
+ && (data[++index] == 'u')
+ && (data[++index] == 'd')
+ && (data[++index] == 'e')
+ && (data[++index] == '_')
+ && (data[++index] == 'o')
+ && (data[++index] == 'n')
+ && (data[++index] == 'c')
+ && (data[++index] == 'e'))
+ return TokenNameinclude_once;
+ else
+ return TokenNameIdentifier;
+ default :
+ return TokenNameIdentifier;
+ }
+
+ case 'l' : //list
+ if (length == 4) {
+ if ((data[++index] == 'i') && (data[++index] == 's') && (data[++index] == 't')) {
+ return TokenNamelist;
+ }
+ }
+ return TokenNameIdentifier;
+
+ case 'n' : // 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;
+
+ default :
+ return TokenNameIdentifier;
+ }
+ case 'o' : // or old_function
+ if (length == 2) {
+ if (data[++index] == 'r') {
+ return TokenNameor;
+ }
+ }
+// if (length == 12) {
+// if ((data[++index] == 'l')
+// && (data[++index] == 'd')
+// && (data[++index] == '_')
+// && (data[++index] == 'f')
+// && (data[++index] == 'u')
+// && (data[++index] == 'n')
+// && (data[++index] == 'c')
+// && (data[++index] == 't')
+// && (data[++index] == 'i')
+// && (data[++index] == 'o')
+// && (data[++index] == 'n')) {
+// return TokenNameold_function;
+// }
+// }
+ return TokenNameIdentifier;
+
+ case 'p' : // print
+ if (length == 5) {
+ if ((data[++index] == 'r') && (data[++index] == 'i') && (data[++index] == 'n') && (data[++index] == 't')) {
+ return TokenNameprint;
+ }
+ }
+ return TokenNameIdentifier;
+ case 'r' : //return require require_once
+ if (length == 6) {
+ if ((data[++index] == 'e')
+ && (data[++index] == 't')
+ && (data[++index] == 'u')
+ && (data[++index] == 'r')
+ && (data[++index] == 'n')) {
+ return TokenNamereturn;
+ }
+ } else if (length == 7) {
+ if ((data[++index] == 'e')
+ && (data[++index] == 'q')
+ && (data[++index] == 'u')
+ && (data[++index] == 'i')
+ && (data[++index] == 'r')
+ && (data[++index] == 'e')) {
+ return TokenNamerequire;
+ }
+ } else if (length == 12) {
+ if ((data[++index] == 'e')
+ && (data[++index] == 'q')
+ && (data[++index] == 'u')
+ && (data[++index] == 'i')
+ && (data[++index] == 'r')
+ && (data[++index] == 'e')
+ && (data[++index] == '_')
+ && (data[++index] == 'o')
+ && (data[++index] == 'n')
+ && (data[++index] == 'c')
+ && (data[++index] == 'e')) {
+ return TokenNamerequire_once;
+ }
+ } else
+ return TokenNameIdentifier;
+
+ case 's' : //static switch
+ switch (length) {
+ 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;
+ default :
+ return TokenNameIdentifier;
+ }
+
+ case 't' : // true
+ switch (length) {
+
+ case 4 :
+ if ((data[index] == 'r') && (data[++index] == 'u') && (data[++index] == 'e'))
+ return TokenNametrue;
+ else
+ return TokenNameIdentifier;
+ // if ((data[++index] == 'h') && (data[++index] == 'i') && (data[++index] == 's'))
+ // return TokenNamethis;
+
+ default :
+ return TokenNameIdentifier;
+ }
+
+ case 'v' : //void volatile
+ switch (length) {
+ case 3 :
+ if ((data[++index] == 'a') && (data[++index] == 'r'))
+ return TokenNamevar;
+ 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;
+ }
+
+ case 'x' : //xor
+ switch (length) {
+ case 3 :
+ if ((data[++index] == 'o') && (data[++index] == 'r'))
+ return TokenNamexor;
+ else
+ return TokenNameIdentifier;
+
+ default :
+ return TokenNameIdentifier;
+ }
+ default :
+ return TokenNameIdentifier;
+ }
+ }
+ public int scanNumber(boolean dotPrefix) throws InvalidInputException {
+
+ //when entering this method the currentCharacter is the firt
+ //digit of the number , i.e. it may be preceeded by a . when
+ //dotPrefix is true
+
+ boolean floating = dotPrefix;
+ if ((!dotPrefix) && (currentCharacter == '0')) {
+ if (getNextChar('x', 'X') >= 0) { //----------hexa-----------------
+ //force the first char of the hexa number do exist...
+ // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ if (Character.digit(currentCharacter, 16) == -1)
+ throw new InvalidInputException(INVALID_HEXA);
+ //---end forcing--
+ while (getNextCharAsDigit(16)) {
+ };
+ 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()) {
+ };
+
+ 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 ....
+ if (getNextChar('.')) { //bingo ! ....
+ while (getNextCharAsDigit()) {
+ };
+ if (getNextChar('e', 'E') >= 0) { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+
+ if ((currentCharacter == '-') || (currentCharacter == '+')) { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ }
+ if (!Character.isDigit(currentCharacter))
+ throw new InvalidInputException(INVALID_FLOAT);
+ while (getNextCharAsDigit()) {
+ };
+ }
+ if (getNextChar('f', 'F') >= 0)
+ return TokenNameFloatingPointLiteral;
+ getNextChar('d', 'D'); //jump over potential d or D
+ return TokenNameDoubleLiteral;
+ } else {
+ return TokenNameIntegerLiteral;
+ }
+ }
+ } else {
+ /* carry on */
+ }
+ }
+
+ while (getNextCharAsDigit()) {
+ };
+
+ if ((!dotPrefix) && (getNextChar('l', 'L') >= 0))
+ return TokenNameLongLiteral;
+
+ if ((!dotPrefix) && (getNextChar('.'))) { //decimal part that can be empty
+ while (getNextCharAsDigit()) {
+ };
+ floating = true;
+ }
+
+ //if floating is true both exponant and suffix may be optional
+
+ if (getNextChar('e', 'E') >= 0) {
+ floating = true;
+ // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+
+ if ((currentCharacter == '-') || (currentCharacter == '+')) { // consume next character
+ unicodeAsBackSlash = false;
+ if (((currentCharacter = source[currentPosition++]) == '\\') && (source[currentPosition] == 'u')) {
+ getNextUnicodeChar();
+ } else {
+ if (withoutUnicodePtr != 0) {
+ withoutUnicodeBuffer[++withoutUnicodePtr] = currentCharacter;
+ }
+ }
+ }
+ if (!Character.isDigit(currentCharacter))
+ throw new InvalidInputException(INVALID_FLOAT);
+ while (getNextCharAsDigit()) {
+ };
+ }
+
+ 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
+ *
+ */
+ public final int getLineNumber(int position) {
+
+ if (lineEnds == null)
+ return 1;
+ int length = 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 < lineEnds[m]) {
+ d = m - 1;
+ } else if (position > lineEnds[m]) {
+ g = m + 1;
+ } else {
+ return m + 1;
+ }
+ }
+ if (position < lineEnds[m]) {
+ return m + 1;
+ }
+ return m + 2;
+ }
+ public final void setSource(char[] source) {
+ //the source-buffer is set to sourceString
+
+ if (source == null) {
+ this.source = new char[0];
+ } else {
+ this.source = source;
+ }
+ startPosition = -1;
+ initialPosition = currentPosition = 0;
+ containsAssertKeyword = false;
+ withoutUnicodeBuffer = new char[this.source.length];
+
+ }
+
+ public String toString() {
+ if (startPosition == source.length)
+ return "EOF\n\n" + new String(source); //$NON-NLS-1$
+ if (currentPosition > source.length)
+ return "behind the EOF :-( ....\n\n" + new String(source); //$NON-NLS-1$
+
+ char front[] = new char[startPosition];
+ System.arraycopy(source, 0, front, 0, startPosition);
+
+ int middleLength = (currentPosition - 1) - startPosition + 1;
+ char middle[];
+ if (middleLength > -1) {
+ middle = new char[middleLength];
+ System.arraycopy(source, startPosition, middle, 0, middleLength);
+ } else {
+ middle = new char[0];
+ }
+
+ char end[] = new char[source.length - (currentPosition - 1)];
+ System.arraycopy(source, (currentPosition - 1) + 1, end, 0, source.length - (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 Scanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean checkNonExternalizedStringLiterals) {
+ this(tokenizeComments, tokenizeWhiteSpace, checkNonExternalizedStringLiterals, false);
+ }
+
+ public Scanner(
+ boolean tokenizeComments,
+ boolean tokenizeWhiteSpace,
+ boolean checkNonExternalizedStringLiterals,
+ boolean assertMode) {
+ this.eofPosition = Integer.MAX_VALUE;
+ this.tokenizeComments = tokenizeComments;
+ this.tokenizeWhiteSpace = tokenizeWhiteSpace;
+ this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
+ this.assertMode = assertMode;
+ }
+
+ private void checkNonExternalizeString() throws InvalidInputException {
+ if (currentLine == null)
+ return;
+ parseTags(currentLine);
+ }
+
+ private void parseTags(NLSLine line) throws InvalidInputException {
+ 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);
+ 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;
+ currentLine = null;
+ return;
+ }
+ this.wasNonExternalizedStringLiteral = true;
+ if (nonNLSCounter != lineLength) {
+ System.arraycopy(this.nonNLSStrings, 0, (this.nonNLSStrings = new StringLiteral[nonNLSCounter]), 0, nonNLSCounter);
+ }
+ currentLine = null;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+
+public class SourceConstructorDeclaration extends ConstructorDeclaration {
+ public int selectorSourceEnd;
+
+ public SourceConstructorDeclaration(CompilationResult compilationResult){
+ super(compilationResult);
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import net.sourceforge.phpdt.internal.compiler.ast.Expression;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+
+public class SourceFieldDeclaration extends FieldDeclaration {
+ public int fieldEndPosition;
+public SourceFieldDeclaration(
+ Expression initialization,
+ char[] name,
+ int sourceStart,
+ int sourceEnd) {
+ super(initialization, name, sourceStart, sourceEnd);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+
+public class SourceMethodDeclaration extends MethodDeclaration {
+ public int selectorSourceEnd;
+
+ public SourceMethodDeclaration(CompilationResult compilationResult){
+ super(compilationResult);
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.parser;
+
+/**
+ * Converter from source element type to parsed compilation unit.
+ *
+ * Limitation:
+ * | The source element field does not carry any information for its constant part, thus
+ * | the converted parse tree will not include any field initializations.
+ * | Therefore, any binary produced by compiling against converted source elements will
+ * | not take advantage of remote field constant inlining.
+ * | Given the intended purpose of the conversion is to resolve references, this is not
+ * | a problem.
+ *
+ */
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.ast.AbstractMethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.Argument;
+import net.sourceforge.phpdt.internal.compiler.ast.ArrayQualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.ArrayTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.CompilationUnitDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ConstructorDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.FieldDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.ImportReference;
+import net.sourceforge.phpdt.internal.compiler.ast.MemberTypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.MethodDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.QualifiedTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.SingleTypeReference;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeDeclaration;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
+import net.sourceforge.phpdt.internal.compiler.env.ISourceField;
+import net.sourceforge.phpdt.internal.compiler.env.ISourceMethod;
+import net.sourceforge.phpdt.internal.compiler.env.ISourceType;
+import net.sourceforge.phpdt.internal.compiler.lookup.CompilerModifiers;
+import net.sourceforge.phpdt.internal.compiler.problem.ProblemReporter;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class SourceTypeConverter implements CompilerModifiers {
+
+ /*
+ * Convert a set of source element types into a parsed compilation unit declaration
+ * The argument types are then all grouped in the same unit. The argument types must
+ * at least contain one type.
+ * Can optionally ignore fields & methods or member types
+ */
+ public static CompilationUnitDeclaration buildCompilationUnit(
+ ISourceType[] sourceTypes,
+ boolean needFieldsAndMethods,
+ boolean needMemberTypes,
+ ProblemReporter problemReporter,
+ CompilationResult compilationResult) {
+
+ ISourceType sourceType = sourceTypes[0];
+ if (sourceType.getName() == null)
+ return null; // do a basic test that the sourceType is valid
+
+ CompilationUnitDeclaration compilationUnit =
+ new CompilationUnitDeclaration(problemReporter, compilationResult, 0);
+ // not filled at this point
+
+ /* only positions available */
+ int start = sourceType.getNameSourceStart();
+ int end = sourceType.getNameSourceEnd();
+
+ /* convert package and imports */
+ if (sourceType.getPackageName() != null
+ && sourceType.getPackageName().length > 0)
+ // if its null then it is defined in the default package
+ compilationUnit.currentPackage =
+ createImportReference(sourceType.getPackageName(), start, end);
+ char[][] importNames = sourceType.getImports();
+ int importCount = importNames == null ? 0 : importNames.length;
+ compilationUnit.imports = new ImportReference[importCount];
+ for (int i = 0; i < importCount; i++)
+ compilationUnit.imports[i] = createImportReference(importNames[i], start, end);
+ /* convert type(s) */
+ int typeCount = sourceTypes.length;
+ compilationUnit.types = new TypeDeclaration[typeCount];
+ for (int i = 0; i < typeCount; i++) {
+ compilationUnit.types[i] =
+ convert(sourceTypes[i], needFieldsAndMethods, needMemberTypes, compilationResult);
+ }
+ return compilationUnit;
+ }
+
+ /*
+ * Convert a field source element into a parsed field declaration
+ */
+ private static FieldDeclaration convert(ISourceField sourceField) {
+
+ FieldDeclaration field = new FieldDeclaration();
+
+ int start = sourceField.getNameSourceStart();
+ int end = sourceField.getNameSourceEnd();
+
+ field.name = sourceField.getName();
+ field.sourceStart = start;
+ field.sourceEnd = end;
+ field.type = createTypeReference(sourceField.getTypeName(), start, end);
+ field.declarationSourceStart = sourceField.getDeclarationSourceStart();
+ field.declarationSourceEnd = sourceField.getDeclarationSourceEnd();
+ field.modifiers = sourceField.getModifiers();
+
+ /* conversion of field constant: if not present, then cannot generate binary against
+ converted parse nodes */
+ /*
+ if (field.modifiers & AccFinal){
+ char[] initializationSource = sourceField.getInitializationSource();
+ }
+ */
+ return field;
+ }
+
+ /*
+ * Convert a method source element into a parsed method/constructor declaration
+ */
+ private static AbstractMethodDeclaration convert(ISourceMethod sourceMethod, CompilationResult compilationResult) {
+
+ AbstractMethodDeclaration method;
+
+ /* only source positions available */
+ int start = sourceMethod.getNameSourceStart();
+ int end = sourceMethod.getNameSourceEnd();
+
+ if (sourceMethod.isConstructor()) {
+ ConstructorDeclaration decl = new ConstructorDeclaration(compilationResult);
+ decl.isDefaultConstructor = false;
+ method = decl;
+ } else {
+ MethodDeclaration decl = new MethodDeclaration(compilationResult);
+ /* convert return type */
+ decl.returnType =
+ createTypeReference(sourceMethod.getReturnTypeName(), start, end);
+ method = decl;
+ }
+ method.selector = sourceMethod.getSelector();
+ method.modifiers = sourceMethod.getModifiers();
+ method.sourceStart = start;
+ method.sourceEnd = end;
+ method.declarationSourceStart = sourceMethod.getDeclarationSourceStart();
+ method.declarationSourceEnd = sourceMethod.getDeclarationSourceEnd();
+
+ /* convert arguments */
+ char[][] argumentTypeNames = sourceMethod.getArgumentTypeNames();
+ char[][] argumentNames = sourceMethod.getArgumentNames();
+ int argumentCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
+ long position = (long) start << 32 + end;
+ method.arguments = new Argument[argumentCount];
+ for (int i = 0; i < argumentCount; i++) {
+ method.arguments[i] =
+ new Argument(
+ argumentNames[i],
+ position,
+ createTypeReference(argumentTypeNames[i], start, end),
+ AccDefault);
+ // do not care whether was final or not
+ }
+
+ /* convert thrown exceptions */
+ char[][] exceptionTypeNames = sourceMethod.getExceptionTypeNames();
+ int exceptionCount = exceptionTypeNames == null ? 0 : exceptionTypeNames.length;
+ method.thrownExceptions = new TypeReference[exceptionCount];
+ for (int i = 0; i < exceptionCount; i++) {
+ method.thrownExceptions[i] =
+ createTypeReference(exceptionTypeNames[i], start, end);
+ }
+ return method;
+ }
+
+ /*
+ * Convert a source element type into a parsed type declaration
+ *
+ * Can optionally ignore fields & methods
+ */
+ private static TypeDeclaration convert(
+ ISourceType sourceType,
+ boolean needFieldsAndMethods,
+ boolean needMemberTypes,
+ CompilationResult compilationResult) {
+ /* create type declaration - can be member type */
+ TypeDeclaration type;
+ if (sourceType.getEnclosingType() == null) {
+ type = new TypeDeclaration(compilationResult);
+ } else {
+ type = new MemberTypeDeclaration(compilationResult);
+ }
+ type.name = sourceType.getName();
+ int start, end; // only positions available
+ type.sourceStart = start = sourceType.getNameSourceStart();
+ type.sourceEnd = end = sourceType.getNameSourceEnd();
+ type.modifiers = sourceType.getModifiers();
+ type.declarationSourceStart = sourceType.getDeclarationSourceStart();
+ type.declarationSourceEnd = sourceType.getDeclarationSourceEnd();
+ type.bodyEnd = type.declarationSourceEnd;
+
+ /* set superclass and superinterfaces */
+ if (sourceType.getSuperclassName() != null)
+ type.superclass =
+ createTypeReference(sourceType.getSuperclassName(), start, end);
+ char[][] interfaceNames = sourceType.getInterfaceNames();
+ int interfaceCount = interfaceNames == null ? 0 : interfaceNames.length;
+ type.superInterfaces = new TypeReference[interfaceCount];
+ for (int i = 0; i < interfaceCount; i++) {
+ type.superInterfaces[i] = createTypeReference(interfaceNames[i], start, end);
+ }
+ /* convert member types */
+ if (needMemberTypes) {
+ ISourceType[] sourceMemberTypes = sourceType.getMemberTypes();
+ int sourceMemberTypeCount =
+ sourceMemberTypes == null ? 0 : sourceMemberTypes.length;
+ type.memberTypes = new MemberTypeDeclaration[sourceMemberTypeCount];
+ for (int i = 0; i < sourceMemberTypeCount; i++) {
+ type.memberTypes[i] =
+ (MemberTypeDeclaration) convert(sourceMemberTypes[i],
+ needFieldsAndMethods,
+ true,
+ compilationResult);
+ }
+ }
+ /* convert fields and methods */
+ if (needFieldsAndMethods) {
+ /* convert fields */
+ ISourceField[] sourceFields = sourceType.getFields();
+ int sourceFieldCount = sourceFields == null ? 0 : sourceFields.length;
+ type.fields = new FieldDeclaration[sourceFieldCount];
+ for (int i = 0; i < sourceFieldCount; i++) {
+ type.fields[i] = convert(sourceFields[i]);
+ }
+
+ /* convert methods - need to add default constructor if necessary */
+ ISourceMethod[] sourceMethods = sourceType.getMethods();
+ int sourceMethodCount = sourceMethods == null ? 0 : sourceMethods.length;
+
+ /* source type has a constructor ? */
+ /* by default, we assume that one is needed. */
+ int neededCount = 1;
+ for (int i = 0; i < sourceMethodCount; i++) {
+ if (sourceMethods[i].isConstructor()) {
+ neededCount = 0;
+ // Does not need the extra constructor since one constructor already exists.
+ break;
+ }
+ }
+ type.methods = new AbstractMethodDeclaration[sourceMethodCount + neededCount];
+ if (neededCount != 0) { // add default constructor in first position
+ type.methods[0] = type.createsInternalConstructor(false, false);
+ }
+ boolean isInterface = type.isInterface();
+ for (int i = 0; i < sourceMethodCount; i++) {
+ AbstractMethodDeclaration method =convert(sourceMethods[i], compilationResult);
+ if (isInterface || method.isAbstract()) { // fix-up flag
+ method.modifiers |= AccSemicolonBody;
+ }
+ type.methods[neededCount + i] = method;
+ }
+ }
+ return type;
+ }
+
+ /*
+ * Build an import reference from an import name, e.g. java.lang.*
+ */
+ private static ImportReference createImportReference(
+ char[] importName,
+ int start,
+ int end) {
+
+ /* count identifiers */
+ int max = importName.length;
+ int identCount = 0;
+ for (int i = 0; i < max; i++) {
+ if (importName[i] == '.')
+ identCount++;
+ }
+ /* import on demand? */
+ boolean onDemand = importName[max - 1] == '*';
+ if (!onDemand)
+ identCount++; // one more ident than dots
+
+ long[] positions = new long[identCount];
+ long position = (long) start << 32 + end;
+ for (int i = 0; i < identCount; i++) {
+ positions[i] = position;
+ }
+ return new ImportReference(
+ CharOperation.splitOn('.', importName, 0, max - (onDemand ? 3 : 1)),
+ positions,
+ onDemand);
+ }
+
+ /*
+ * Build a type reference from a readable name, e.g. java.lang.Object[][]
+ */
+ private static TypeReference createTypeReference(
+ char[] typeSignature,
+ int start,
+ int end) {
+
+ /* count identifiers and dimensions */
+ int max = typeSignature.length;
+ int dimStart = max;
+ int dim = 0;
+ int identCount = 1;
+ for (int i = 0; i < max; i++) {
+ switch (typeSignature[i]) {
+ case '[' :
+ if (dim == 0)
+ dimStart = i;
+ dim++;
+ break;
+ case '.' :
+ identCount++;
+ break;
+ }
+ }
+ /* rebuild identifiers and dimensions */
+ if (identCount == 1) { // simple type reference
+ if (dim == 0) {
+ return new SingleTypeReference(typeSignature, (((long) start )<< 32) + end);
+ } else {
+ char[] identifier = new char[dimStart];
+ System.arraycopy(typeSignature, 0, identifier, 0, dimStart);
+ return new ArrayTypeReference(identifier, dim, (((long) start) << 32) + end);
+ }
+ } else { // qualified type reference
+ long[] positions = new long[identCount];
+ long pos = (((long) start) << 32) + end;
+ for (int i = 0; i < identCount; i++) {
+ positions[i] = pos;
+ }
+ char[][] identifiers =
+ CharOperation.splitOn('.', typeSignature, 0, dimStart - 1);
+ if (dim == 0) {
+ return new QualifiedTypeReference(identifiers, positions);
+ } else {
+ return new ArrayQualifiedTypeReference(identifiers, dim, positions);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+
+/*
+ * 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 int problemId;
+ public String[] problemArguments;
+
+ /* special fields used to abort silently (e.g. when cancelling build process) */
+ public boolean isSilent;
+ public RuntimeException silentException;
+public AbortCompilation() {
+ this((CompilationResult)null);
+}
+public AbortCompilation(int problemId, String[] problemArguments) {
+
+ this.problemId = problemId;
+ this.problemArguments = problemArguments;
+}
+public AbortCompilation(CompilationResult compilationResult) {
+ this(compilationResult, null);
+}
+public AbortCompilation(CompilationResult compilationResult, Throwable exception) {
+ this.compilationResult = compilationResult;
+ this.exception = exception;
+}
+public AbortCompilation(boolean isSilent, RuntimeException silentException) {
+ this.isSilent = isSilent;
+ this.silentException = silentException;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import net.sourceforge.phpdt.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 {
+public AbortCompilationUnit(CompilationResult compilationResult) {
+ super(compilationResult);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import net.sourceforge.phpdt.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 {
+public AbortMethod(CompilationResult compilationResult) {
+ super(compilationResult);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import net.sourceforge.phpdt.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 {
+public AbortType(CompilationResult compilationResult) {
+ super(compilationResult);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.compiler.env.ICompilationUnit;
+import net.sourceforge.phpdt.internal.compiler.util.Util;
+
+public class DefaultProblem implements ProblemSeverities, IProblem {
+
+ 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(ICompilationUnit compilationUnit) {
+ //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 ((startPosition > endPosition)
+ || ((startPosition <= 0) && (endPosition <= 0)))
+ return Util.bind("problem.noSourceInformation"); //$NON-NLS-1$
+
+ final char SPACE = '\u0020';
+ final char MARK = '^';
+ final char TAB = '\t';
+ char[] source = compilationUnit.getContents();
+ //the next code tries to underline the token.....
+ //it assumes (for a good display) that token source does not
+ //contain any \r \n. This is false on statements !
+ //(the code still works but the display is not optimal !)
+
+ //compute the how-much-char we are displaying around the inaccurate token
+ int begin = startPosition >= source.length ? source.length - 1 : startPosition;
+ int relativeStart = 0;
+ int end = endPosition >= source.length ? source.length - 1 : endPosition;
+ int relativeEnd = 0;
+ label : for (relativeStart = 0;; relativeStart++) {
+ if (begin == 0)
+ break label;
+ if ((source[begin - 1] == '\n') || (source[begin - 1] == '\r'))
+ break label;
+ begin--;
+ }
+ label : for (relativeEnd = 0;; relativeEnd++) {
+ if ((end + 1) >= source.length)
+ break label;
+ if ((source[end + 1] == '\r') || (source[end + 1] == '\n')) {
+ break label;
+ }
+ end++;
+ }
+ //extract the message form the source
+ char[] extract = new char[end - begin + 1];
+ System.arraycopy(source, begin, extract, 0, extract.length);
+ char c;
+ //remove all SPACE and TAB that begin the error message...
+ int trimLeftIndex = 0;
+ while (((c = extract[trimLeftIndex++]) == TAB) || (c == SPACE)) {
+ };
+ System.arraycopy(
+ extract,
+ trimLeftIndex - 1,
+ extract = new char[extract.length - trimLeftIndex + 1],
+ 0,
+ extract.length);
+ relativeStart -= trimLeftIndex;
+ //buffer spaces and tabs in order to reach the error position
+ int pos = 0;
+ char[] underneath = new char[extract.length]; // can't be bigger
+ for (int i = 0; i <= relativeStart; i++) {
+ if (extract[i] == TAB) {
+ underneath[pos++] = TAB;
+ } else {
+ underneath[pos++] = SPACE;
+ }
+ }
+ //mark the error position
+ for (int i = startPosition;
+ i <= (endPosition >= source.length ? source.length - 1 : endPosition);
+ i++)
+ underneath[pos++] = MARK;
+ //resize underneathto remove 'null' chars
+ System.arraycopy(underneath, 0, underneath = new char[pos], 0, pos);
+
+ return " " + Util.bind("problem.atLine", String.valueOf(line)) //$NON-NLS-2$ //$NON-NLS-1$
+ + "\n\t" + new String(extract) + "\n\t" + new String(underneath); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+
+ /**
+ * Answer back the original arguments recorded into the problem.
+ * @return java.lang.String[]
+ */
+ public String[] getArguments() {
+
+ return arguments;
+ }
+
+ /**
+ * Answer the type of problem.
+ * @see org.eclipse.jdt.core.compiler.IProblem#getID()
+ * @return int
+ */
+ public int getID() {
+
+ return id;
+ }
+
+ /**
+ * Answer a localized, human-readable message string which describes the problem.
+ * @return java.lang.String
+ */
+ public String getMessage() {
+
+ return message;
+ }
+
+ /**
+ * Answer the file name in which the problem was found.
+ * @return char[]
+ */
+ public char[] getOriginatingFileName() {
+
+ return fileName;
+ }
+
+ /**
+ * Answer the end position of the problem (inclusive), or -1 if unknown.
+ * @return int
+ */
+ public int getSourceEnd() {
+
+ return endPosition;
+ }
+
+ /**
+ * Answer the line number in source where the problem begins.
+ * @return int
+ */
+ public int getSourceLineNumber() {
+
+ return line;
+ }
+
+ /**
+ * Answer the start position of the problem (inclusive), or -1 if unknown.
+ * @return int
+ */
+ public int getSourceStart() {
+
+ return startPosition;
+ }
+
+ /*
+ * Helper method: checks the severity to see if the Error bit is set.
+ * @return boolean
+ */
+ public boolean isError() {
+
+ return (severity & ProblemSeverities.Error) != 0;
+ }
+
+ /*
+ * Helper method: checks the severity to see if the Error bit is not set.
+ * @return boolean
+ */
+ public boolean isWarning() {
+
+ return (severity & ProblemSeverities.Error) == 0;
+ }
+
+ /**
+ * 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) {
+
+ 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) {
+
+ 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) {
+
+ startPosition = sourceStart;
+ }
+
+ public String toString() {
+
+ String s = "Pb(" + (id & IgnoreCategoriesMask) + ") "; //$NON-NLS-1$ //$NON-NLS-2$
+ if (message != null) {
+ s += message;
+ } else {
+ if (arguments != null)
+ for (int i = 0; i < arguments.length; i++)
+ s += " " + arguments[i]; //$NON-NLS-1$
+ }
+ return s;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.compiler.IProblemFactory;
+import net.sourceforge.phpdt.internal.compiler.util.CharOperation;
+
+public class DefaultProblemFactory implements IProblemFactory {
+
+
+ public String[] messageTemplates;
+ private Locale locale;
+ private static String[] DEFAULT_LOCALE_TEMPLATES;
+ private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+ private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+
+/**
+ * @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>arguments the arguments needed to set the error message
+ * <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 arguments 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[] arguments,
+ int severity,
+ int startPosition,
+ int endPosition,
+ int lineNumber) {
+
+ return new DefaultProblem(
+ originatingFileName,
+ this.getLocalizedMessage(problemId, arguments),
+ problemId,
+ arguments,
+ severity,
+ startPosition,
+ endPosition,
+ lineNumber);
+}
+/**
+ * Answer the locale used to retrieve the error messages
+ * @return java.util.Locale
+ */
+public Locale getLocale() {
+ return locale;
+}
+public final String getLocalizedMessage(int id, String[] problemArguments) {
+ StringBuffer output = new StringBuffer(80);
+ String message =
+ messageTemplates[(id & IProblem.IgnoreCategoriesMask)];
+ if (message == null) {
+ return "Unable to retrieve the error message for problem id: " //$NON-NLS-1$
+ + id
+ + ". 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);
+ message = new String(messageWithNoDoubleQuotes);
+
+ int length = message.length();
+ int start = -1, end = length;
+ while (true) {
+ if ((end = message.indexOf('{', start)) > -1) {
+ output.append(message.substring(start + 1, end));
+ if ((start = message.indexOf('}', end)) > -1) {
+ try {
+ output.append(
+ problemArguments[Integer.parseInt(message.substring(end + 1, start))]);
+ } catch (NumberFormatException nfe) {
+ output.append(message.substring(end + 1, start + 1));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return "Corrupted compiler resources for problem id: " //$NON-NLS-1$
+ + (id & IProblem.IgnoreCategoriesMask)
+ + ". Check compiler resources."; //$NON-NLS-1$
+ }
+ } else {
+ output.append(message.substring(end, length));
+ break;
+ }
+ } else {
+ output.append(message.substring(start + 1, length));
+ 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.
+ */
+public static String[] loadMessageTemplates(Locale loc) {
+ ResourceBundle bundle = ResourceBundle.getBundle("org.eclipse.jdt.internal.compiler.problem.messages", loc); //$NON-NLS-1$
+ String[] templates = new String[500];
+ for (int i = 0, max = templates.length; i < max; i++) {
+ try {
+ templates[i] = bundle.getString(String.valueOf(i));
+ } catch (MissingResourceException e) {
+ // available ID
+ }
+ }
+ return templates;
+}
+
+public DefaultProblemFactory() {
+ this(Locale.getDefault());
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.compiler.CompilationResult;
+import net.sourceforge.phpdt.internal.compiler.IErrorHandlingPolicy;
+import net.sourceforge.phpdt.internal.compiler.IProblemFactory;
+import net.sourceforge.phpdt.internal.compiler.impl.CompilerOptions;
+import net.sourceforge.phpdt.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 {
+
+ 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,
+ int severity,
+ int problemStartPosition,
+ int problemEndPosition,
+ int lineNumber,
+ ReferenceContext referenceContext,
+ CompilationResult unitResult) {
+
+ return problemFactory.createProblem(
+ fileName,
+ problemId,
+ problemArguments,
+ severity,
+ problemStartPosition,
+ problemEndPosition,
+ lineNumber);
+}
+public void handle(
+ int problemId,
+ String[] problemArguments,
+ 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
+ throw new AbortCompilation(problemId, problemArguments);
+ } else {
+ return; // ignore non reportable warning
+ }
+ }
+
+ IProblem problem =
+ this.createProblem(
+ unitResult.getFileName(),
+ problemId,
+ problemArguments,
+ severity,
+ problemStartPosition,
+ problemEndPosition,
+ problemStartPosition >= 0
+ ? searchLineNumber(unitResult.lineSeparatorPositions, problemStartPosition)
+ : 0,
+ referenceContext,
+ unitResult);
+ 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 =
+ (policy.stopOnFirstError() ? AbortCompilation : severity & Abort)) != 0) {
+
+ referenceContext.abort(abortLevel);
+ }
+ 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,
+ int problemStartPosition,
+ int problemEndPosition,
+ ReferenceContext referenceContext,
+ CompilationResult unitResult) {
+
+ this.handle(
+ problemId,
+ problemArguments,
+ 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
+ *
+ * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+ */
+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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.core.compiler.ITerminalSymbols;
+import net.sourceforge.phpdt.core.compiler.InvalidInputException;
+import net.sourceforge.phpdt.internal.compiler.*;
+import net.sourceforge.phpdt.internal.compiler.ast.*;
+import net.sourceforge.phpdt.internal.compiler.lookup.*;
+import net.sourceforge.phpdt.internal.compiler.parser.*;
+import net.sourceforge.phpdt.internal.compiler.util.*;
+import net.sourceforge.phpdt.internal.compiler.impl.*;
+
+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) {
+ this.handle(
+ IProblem.Unclassified,
+ new String[] {errorMessage},
+ Error | Abort,
+ 0,
+ 0);
+}
+public void abortDueToInternalError(String errorMessage, AstNode location) {
+ this.handle(
+ IProblem.Unclassified,
+ new String[] {errorMessage},
+ 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(concreteMethod.readableName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void abstractMethodInAbstractClass(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.AbstractMethodInAbstractClass,
+ new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+ 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(),
+ '.'))},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void abstractMethodNeedingNoBody(AbstractMethodDeclaration method) {
+ this.handle(
+ IProblem.BodyForAbstractMethod,
+ new String[0],
+ method.sourceStart,
+ method.sourceEnd,
+ method,
+ method.compilationResult());
+}
+public void alreadyDefinedLabel(char[] labelName, AstNode location) {
+ this.handle(
+ IProblem.DuplicateLabel,
+ new String[] {new String(labelName)},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void anonymousClassCannotExtendFinalClass(Expression expression, TypeBinding type) {
+ this.handle(
+ IProblem.AnonymousClassCannotExtendFinalClass,
+ new String[] {new String(type.readableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void argumentTypeCannotBeVoid(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, Argument arg) {
+ this.handle(
+ IProblem.ArgumentTypeCannotBeVoid,
+ new String[] {new String(methodDecl.selector), new String(arg.name)},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void argumentTypeCannotBeVoidArray(SourceTypeBinding type, AbstractMethodDeclaration methodDecl, Argument arg) {
+ this.handle(
+ IProblem.ArgumentTypeCannotBeVoidArray,
+ new String[] {new String(methodDecl.selector), new String(arg.name)},
+ 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), arg.name(), new String(expectedType.readableName())},
+ arg.type.sourceStart,
+ arg.type.sourceEnd);
+}
+public void arrayConstantsOnlyInArrayInitializers(int sourceStart, int sourceEnd) {
+ this.handle(
+ IProblem.ArrayConstantsOnlyInArrayInitializers,
+ new String[0],
+ sourceStart,
+ sourceEnd);
+}
+public void attemptToReturnNonVoidExpression(ReturnStatement returnStatement, TypeBinding expectedType) {
+ this.handle(
+ IProblem.VoidMethodReturnsValue,
+ new String[] {new String(expectedType.readableName())},
+ returnStatement.sourceStart,
+ returnStatement.sourceEnd);
+}
+public void attemptToReturnVoidValue(ReturnStatement returnStatement) {
+ this.handle(
+ IProblem.MethodReturnsVoid,
+ new String[] {},
+ returnStatement.sourceStart,
+ returnStatement.sourceEnd);
+}
+public void bytecodeExceeds64KLimit(AbstractMethodDeclaration location) {
+ this.handle(
+ IProblem.BytecodeExceeds64KLimit,
+ new String[] {new String(location.selector)},
+ Error | Abort,
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void bytecodeExceeds64KLimit(TypeDeclaration location) {
+ this.handle(
+ IProblem.BytecodeExceeds64KLimitForClinit,
+ new String[0],
+ Error | Abort,
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void cannotAllocateVoidArray(Expression expression) {
+ this.handle(
+ IProblem.CannotAllocateVoidArray,
+ new String[] {},
+ 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())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void cannotAssignToFinalOuterLocal(LocalVariableBinding local, AstNode location) {
+ this.handle(
+ IProblem.FinalOuterLocalAssignment,
+ new String[] {new String(local.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void cannotDeclareLocalInterface(char[] interfaceName, int sourceStart, int sourceEnd) {
+ this.handle(
+ IProblem.CannotDefineInterfaceInLocalType,
+ new String[] {new String(interfaceName)},
+ sourceStart,
+ sourceEnd);
+}
+public void cannotDefineDimensionsAndInitializer(ArrayAllocationExpression expresssion) {
+ this.handle(
+ IProblem.CannotDefineDimensionExpressionsWithInit,
+ new String[0],
+ 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)},
+ messageSend.sourceStart,
+ messageSend.sourceEnd);
+}
+public void cannotImportPackage(ImportReference importRef) {
+ this.handle(
+ IProblem.CannotImportPackage,
+ new String[] {CharOperation.toString(importRef.tokens)},
+ importRef.sourceStart,
+ importRef.sourceEnd);
+}
+public void cannotInstantiate(TypeReference typeRef, TypeBinding type) {
+ this.handle(
+ IProblem.InvalidClassInstantiation,
+ new String[] {new String(type.readableName())},
+ typeRef.sourceStart,
+ typeRef.sourceEnd);
+}
+public void cannotReferToNonFinalOuterLocal(LocalVariableBinding local, AstNode location) {
+ this.handle(
+ IProblem.OuterLocalMustBeFinal,
+ new String[] {new String(local.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void cannotReturnInInitializer(AstNode location) {
+ this.handle(
+ IProblem.CannotReturnInInitializer,
+ new String[0],
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void cannotThrowNull(ThrowStatement statement) {
+ this.handle(
+ IProblem.CannotThrowNull,
+ new String[0],
+ 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())},
+ exceptionType.sourceStart,
+ exceptionType.sourceEnd);
+}
+public void cannotUseSuperInJavaLangObject(AstNode reference) {
+ this.handle(
+ IProblem.ObjectHasNoSuperclass,
+ new String[0],
+ reference.sourceStart,
+ reference.sourceEnd);
+}
+public void cannotUseSuperInCodeSnippet(int start, int end) {
+ this.handle(
+ IProblem.CannotUseSuperInCodeSnippet,
+ new String[0],
+ Error | Abort,
+ start,
+ end);
+}
+public void caseExpressionMustBeConstant(Expression expression) {
+ this.handle(
+ IProblem.NonConstantExpression,
+ new String[0],
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void classExtendFinalClass(SourceTypeBinding type, TypeReference superclass, TypeBinding expectedType) {
+ this.handle(
+ IProblem.ClassExtendFinalClass,
+ new String[] {new String(expectedType.readableName()), new String(type.sourceName())},
+ superclass.sourceStart,
+ superclass.sourceEnd);
+}
+public void codeSnippetMissingClass(String missing, int start, int end) {
+ this.handle(
+ IProblem.CodeSnippetMissingClass,
+ new String[]{ missing },
+ Error | Abort,
+ start,
+ end);
+}
+public void codeSnippetMissingMethod(String className, String missingMethod, String argumentTypes, int start, int end) {
+ this.handle(
+ IProblem.CodeSnippetMissingMethod,
+ new String[]{ className, missingMethod, argumentTypes },
+ 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
+ int errorThreshold = options.errorThreshold;
+ int warningThreshold = options.warningThreshold;
+
+ switch(problemId){
+
+ case IProblem.UnreachableCatch :
+ case IProblem.CodeCannotBeReached :
+ if ((errorThreshold & CompilerOptions.UnreachableCode) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.UnreachableCode) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.MaskedCatch :
+ if ((errorThreshold & CompilerOptions.MaskedCatchBlock) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.MaskedCatchBlock) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+/*
+ case Never Used :
+ if ((errorThreshold & ParsingOptionalError) != 0){
+ return Error;
+ }
+ if ((warningThreshold & ParsingOptionalError) != 0){
+ return Warning;
+ }
+ return Ignore;
+*/
+ case IProblem.ImportNotFound :
+ case IProblem.ImportNotVisible :
+ case IProblem.ImportAmbiguous :
+ case IProblem.ImportInternalNameProvided :
+ case IProblem.ImportInheritedNameHidesEnclosingName :
+ case IProblem.DuplicateImport :
+ case IProblem.ConflictingImport :
+ case IProblem.CannotImportPackage :
+ if ((errorThreshold & CompilerOptions.ImportProblem) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.ImportProblem) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.UnusedImport :
+ // if import problem are disabled, then ignore
+ if ((errorThreshold & CompilerOptions.ImportProblem) == 0
+ && (warningThreshold & CompilerOptions.ImportProblem) == 0){
+ return Ignore;
+ }
+ if ((errorThreshold & CompilerOptions.UnusedImport) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.UnusedImport) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+/*
+ case UnnecessaryEnclosingInstanceSpecification :
+ if ((errorThreshold & UnnecessaryEnclosingInstance) != 0){
+ return Error;
+ }
+ if ((warningThreshold & UnnecessaryEnclosingInstance) != 0){
+ return Warning;
+ }
+ return Ignore;
+*/
+ case IProblem.MethodButWithConstructorName :
+ if ((errorThreshold & CompilerOptions.MethodWithConstructorName) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.MethodWithConstructorName) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.OverridingNonVisibleMethod :
+ if ((errorThreshold & CompilerOptions.OverriddenPackageDefaultMethod) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.OverriddenPackageDefaultMethod) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.OverridingDeprecatedMethod :
+ case IProblem.UsingDeprecatedType :
+ case IProblem.UsingDeprecatedMethod :
+ case IProblem.UsingDeprecatedConstructor :
+ case IProblem.UsingDeprecatedField :
+ if ((errorThreshold & CompilerOptions.UsingDeprecatedAPI) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.UsingDeprecatedAPI) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.LocalVariableIsNeverUsed :
+ if ((errorThreshold & CompilerOptions.UnusedLocalVariable) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.UnusedLocalVariable) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.ArgumentIsNeverUsed :
+ if ((errorThreshold & CompilerOptions.UnusedArgument) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.UnusedArgument) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.NoImplicitStringConversionForCharArrayExpression :
+ if ((errorThreshold & CompilerOptions.NoImplicitStringConversion) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.NoImplicitStringConversion) != 0){
+ return Warning;
+ }
+ return Ignore;
+
+ case IProblem.NeedToEmulateFieldReadAccess :
+ case IProblem.NeedToEmulateFieldWriteAccess :
+ case IProblem.NeedToEmulateMethodAccess :
+ case IProblem.NeedToEmulateConstructorAccess :
+ if ((errorThreshold & CompilerOptions.AccessEmulation) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.AccessEmulation) != 0){
+ return Warning;
+ }
+ return Ignore;
+ case IProblem.NonExternalizedStringLiteral :
+ if ((errorThreshold & CompilerOptions.NonExternalizedString) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.NonExternalizedString) != 0){
+ return Warning;
+ }
+ return Ignore;
+ case IProblem.UseAssertAsAnIdentifier :
+ if ((errorThreshold & CompilerOptions.AssertUsedAsAnIdentifier) != 0){
+ return Error;
+ }
+ if ((warningThreshold & CompilerOptions.AssertUsedAsAnIdentifier) != 0){
+ return Warning;
+ }
+ return Ignore;
+ 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())},
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void conflictingImport(ImportReference importRef) {
+ this.handle(
+ IProblem.ConflictingImport,
+ new String[] {CharOperation.toString(importRef.tokens)},
+ importRef.sourceStart,
+ importRef.sourceEnd);
+}
+public void constantOutOfFormat(NumberLiteral lit) {
+ // the literal is not in a correct format
+ // this code is called on IntLiteral and LongLiteral
+ // example 000811 ...the 8 is uncorrect.
+
+ if ((lit instanceof LongLiteral) || (lit instanceof IntLiteral)) {
+ char[] source = lit.source();
+ try {
+ final String Radix;
+ final int radix;
+ if ((source[1] == 'x') || (source[1] == 'X')) {
+ radix = 16;
+ Radix = "Hexa"; //$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;
+ }
+ }
+
+ this.handle(
+ IProblem.NumericValueOutOfRange,
+ new String[] {Radix + " " + new String(source) + " (digit " + new String(new char[] {source[place]}) + ")"}, //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ lit.sourceStart,
+ lit.sourceEnd);
+ return;
+ } catch (IndexOutOfBoundsException ex) {}
+
+ // just in case .... use a predefined error..
+ // we should never come here...(except if the code changes !)
+ this.constantOutOfRange(lit);
+ }
+}
+public void constantOutOfRange(Literal lit) {
+ // lit is some how out of range of it declared type
+ // example 9999999999999999999999999999999999999999999999999999999999999999999
+
+ this.handle(
+ IProblem.NumericValueOutOfRange,
+ new String[] {new String(lit.source())},
+ lit.sourceStart,
+ lit.sourceEnd);
+}
+public void deprecatedField(FieldBinding field, AstNode location) {
+ this.handle(
+ IProblem.UsingDeprecatedField,
+ new String[] {new String(field.declaringClass.readableName()), 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)},
+ location.sourceStart,
+ location.sourceEnd);
+ else
+ this.handle(
+ IProblem.UsingDeprecatedMethod,
+ new String[] {new String(method.declaringClass.readableName()), new String(method.selector), parametersAsString(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())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void duplicateCase(Case statement, Constant constant) {
+ this.handle(
+ IProblem.DuplicateCase,
+ new String[] {String.valueOf(constant.intValue())},
+ statement.sourceStart,
+ statement.sourceEnd);
+}
+public void duplicateDefaultCase(DefaultCase statement) {
+ this.handle(
+ IProblem.DuplicateDefaultCase,
+ new String[0],
+ statement.sourceStart,
+ statement.sourceEnd);
+}
+public void duplicateFieldInType(SourceTypeBinding type, FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.DuplicateField,
+ new String[] {new String(type.sourceName()), fieldDecl.name()},
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+public void duplicateImport(ImportReference importRef) {
+ this.handle(
+ IProblem.DuplicateImport,
+ new String[] {CharOperation.toString(importRef.tokens)},
+ importRef.sourceStart,
+ importRef.sourceEnd);
+}
+public void duplicateInitializationOfBlankFinalField(FieldBinding field, Reference reference) {
+ this.handle(
+ IProblem.DuplicateBlankFinalFieldInitialization,
+ new String[] {new String(field.readableName())},
+ reference.sourceStart,
+ reference.sourceEnd);
+}
+public void duplicateInitializationOfFinalLocal(LocalVariableBinding local, NameReference reference) {
+ this.handle(
+ IProblem.DuplicateFinalLocalInitialization,
+ new String[] {new String(local.readableName())},
+ reference.sourceStart,
+ reference.sourceEnd);
+}
+public void duplicateMethodInType(SourceTypeBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.DuplicateMethod,
+ new String[] {new String(methodDecl.selector), new String(type.sourceName())},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void duplicateModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+/* to highlight modifiers use:
+ this.handle(
+ new Problem(
+ DuplicateModifierForField,
+ new String[] {fieldDecl.name()},
+ fieldDecl.modifiers.sourceStart,
+ fieldDecl.modifiers.sourceEnd));
+*/
+
+ this.handle(
+ IProblem.DuplicateModifierForField,
+ new String[] {fieldDecl.name()},
+ 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)},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void duplicateModifierForType(SourceTypeBinding type) {
+ this.handle(
+ IProblem.DuplicateModifierForType,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void duplicateModifierForVariable(LocalDeclaration localDecl, boolean complainForArgument) {
+ this.handle(
+ complainForArgument
+ ? IProblem.DuplicateModifierForArgument
+ : IProblem.DuplicateModifierForVariable,
+ new String[] {localDecl.name()},
+ localDecl.sourceStart,
+ localDecl.sourceEnd);
+}
+public void duplicateNestedType(TypeDeclaration typeDecl) {
+ this.handle(
+ IProblem.DuplicateNestedType,
+ new String[] {new String(typeDecl.name)},
+ 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())},
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd);
+}
+public void duplicateTypes(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
+ this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
+ this.handle(
+ IProblem.DuplicateTypes,
+ new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)},
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ compUnitDecl.compilationResult);
+}
+public void errorNoMethodFor(MessageSend messageSend, TypeBinding recType, TypeBinding[] params) {
+ 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()));
+ }
+
+ this.handle(
+ recType.isArrayType() ? IProblem.NoMessageSendOnArrayType : IProblem.NoMessageSendOnBaseType,
+ new String[] {new String(recType.readableName()), new String(messageSend.selector), buffer.toString()},
+ messageSend.sourceStart,
+ messageSend.sourceEnd);
+}
+public void errorThisSuperInStatic(AstNode reference) {
+ this.handle(
+ IProblem.ThisInStaticContext,
+ new String[] {reference.isSuper() ? "super" : "this"}, //$NON-NLS-2$ //$NON-NLS-1$
+ 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())},
+ exceptionType.sourceStart,
+ exceptionType.sourceEnd);
+}
+public void fieldsOrThisBeforeConstructorInvocation(ThisReference reference) {
+ this.handle(
+ IProblem.ThisSuperDuringConstructorInvocation,
+ new String[0],
+ 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[] {fieldDecl.name(), new String(type.sourceName()), new String(expectedType.readableName())},
+ fieldDecl.type.sourceStart,
+ fieldDecl.type.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())},
+ currentMethod.sourceStart(),
+ currentMethod.sourceEnd());
+}
+public void forwardReference(Reference reference, int indexInQualification, TypeBinding type) {
+ this.handle(
+ IProblem.ReferenceToForwardField,
+ new String[] {},
+ 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,
+ int problemStartPosition,
+ int problemEndPosition){
+
+ this.handle(
+ problemId,
+ problemArguments,
+ problemStartPosition,
+ problemEndPosition,
+ referenceContext,
+ referenceContext == null ? null : referenceContext.compilationResult());
+ 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,
+ int severity,
+ int problemStartPosition,
+ int problemEndPosition){
+
+ this.handle(
+ problemId,
+ problemArguments,
+ severity,
+ problemStartPosition,
+ problemEndPosition,
+ referenceContext,
+ referenceContext == null ? null : referenceContext.compilationResult());
+ 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,
+ int problemStartPosition,
+ int problemEndPosition,
+ CompilationResult unitResult){
+
+ this.handle(
+ problemId,
+ problemArguments,
+ problemStartPosition,
+ problemEndPosition,
+ referenceContext,
+ unitResult);
+ referenceContext = null;
+}
+public void hidingEnclosingType(TypeDeclaration typeDecl) {
+ this.handle(
+ IProblem.HidingEnclosingType,
+ new String[] {new String(typeDecl.name)},
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd);
+}
+public void hierarchyCircularity(SourceTypeBinding sourceType, ReferenceBinding superType, TypeReference reference) {
+ int start = 0;
+ int end = 0;
+ String typeName = ""; //$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());
+ } else {
+ start = reference.sourceStart;
+ end = reference.sourceEnd;
+ typeName = CharOperation.toString(reference.getTypeName());
+ }
+
+ if (sourceType == superType)
+ this.handle(
+ IProblem.HierarchyCircularitySelfReference,
+ new String[] {new String(sourceType.sourceName()), typeName},
+ start,
+ end);
+ else
+ this.handle(
+ IProblem.HierarchyCircularity,
+ new String[] {new String(sourceType.sourceName()), typeName},
+ start,
+ end);
+}
+public void hierarchyHasProblems(SourceTypeBinding type) {
+ this.handle(
+ IProblem.HierarchyHasProblems,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalAbstractModifierCombinationForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.IllegalAbstractModifierCombinationForMethod,
+ new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void illegalModifierCombinationFinalAbstractForClass(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalModifierCombinationFinalAbstractForClass,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalModifierCombinationFinalVolatileForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.IllegalModifierCombinationFinalVolatileForField,
+ new String[] {fieldDecl.name()},
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+
+public void illegalModifierForClass(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalModifierForClass,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalModifierForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.IllegalModifierForField,
+ new String[] {fieldDecl.name()},
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+public void illegalModifierForInterface(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalModifierForInterface,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalModifierForInterfaceField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.IllegalModifierForInterfaceField,
+ new String[] {fieldDecl.name()},
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+public void illegalModifierForInterfaceMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.IllegalModifierForInterfaceMethod,
+ new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void illegalModifierForLocalClass(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalModifierForLocalClass,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalModifierForMemberClass(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalModifierForMemberClass,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalModifierForMemberInterface(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalModifierForMemberInterface,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.IllegalModifierForMethod,
+ new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void illegalModifierForVariable(LocalDeclaration localDecl, boolean complainAsArgument) {
+ this.handle(
+ complainAsArgument
+ ? IProblem.IllegalModifierForArgument
+ : IProblem.IllegalModifierForVariable,
+ new String[] {localDecl.name()},
+ localDecl.sourceStart,
+ localDecl.sourceEnd);
+}
+public void illegalPrimitiveOrArrayTypeForEnclosingInstance(TypeBinding enclosingType, AstNode location) {
+ this.handle(
+ IProblem.IllegalPrimitiveOrArrayTypeForEnclosingInstance,
+ new String[] {new String(enclosingType.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void illegalStaticModifierForMemberType(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalStaticModifierForMemberType,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalVisibilityModifierCombinationForField(ReferenceBinding type, FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.IllegalVisibilityModifierCombinationForField,
+ new String[] {new String(fieldDecl.name())},
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+public void illegalVisibilityModifierCombinationForMemberType(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalVisibilityModifierCombinationForMemberType,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalVisibilityModifierCombinationForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.IllegalVisibilityModifierCombinationForMethod,
+ new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void illegalVisibilityModifierForInterfaceMemberType(SourceTypeBinding type) {
+ this.handle(
+ IProblem.IllegalVisibilityModifierForInterfaceMemberType,
+ new String[] {new String(type.sourceName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void illegalVoidExpression(AstNode location) {
+ this.handle(
+ IProblem.InvalidVoidExpression,
+ new String[] {},
+ 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;
+ }
+ String argument;
+ if(expectedImport instanceof ProblemReferenceBinding) {
+ argument = CharOperation.toString(((ProblemReferenceBinding)expectedImport).compoundName);
+ } else {
+ argument = CharOperation.toString(importRef.tokens);
+ }
+ this.handle(id, new String[] {argument}, importRef.sourceStart, importRef.sourceEnd);
+}
+public void incompatibleExceptionInThrowsClause(SourceTypeBinding type, MethodBinding currentMethod, MethodBinding inheritedMethod, ReferenceBinding exceptionType) {
+ if (type == currentMethod.declaringClass)
+ 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.
+ IProblem.IncompatibleExceptionInThrowsClause,
+ new String[] {
+ new String(exceptionType.sourceName()),
+ new String(
+ CharOperation.concat(
+ inheritedMethod.declaringClass.readableName(),
+ inheritedMethod.readableName(),
+ '.'))},
+ 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(),
+ '.'))},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void incompatibleReturnType(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+ StringBuffer methodSignature = new StringBuffer();
+ methodSignature
+ .append(inheritedMethod.declaringClass.readableName())
+ .append('.')
+ .append(inheritedMethod.readableName());
+
+ 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[] {methodSignature.toString()},
+ currentMethod.sourceStart(),
+ currentMethod.sourceEnd());
+}
+public void incorrectEnclosingInstanceReference(
+ QualifiedThisReference reference,
+ TypeBinding qualificationType) {
+
+ this.handle(
+ IProblem.IncorrectEnclosingInstanceReference,
+ new String[] { new String(qualificationType.readableName())},
+ reference.sourceStart,
+ reference.sourceEnd);
+}
+public void incorrectLocationForEmptyDimension(ArrayAllocationExpression expression, int index) {
+ this.handle(
+ IProblem.IllegalDimension,
+ new String[0],
+ expression.dimensions[index + 1].sourceStart,
+ expression.dimensions[index + 1].sourceEnd);
+}
+public void incorrectSwitchType(Expression expression, TypeBinding testType) {
+ this.handle(
+ IProblem.IncorrectSwitchType,
+ new String[] {new String(testType.readableName())},
+ 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());
+ this.handle(
+ // The inherited method %1 cannot hide the public abstract method in %2
+ IProblem.InheritedMethodReducesVisibility,
+ new String[] {
+ new String(concreteSignature.toString()),
+ new String(abstractMethods[0].declaringClass.readableName())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void inheritedMethodsHaveIncompatibleReturnTypes(SourceTypeBinding type, MethodBinding[] inheritedMethods, int length) {
+ StringBuffer methodSignatures = new StringBuffer();
+ for (int i = length; --i >= 0;) {
+ methodSignatures
+ .append(inheritedMethods[i].declaringClass.readableName())
+ .append('.')
+ .append(inheritedMethods[i].readableName());
+ if (i != 0)
+ methodSignatures.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()},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void initializerMustCompleteNormally(FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.InitializerMustCompleteNormally,
+ new String[0],
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+public void innerTypesCannotDeclareStaticInitializers(ReferenceBinding innerType, AstNode location) {
+ this.handle(
+ IProblem.CannotDefineStaticInitializerInLocalType,
+ new String[] {new String(innerType.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void interfaceCannotHaveConstructors(ConstructorDeclaration constructor) {
+ this.handle(
+ IProblem.InterfaceCannotHaveConstructors,
+ new String[0],
+ constructor.sourceStart,
+ constructor.sourceEnd,
+ constructor,
+ constructor.compilationResult());
+}
+public void interfaceCannotHaveInitializers(SourceTypeBinding type, FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.InterfaceCannotHaveInitializers,
+ new String[] {new String(type.sourceName())},
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+public void invalidBreak(AstNode location) {
+ this.handle(
+ IProblem.InvalidBreak,
+ new String[0],
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void invalidConstructor(Statement statement, MethodBinding targetConstructor) {
+
+ boolean insideDefaultConstructor =
+ (referenceContext instanceof ConstructorDeclaration)
+ && ((ConstructorDeclaration)referenceContext).isDefaultConstructor();
+ boolean insideImplicitConstructorCall =
+ (statement instanceof ExplicitConstructorCall)
+ && (((ExplicitConstructorCall) statement).accessMode == ExplicitConstructorCall.ImplicitSuper);
+
+ int flag = IProblem.UndefinedConstructor; //default...
+ switch (targetConstructor.problemId()) {
+ case NotFound :
+ if (insideDefaultConstructor){
+ flag = IProblem.UndefinedConstructorInDefaultConstructor;
+ } else if (insideImplicitConstructorCall){
+ flag = IProblem.UndefinedConstructorInImplicitConstructorCall;
+ } else {
+ flag = IProblem.UndefinedConstructor;
+ }
+ break;
+ case NotVisible :
+ if (insideDefaultConstructor){
+ flag = IProblem.NotVisibleConstructorInDefaultConstructor;
+ } else if (insideImplicitConstructorCall){
+ flag = IProblem.NotVisibleConstructorInImplicitConstructorCall;
+ } else {
+ flag = IProblem.NotVisibleConstructor;
+ }
+ break;
+ case Ambiguous :
+ if (insideDefaultConstructor){
+ flag = IProblem.AmbiguousConstructorInDefaultConstructor;
+ } else if (insideImplicitConstructorCall){
+ flag = IProblem.AmbiguousConstructorInImplicitConstructorCall;
+ } else {
+ flag = IProblem.AmbiguousConstructor;
+ }
+ break;
+ case NoError : // 0
+ default :
+ needImplementation(); // want to fail to see why we were here...
+ break;
+ }
+
+
+ this.handle(
+ flag,
+ new String[] {new String(targetConstructor.declaringClass.readableName()), parametersAsString(targetConstructor)},
+ statement.sourceStart,
+ statement.sourceEnd);
+}
+public void invalidContinue(AstNode location) {
+ this.handle(
+ IProblem.InvalidContinue,
+ new String[0],
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void invalidEnclosingType(Expression expression, TypeBinding type, TypeBinding enclosingType) {
+
+ 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$
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void invalidExpressionAsStatement(Expression expression){
+ this.handle(
+ IProblem.InvalidExpressionAsStatement,
+ new String[0],
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void invalidField(FieldReference fieldRef, TypeBinding searchedType) {
+ int severity = Error;
+ int flag = IProblem.UndefinedField;
+ FieldBinding field = fieldRef.binding;
+ switch (field.problemId()) {
+ case NotFound :
+ flag = IProblem.UndefinedField;
+/* also need to check that the searchedType is the receiver type
+ if (searchedType.isHierarchyInconsistent())
+ severity = SecondaryError;
+*/
+ break;
+ case NotVisible :
+ flag = IProblem.NotVisibleField;
+ break;
+ case Ambiguous :
+ flag = IProblem.AmbiguousField;
+ break;
+ case NonStaticReferenceInStaticContext :
+ flag = IProblem.NonStaticFieldFromStaticInvocation;
+ break;
+ case NonStaticReferenceInConstructorInvocation :
+ flag = IProblem.InstanceFieldDuringConstructorInvocation;
+ break;
+ case InheritedNameHidesEnclosingName :
+ flag = IProblem.InheritedFieldHidesEnclosingName;
+ break;
+ case NoError : // 0
+ default :
+ needImplementation(); // want to fail to see why we were here...
+ break;
+ }
+
+ this.handle(
+ flag,
+ new String[] {new String(field.readableName())},
+ severity,
+ fieldRef.sourceStart,
+ fieldRef.sourceEnd);
+}
+public void invalidField(NameReference nameRef, FieldBinding field) {
+ int flag = IProblem.UndefinedField;
+ switch (field.problemId()) {
+ case NotFound :
+ flag = IProblem.UndefinedField;
+ break;
+ case NotVisible :
+ flag = IProblem.NotVisibleField;
+ break;
+ case Ambiguous :
+ flag = IProblem.AmbiguousField;
+ break;
+ case NonStaticReferenceInStaticContext :
+ flag = IProblem.NonStaticFieldFromStaticInvocation;
+ break;
+ case NonStaticReferenceInConstructorInvocation :
+ flag = IProblem.InstanceFieldDuringConstructorInvocation;
+ break;
+ case InheritedNameHidesEnclosingName :
+ flag = IProblem.InheritedFieldHidesEnclosingName;
+ break;
+ case NoError : // 0
+ default :
+ needImplementation(); // want to fail to see why we were here...
+ break;
+ }
+ this.handle(
+ flag,
+ new String[] {new String(field.readableName())},
+ 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])},
+ nameRef.sourceStart,
+ nameRef.sourceEnd);
+ return;
+ }
+
+ int flag = IProblem.UndefinedField;
+ switch (field.problemId()) {
+ case NotFound :
+ flag = IProblem.UndefinedField;
+/* also need to check that the searchedType is the receiver type
+ if (searchedType.isHierarchyInconsistent())
+ severity = SecondaryError;
+*/
+ break;
+ case NotVisible :
+ flag = IProblem.NotVisibleField;
+ break;
+ case Ambiguous :
+ flag = IProblem.AmbiguousField;
+ break;
+ case NonStaticReferenceInStaticContext :
+ flag = IProblem.NonStaticFieldFromStaticInvocation;
+ break;
+ case NonStaticReferenceInConstructorInvocation :
+ flag = IProblem.InstanceFieldDuringConstructorInvocation;
+ break;
+ case InheritedNameHidesEnclosingName :
+ flag = IProblem.InheritedFieldHidesEnclosingName;
+ break;
+ case NoError : // 0
+ default :
+ needImplementation(); // want to fail to see why we were here...
+ break;
+ }
+ this.handle(
+ flag,
+ new String[] {CharOperation.toString(CharOperation.subarray(nameRef.tokens, 0, index + 1))},
+ nameRef.sourceStart,
+ nameRef.sourceEnd);
+}
+public void invalidMethod(MessageSend messageSend, MethodBinding method) {
+ // CODE should be UPDATED according to error coding in the different method binding errors
+ // The different targetted errors should be :
+ // UndefinedMethod
+ // NotVisibleMethod
+ // AmbiguousMethod
+ // InheritedNameHidesEnclosingName
+ // InstanceMethodDuringConstructorInvocation
+ // StaticMethodRequested
+
+ int flag = IProblem.UndefinedMethod; //default...
+ switch (method.problemId()) {
+ case NotFound :
+ flag = IProblem.UndefinedMethod;
+ break;
+ case NotVisible :
+ flag = IProblem.NotVisibleMethod;
+ break;
+ case Ambiguous :
+ flag = IProblem.AmbiguousMethod;
+ break;
+ case InheritedNameHidesEnclosingName :
+ flag = IProblem.InheritedMethodHidesEnclosingName;
+ break;
+ case NonStaticReferenceInConstructorInvocation :
+ flag = IProblem.InstanceMethodDuringConstructorInvocation;
+ break;
+ case NonStaticReferenceInStaticContext :
+ flag = IProblem.StaticMethodRequested;
+ break;
+ case NoError : // 0
+ default :
+ needImplementation(); // want to fail to see why we were here...
+ break;
+ }
+
+ if (flag == IProblem.UndefinedMethod) {
+ ProblemMethodBinding problemMethod = (ProblemMethodBinding) method;
+ if (problemMethod.closestMatch != null) {
+ this.handle(
+ IProblem.ParameterMismatch,
+ new String[] {
+ new String(problemMethod.closestMatch.declaringClass.readableName()),
+ new String(problemMethod.closestMatch.selector),
+ parametersAsString(problemMethod.closestMatch),
+ parametersAsString(method)},
+ (int) (messageSend.nameSourcePosition >>> 32),
+ (int) messageSend.nameSourcePosition);
+ return;
+ }
+ }
+
+ this.handle(
+ flag,
+ new String[] {
+ new String(method.declaringClass.readableName()),
+ new String(method.selector), parametersAsString(method)},
+ (int) (messageSend.nameSourcePosition >>> 32),
+ (int) messageSend.nameSourcePosition);
+}
+public void invalidNullToSynchronize(Expression expression) {
+ this.handle(
+ IProblem.InvalidNullToSynchronized,
+ new String[0],
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void invalidOperator(BinaryExpression expression, TypeBinding leftType, TypeBinding rightType) {
+ this.handle(
+ IProblem.InvalidOperator,
+ new String[] {
+ expression.operatorToString(),
+ new String(leftType.readableName()) + ", " + new String(rightType.readableName())}, //$NON-NLS-1$
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void invalidOperator(CompoundAssignment assign, TypeBinding leftType, TypeBinding rightType) {
+ this.handle(
+ IProblem.InvalidOperator,
+ new String[] {
+ assign.operatorToString(),
+ new String(leftType.readableName()) + ", " + new String(rightType.readableName())}, //$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())},
+ expression.sourceStart,
+ expression.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())},
+ 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())},
+ superinterfaceRef.sourceStart,
+ superinterfaceRef.sourceEnd);
+}
+public void invalidType(AstNode location, TypeBinding type) {
+ int flag = IProblem.UndefinedType; // default
+ switch (type.problemId()) {
+ case NotFound :
+ flag = IProblem.UndefinedType;
+ break;
+ case NotVisible :
+ flag = IProblem.NotVisibleType;
+ break;
+ case Ambiguous :
+ flag = IProblem.AmbiguousType;
+ break;
+ case InternalNameProvided :
+ flag = IProblem.InternalTypeNameProvided;
+ break;
+ case InheritedNameHidesEnclosingName :
+ flag = IProblem.InheritedTypeHidesEnclosingName;
+ break;
+ case NoError : // 0
+ default :
+ needImplementation(); // want to fail to see why we were here...
+ break;
+ }
+
+ this.handle(
+ flag,
+ new String[] {new String(type.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void invalidTypeReference(Expression expression) {
+ this.handle(
+ IProblem.InvalidTypeExpression,
+ new String[0],
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void invalidTypeToSynchronize(Expression expression, TypeBinding type) {
+ this.handle(
+ IProblem.InvalidTypeToSynchronized,
+ new String[] {new String(type.readableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void invalidUnaryExpression(Expression expression) {
+ this.handle(
+ IProblem.InvalidUnaryExpression,
+ new String[0],
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void isClassPathCorrect(char[][] wellKnownTypeName, CompilationUnitDeclaration compUnitDecl) {
+ referenceContext = compUnitDecl;
+ this.handle(
+ IProblem.IsClassPathCorrect,
+ new String[] {CharOperation.toString(wellKnownTypeName)},
+ AbortCompilation | Error,
+ compUnitDecl == null ? 0 : compUnitDecl.sourceStart,
+ compUnitDecl == null ? 1 : compUnitDecl.sourceEnd);
+}
+public void maskedExceptionHandler(ReferenceBinding exceptionType, AstNode location) {
+ this.handle(
+ IProblem.MaskedCatch,
+ new String[0],
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void methodNeedingAbstractModifier(MethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.MethodRequiresBody,
+ new String[0],
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void methodNeedingNoBody(MethodDeclaration methodDecl) {
+ this.handle(
+ ((methodDecl.modifiers & CompilerModifiers.AccNative) != 0) ? IProblem.BodyForNativeMethod : IProblem.BodyForAbstractMethod,
+ new String[0],
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void methodWithConstructorName(MethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.MethodButWithConstructorName,
+ new String[0],
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void missingEnclosingInstanceSpecification(ReferenceBinding enclosingType, AstNode location) {
+ boolean insideConstructorCall =
+ (location instanceof ExplicitConstructorCall)
+ && (((ExplicitConstructorCall) location).accessMode == ExplicitConstructorCall.ImplicitSuper);
+
+ this.handle(
+ insideConstructorCall
+ ? IProblem.MissingEnclosingInstanceForConstructorCall
+ : IProblem.MissingEnclosingInstance,
+ new String[] {new String(enclosingType.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void missingReturnType(AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.MissingReturnType,
+ new String[0],
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void mustDefineDimensionsOrInitializer(ArrayAllocationExpression expression) {
+ this.handle(
+ IProblem.MustDefineEitherDimensionExpressionsOrInitializer,
+ new String[0],
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void mustSpecifyPackage(CompilationUnitDeclaration compUnitDecl) {
+ this.handle(
+ IProblem.MustSpecifyPackage,
+ new String[] {new String(compUnitDecl.getFileName())},
+ 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)},
+ messageSend.sourceStart,
+ messageSend.sourceEnd);
+}
+public void nativeMethodsCannotBeStrictfp(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.NativeMethodsCannotBeStrictfp,
+ new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+ 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)},
+ 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)},
+ 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)
+ },
+ location.sourceStart,
+ location.sourceEnd);
+ else
+ this.handle(
+ IProblem.NeedToEmulateMethodAccess,
+ new String[] {
+ new String(method.declaringClass.readableName()),
+ new String(method.selector),
+ parametersAsString(method)
+ },
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void nestedClassCannotDeclareInterface(TypeDeclaration typeDecl) {
+ this.handle(
+ IProblem.CannotDefineInterfaceInLocalType,
+ new String[] {new String(typeDecl.name)},
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd);
+}
+public void noMoreAvailableSpaceForArgument(LocalVariableBinding local, AstNode location) {
+ this.handle(
+ IProblem.TooManyArgumentSlots,
+ new String[]{ new String(local.name) },
+ Abort | Error,
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void noMoreAvailableSpaceForLocal(LocalVariableBinding local, AstNode location) {
+ this.handle(
+ IProblem.TooManyLocalVariableSlots,
+ new String[]{ new String(local.name) },
+ Abort | Error,
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void notCompatibleTypesError(EqualExpression expression, TypeBinding leftType, TypeBinding rightType) {
+ this.handle(
+ IProblem.IncompatibleTypesInEqualityOperator,
+ new String[] {new String(leftType.readableName()), new String(rightType.readableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void notCompatibleTypesError(InstanceOfExpression expression, TypeBinding leftType, TypeBinding rightType) {
+ this.handle(
+ IProblem.IncompatibleTypesInConditionalOperator,
+ new String[] {new String(leftType.readableName()), new String(rightType.readableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void operatorOnlyValidOnNumericType(CompoundAssignment assignment, TypeBinding leftType, TypeBinding rightType) {
+ this.handle(
+ IProblem.TypeMismatch,
+ new String[] {new String(leftType.readableName()), new String(rightType.readableName())},
+ assignment.sourceStart,
+ assignment.sourceEnd);
+}
+public void overridesDeprecatedMethod(MethodBinding currentMethod, MethodBinding inheritedMethod) {
+ this.handle(
+ IProblem.OverridingDeprecatedMethod,
+ new String[] {new String(inheritedMethod.declaringClass.readableName())},
+ currentMethod.sourceStart(),
+ currentMethod.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())},
+ localMethod.sourceStart(),
+ localMethod.sourceEnd());
+}
+public void packageCollidesWithType(CompilationUnitDeclaration compUnitDecl) {
+ this.handle(
+ IProblem.PackageCollidesWithType,
+ new String[] {CharOperation.toString(compUnitDecl.currentPackage.tokens)},
+ compUnitDecl.currentPackage.sourceStart,
+ compUnitDecl.currentPackage.sourceEnd);
+}
+public void packageIsNotExpectedPackage(CompilationUnitDeclaration compUnitDecl) {
+ this.handle(
+ IProblem.PackageIsNotExpectedPackage,
+ new String[] {CharOperation.toString(compUnitDecl.compilationResult.compilationUnit.getPackageName())},
+ 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();
+}
+public void parseError(
+ int startPosition,
+ int endPosition,
+ char[] currentTokenSource,
+ String errorTokenName,
+ String[] possibleTokens) {
+
+ if (possibleTokens.length == 0) { //no suggestion available
+ if (isKeyword(currentTokenSource)) {
+ this.handle(
+ IProblem.ParsingErrorOnKeywordNoSuggestion,
+ new String[] {new String(currentTokenSource)},
+ // this is the current -invalid- token position
+ startPosition,
+ endPosition);
+ return;
+ } else {
+ this.handle(
+ IProblem.ParsingErrorNoSuggestion,
+ new String[] {errorTokenName},
+ // 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(currentTokenSource)) {
+ this.handle(
+ IProblem.ParsingErrorOnKeyword,
+ new String[] {new String(currentTokenSource), list.toString()},
+ // this is the current -invalid- token position
+ startPosition,
+ endPosition);
+ return;
+ }
+ //extract the literal when it's a literal
+ if ((errorTokenName.equals("IntegerLiteral")) || //$NON-NLS-1$
+ (errorTokenName.equals("LongLiteral")) || //$NON-NLS-1$
+ (errorTokenName.equals("FloatingPointLiteral")) || //$NON-NLS-1$
+ (errorTokenName.equals("DoubleLiteral")) || //$NON-NLS-1$
+ (errorTokenName.equals("StringLiteral")) || //$NON-NLS-1$
+ (errorTokenName.equals("CharacterLiteral")) || //$NON-NLS-1$
+ (errorTokenName.equals("Identifier"))) { //$NON-NLS-1$
+ errorTokenName = new String(currentTokenSource);
+ }
+
+ this.handle(
+ IProblem.ParsingError,
+ new String[] {errorTokenName, list.toString()},
+ // this is the current -invalid- token position
+ startPosition,
+ endPosition);
+}
+public void publicClassMustMatchFileName(CompilationUnitDeclaration compUnitDecl, TypeDeclaration typeDecl) {
+ this.referenceContext = typeDecl; // report the problem against the type not the entire compilation unit
+ this.handle(
+ IProblem.PublicClassMustMatchFileName,
+ new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)},
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ compUnitDecl.compilationResult);
+}
+/*
+ * Flag all constructors involved in a cycle, we know we have a cycle.
+ */
+public void recursiveConstructorInvocation(TypeDeclaration typeDeclaration) {
+
+ // propagate the reference count, negative counts means leading to a super constructor invocation (directly or indirectly)
+ boolean hasChanged;
+ AbstractMethodDeclaration[] methods = typeDeclaration.methods;
+ int max = methods.length;
+ do {
+ hasChanged = false;
+ for(int i = 0; i < max; i++){
+ if (methods[i].isConstructor()){
+ ConstructorDeclaration constructor = (ConstructorDeclaration) methods[i];
+ if (constructor.referenceCount > 0){
+ ConstructorDeclaration targetConstructor = constructor.constructorCall == null
+ ? null
+ : (ConstructorDeclaration)(typeDeclaration.declarationOf(constructor.constructorCall.binding));
+ if ((targetConstructor == null) || (targetConstructor.referenceCount < 0)){
+ hasChanged = true;
+ constructor.referenceCount = -1;
+ }
+ }
+ }
+ }
+ } while (hasChanged);
+
+ // all remaining constructors with a positive count are still involved in a cycle
+ for(int i = 0; i < max; i++){
+ if (methods[i].isConstructor()){
+ ConstructorDeclaration constructor = (ConstructorDeclaration) methods[i];
+ if (constructor.referenceCount > 0){
+ this.referenceContext = constructor;
+ this.handle(
+ IProblem.RecursiveConstructorInvocation,
+ new String[] {
+ new String(constructor.constructorCall.binding.declaringClass.readableName()),
+ parametersAsString(constructor.constructorCall.binding)
+ },
+ constructor.constructorCall.sourceStart,
+ constructor.constructorCall.sourceEnd);
+ }
+ }
+ }
+}
+public void redefineArgument(Argument arg) {
+ this.handle(
+ IProblem.RedefinedArgument,
+ new String[] {new String(arg.name)},
+ arg.sourceStart,
+ arg.sourceEnd);
+}
+public void redefineLocal(LocalDeclaration localDecl) {
+ this.handle(
+ IProblem.RedefinedLocal,
+ new String[] {new String(localDecl.name)},
+ localDecl.sourceStart,
+ localDecl.sourceEnd);
+}
+public void referenceMustBeArrayTypeAt(TypeBinding arrayType, ArrayReference arrayRef) {
+ this.handle(
+ IProblem.ArrayReferenceRequired,
+ new String[] {new String(arrayType.readableName())},
+ arrayRef.sourceStart,
+ arrayRef.sourceEnd);
+}
+public void returnTypeCannotBeVoidArray(SourceTypeBinding type, MethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.ReturnTypeCannotBeVoidArray,
+ new String[] {new String(methodDecl.selector)},
+ 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())},
+ 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;
+
+ this.handle(
+ flag,
+ flag == IProblem.ParsingErrorNoSuggestion
+ ? new String[] {errorTokenName}
+ : new String[0],
+ // 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())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void signalNoImplicitStringConversionForCharArrayExpression(Expression expression) {
+ this.handle(
+ IProblem.NoImplicitStringConversionForCharArrayExpression,
+ new String[] {},
+ 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())},
+ 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())},
+ currentMethod.sourceStart(),
+ currentMethod.sourceEnd());
+}
+public void staticFieldAccessToNonStaticVariable(FieldReference fieldRef, FieldBinding field) {
+ this.handle(
+ IProblem.NonStaticFieldFromStaticInvocation,
+ new String[] {new String(field.readableName())},
+ fieldRef.sourceStart,
+ fieldRef.sourceEnd);
+}
+public void staticFieldAccessToNonStaticVariable(QualifiedNameReference nameRef, FieldBinding field){
+ this.handle(
+ IProblem.NonStaticFieldFromStaticInvocation,
+ new String[] { new String(field.readableName())},
+ nameRef.sourceStart,
+ nameRef.sourceEnd);
+}
+public void staticFieldAccessToNonStaticVariable(SingleNameReference nameRef, FieldBinding field) {
+ this.handle(
+ IProblem.NonStaticFieldFromStaticInvocation,
+ new String[] {new String(field.readableName())},
+ nameRef.sourceStart,
+ nameRef.sourceEnd);
+}
+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())},
+ type.sourceStart(),
+ type.sourceEnd());
+}
+public void stringConstantIsExceedingUtf8Limit(AstNode location) {
+ this.handle(
+ IProblem.StringConstantIsExceedingUtf8Limit,
+ new String[0],
+ 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())},
+ superclassRef.sourceStart,
+ superclassRef.sourceEnd);
+}
+public void superinterfaceMustBeAnInterface(SourceTypeBinding type, TypeDeclaration typeDecl, ReferenceBinding superType) {
+ this.handle(
+ IProblem.SuperInterfaceMustBeAnInterface,
+ new String[] {new String(superType.readableName()), new String(type.sourceName())},
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd);
+}
+public void typeCastError(CastExpression expression, TypeBinding leftType, TypeBinding rightType) {
+ this.handle(
+ IProblem.IllegalCast,
+ new String[] {new String(rightType.readableName()), new String(leftType.readableName())},
+ 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
+ this.handle(
+ IProblem.TypeCollidesWithPackage,
+ new String[] {new String(compUnitDecl.getFileName()), new String(typeDecl.name)},
+ typeDecl.sourceStart,
+ typeDecl.sourceEnd,
+ compUnitDecl.compilationResult);
+}
+public void typeMismatchError(TypeBinding resultType, TypeBinding expectedType, AstNode location) {
+ this.handle(
+ IProblem.TypeMismatch,
+ new String[] {new String(resultType.readableName()), new String(expectedType.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void typeMismatchErrorActualTypeExpectedType(Expression expression, TypeBinding constantType, TypeBinding expectedType) {
+ this.handle(
+ IProblem.TypeMismatch,
+ new String[] {new String(constantType.readableName()), new String(expectedType.readableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void undefinedLabel(BranchStatement statement) {
+ this.handle(
+ IProblem.UndefinedLabel,
+ new String[] {new String(statement.label)},
+ statement.sourceStart,
+ statement.sourceEnd);
+}
+public void unexpectedStaticModifierForField(SourceTypeBinding type, FieldDeclaration fieldDecl) {
+ this.handle(
+ IProblem.UnexpectedStaticModifierForField,
+ new String[] {fieldDecl.name()},
+ fieldDecl.sourceStart,
+ fieldDecl.sourceEnd);
+}
+public void unexpectedStaticModifierForMethod(ReferenceBinding type, AbstractMethodDeclaration methodDecl) {
+ this.handle(
+ IProblem.UnexpectedStaticModifierForMethod,
+ new String[] {new String(type.sourceName()), new String(methodDecl.selector)},
+ methodDecl.sourceStart,
+ methodDecl.sourceEnd);
+}
+public void unhandledException(TypeBinding exceptionType, AstNode location) {
+
+ boolean insideDefaultConstructor =
+ (referenceContext instanceof ConstructorDeclaration)
+ && ((ConstructorDeclaration)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())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void uninitializedBlankFinalField(FieldBinding binding, AstNode location) {
+ this.handle(
+ IProblem.UninitializedBlankFinalField,
+ new String[] {new String(binding.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void uninitializedLocalVariable(LocalVariableBinding binding, AstNode location) {
+ this.handle(
+ IProblem.UninitializedLocalVariable,
+ new String[] {new String(binding.readableName())},
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void unmatchedBracket(int position, ReferenceContext context, CompilationResult compilationResult) {
+
+ this.handle(
+ IProblem.UnmatchedBracket,
+ new String[] {},
+ position,
+ position,
+ context,
+ compilationResult);
+}
+public void unnecessaryEnclosingInstanceSpecification(Expression expression, ReferenceBinding targetType) {
+ this.handle(
+ IProblem.IllegalEnclosingInstanceSpecification,
+ new String[]{ new String(targetType.readableName())},
+ expression.sourceStart,
+ expression.sourceEnd);
+}
+public void unreachableCode(Statement statement) {
+ this.handle(
+ IProblem.CodeCannotBeReached,
+ new String[0],
+ statement.sourceStart,
+ statement.sourceEnd);
+}
+public void unreachableExceptionHandler(ReferenceBinding exceptionType, AstNode location) {
+ this.handle(
+ IProblem.UnreachableCatch,
+ new String[0],
+ location.sourceStart,
+ location.sourceEnd);
+}
+public void unresolvableReference(NameReference nameRef, Binding binding) {
+ int severity = Error;
+/* also need to check that the searchedType is the receiver type
+ if (binding instanceof ProblemBinding) {
+ ProblemBinding problem = (ProblemBinding) binding;
+ if (problem.searchType != null && problem.searchType.isHierarchyInconsistent())
+ severity = SecondaryError;
+ }
+*/
+ this.handle(
+ IProblem.UndefinedName,
+ new String[] {new String(binding.readableName())},
+ severity,
+ nameRef.sourceStart,
+ nameRef.sourceEnd);
+}
+public void unusedArgument(LocalDeclaration localDecl) {
+ this.handle(
+ IProblem.ArgumentIsNeverUsed,
+ new String[] {localDecl.name()},
+ localDecl.sourceStart,
+ localDecl.sourceEnd);
+}
+public void unusedImport(ImportReference importRef) {
+ this.handle(
+ IProblem.UnusedImport,
+ new String[] { CharOperation.toString(importRef.tokens) },
+ importRef.sourceStart,
+ importRef.sourceEnd);
+}
+public void unusedLocalVariable(LocalDeclaration localDecl) {
+ this.handle(
+ IProblem.LocalVariableIsNeverUsed,
+ new String[] {localDecl.name()},
+ localDecl.sourceStart,
+ localDecl.sourceEnd);
+}
+
+public void useAssertAsAnIdentifier(int sourceStart, int sourceEnd) {
+ this.handle(
+ IProblem.UseAssertAsAnIdentifier,
+ new String[0],
+ sourceStart,
+ sourceEnd);
+}
+
+public void variableTypeCannotBeVoid(AbstractVariableDeclaration varDecl) {
+ this.handle(
+ IProblem.VariableTypeCannotBeVoid,
+ new String[] {new String(varDecl.name)},
+ varDecl.sourceStart,
+ varDecl.sourceEnd);
+}
+public void variableTypeCannotBeVoidArray(AbstractVariableDeclaration varDecl) {
+ this.handle(
+ IProblem.VariableTypeCannotBeVoidArray,
+ new String[] {new String(varDecl.name)},
+ 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())},
+ currentMethod.sourceStart(),
+ currentMethod.sourceEnd());
+}
+public void wrongSequenceOfExceptionTypesError(TryStatement statement, int under, int upper) {
+ //the two catch block under and upper are in an incorrect order.
+ //under should be define BEFORE upper in the source
+
+ //notice that the compiler could arrange automatically the
+ //correct order - and the only error would be on cycle ....
+ //on this one again , java is compiler-driven instead of being
+ //user-driven .....
+
+ TypeReference typeRef = statement.catchArguments[under].type;
+ this.handle(
+ IProblem.UnreachableCatch,
+ new String[0],
+ typeRef.sourceStart,
+ typeRef.sourceEnd);
+}
+
+public void nonExternalizedStringLiteral(AstNode location) {
+ this.handle(
+ IProblem.NonExternalizedStringLiteral,
+ new String[] {},
+ location.sourceStart,
+ location.sourceEnd);
+}
+
+public void noMoreAvailableSpaceInConstantPool(TypeDeclaration typeDeclaration) {
+ this.handle(
+ IProblem.TooManyConstantsInConstantPool,
+ new String[]{ new String(typeDeclaration.binding.readableName())},
+ Abort | Error,
+ typeDeclaration.sourceStart,
+ typeDeclaration.sourceEnd);
+}
+
+private boolean isKeyword(char[] tokenSource) {
+ /*
+ * This code is heavily grammar dependant
+ */
+
+ if (tokenSource == null) {
+ return false;
+ }
+ try {
+ Scanner scanner = new Scanner();
+ scanner.setSource(tokenSource);
+ int token = scanner.getNextToken();
+ char[] currentKeyword;
+ try {
+ currentKeyword = scanner.getCurrentIdentifierSource();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ return false;
+ }
+ int nextToken= scanner.getNextToken();
+ if (nextToken == ITerminalSymbols.TokenNameEOF
+ && scanner.startPosition == scanner.source.length) { // to handle case where we had an ArrayIndexOutOfBoundsException
+ // while reading the last token
+ switch(token) {
+ case Scanner.TokenNameERROR:
+ if (CharOperation.equals("goto".toCharArray(), currentKeyword) ||CharOperation.equals("const".toCharArray(), currentKeyword)) { //$NON-NLS-1$ //$NON-NLS-2$
+ return true;
+ } else {
+ return false;
+ }
+ case Scanner.TokenNameas:
+ case Scanner.TokenNameand:
+// case Scanner.TokenNameabstract:
+// case Scanner.TokenNameassert:
+// case Scanner.TokenNamebyte:
+ case Scanner.TokenNamebreak:
+// case Scanner.TokenNameboolean:
+ case Scanner.TokenNamecase:
+// case Scanner.TokenNamechar:
+// case Scanner.TokenNamecatch:
+ case Scanner.TokenNameclass:
+ case Scanner.TokenNamecontinue:
+ case Scanner.TokenNamedo:
+// case Scanner.TokenNamedouble:
+ case Scanner.TokenNamedefault:
+ case Scanner.TokenNameecho:
+ case Scanner.TokenNameendif:
+ case Scanner.TokenNameendfor:
+ case Scanner.TokenNameendforeach:
+ case Scanner.TokenNameendswitch:
+ case Scanner.TokenNameendwhile:
+ case Scanner.TokenNameelse:
+ case Scanner.TokenNameextends:
+ case Scanner.TokenNamefor:
+// case Scanner.TokenNamefinal:
+// case Scanner.TokenNamefloat:
+ case Scanner.TokenNamefalse:
+// case Scanner.TokenNamefinally:
+ case Scanner.TokenNameglobal:
+ case Scanner.TokenNameif:
+ case Scanner.TokenNameinclude:
+ case Scanner.TokenNameinclude_once:
+// case Scanner.TokenNameint:
+// case Scanner.TokenNameimport:
+// case Scanner.TokenNameinterface:
+// case Scanner.TokenNameimplements:
+// case Scanner.TokenNameinstanceof:
+ case Scanner.TokenNamelist:
+// case Scanner.TokenNamelong:
+ case Scanner.TokenNamenew:
+ case Scanner.TokenNamenull:
+// case Scanner.TokenNamenative:
+ case Scanner.TokenNameold_function:
+ case Scanner.TokenNameor:
+ case Scanner.TokenNameprint:
+// case Scanner.TokenNamepublic:
+// case Scanner.TokenNamepackage:
+// case Scanner.TokenNameprivate:
+// case Scanner.TokenNameprotected:
+ case Scanner.TokenNamerequire:
+ case Scanner.TokenNamerequire_once:
+ case Scanner.TokenNamereturn:
+// case Scanner.TokenNameshort:
+// case Scanner.TokenNamesuper:
+ case Scanner.TokenNamestatic:
+ case Scanner.TokenNameswitch:
+// case Scanner.TokenNamestrictfp:
+// case Scanner.TokenNamesynchronized:
+// case Scanner.TokenNametry:
+// case Scanner.TokenNamethis:
+ case Scanner.TokenNametrue:
+// case Scanner.TokenNamethrow:
+// case Scanner.TokenNamethrows:
+// case Scanner.TokenNametransient:
+ case Scanner.TokenNamevar:
+// case Scanner.TokenNamevoid:
+// case Scanner.TokenNamevolatile:
+ case Scanner.TokenNamewhile:
+ case Scanner.TokenNamexor:
+ return true;
+ default:
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ catch (InvalidInputException e) {
+ return false;
+ }
+
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.problem;
+
+/*
+ * Special unchecked exception type used
+ * to denote implementation that should never be reached.
+ *
+ * (internal only)
+ */
+public class ShouldNotImplement extends RuntimeException {
+public ShouldNotImplement(){
+}
+public ShouldNotImplement(String message){
+ super(message);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.util;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.TypeConstants;
+
+public final class CharOperation {
+
+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;
+}
+
+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][];
+/* if we do not trust System.arraycopy on our VM with char[][]'s
+ int i;
+ for (i = 0; i < length1; i++)
+ result[i] = first[i];
+ for (int j = 0; j < length2; j++)
+ result[i++] = second[j];
+*/
+ System.arraycopy(first, 0, result, 0, length1);
+ System.arraycopy(second, 0, result, length1, length2);
+ return result;
+}
+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][];
+/* if we do not trust System.arraycopy on our VM with char[][]'s
+ for (int i = 0; i < length; i++)
+ result[i] = first[i];
+*/
+ System.arraycopy(first, 0, result, 0, length);
+ result[length] = second;
+ return result;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+public static final char[] concatWith(char[][] array, char separator) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return TypeConstants.NoChar;
+
+ 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 TypeConstants.NoChar;
+ 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;
+}
+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;
+}
+public static final boolean contains(char character, char[] array) {
+ for (int i = array.length; --i >= 0;)
+ if (array[i] == character)
+ return true;
+ return false;
+}
+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;
+}
+
+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;
+}
+
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+public static final int lastIndexOf(char toBeFound, char[] array) {
+ for (int i = array.length; --i >= 0;)
+ if (toBeFound == array[i])
+ return i;
+ return -1;
+}
+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;
+}
+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;
+}
+/**
+ * Answer the last portion of a name given a separator
+ * e.g. lastSegment("java.lang.Object".toCharArray(),'.') --> Object
+ */
+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);
+}
+/**
+ * char[] pattern matching, accepting wild-cards '*'.
+ *
+ * When not case sensitive, the pattern is assumed to already be lowercased, the
+ * name will be lowercased character per character as comparing.
+ */
+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 '*'
+ int iPattern = 0, patternLength = pattern.length;
+ int iName = 0, nameLength = name.length;
+
+ /* check first segment */
+ char patternChar = 0;
+ while ((iPattern < patternLength) && (patternChar = pattern[iPattern]) != '*'){
+ if (iName == nameLength) return false;
+ if (patternChar != (isCaseSensitive
+ ? name[iName]
+ : Character.toLowerCase(name[iName]))){
+ 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 < nameLength && iPattern < patternLength){
+ /* segment is ending */
+ if ((patternChar = pattern[iPattern]) == '*'){
+ segmentStart = ++iPattern; // skip start
+ prefixStart = iName;
+ continue checkSegment;
+ }
+ /* chech current name character */
+ if ((isCaseSensitive
+ ? name[iName]
+ : Character.toLowerCase(name[iName]))!= patternChar){
+ iPattern = segmentStart; // mismatch - restart current segment
+ iName = ++prefixStart;
+ continue checkSegment;
+ }
+ iName++;
+ iPattern++;
+ }
+
+ return (segmentStart == patternLength)
+ || (iName == nameLength && iPattern == patternLength)
+ || (iPattern == patternLength - 1 && pattern[iPattern] == '*');
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+}
+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;
+ }
+ }
+}
+
+/*
+ * Returns a char[] with substitutions. No side-effect is operated on the original
+ * array, in case no substitution happened, then the result might be the same as the
+ * original one.
+ *
+ */
+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;
+}
+
+public static final char[][] splitAndTrimOn(char divider, char[] array) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return TypeConstants.NoCharChar;
+
+ 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;
+}
+
+public static final char[][] splitOn(char divider, char[] array) {
+ int length = array == null ? 0 : array.length;
+ if (length == 0)
+ return TypeConstants.NoCharChar;
+
+ 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;
+}
+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 TypeConstants.NoCharChar;
+
+ 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 + 1];
+ System.arraycopy(array, last, split[currentWord], 0, end - last + 1);
+ return split;
+}
+public static final boolean startsWith(char[] array, char[] toBeFound) {
+ int i = toBeFound.length;
+ if (i > array.length)
+ return false;
+ while (--i >= 0)
+ if (toBeFound[i] != array[i])
+ return false;
+ return true;
+}
+/*
+ * copies from array[start] through array[end - 1] (does not copy array[end])
+ */
+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][];
+/* if we do not trust System.arraycopy on our VM with char[][]'s
+ for (int i = 0, s = start; s < end; i++, s++)
+ result[i] = array[s];
+*/
+ System.arraycopy(array, start, result, 0, end - start);
+ return result;
+}
+/*
+ * copies from array[start] through array[end - 1] (does not copy array[end])
+ */
+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.
+ * NOTE: if no conversion was necessary, then answers back the argument one.
+ */
+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;
+}
+
+/**
+ * Remove leading and trailing spaces
+ */
+final static public char[] trim(char[] chars){
+
+ if (chars == null) return null;
+
+ char[] result = chars;
+ 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;
+}
+final static public String toString(char[][] array) {
+ char[] result = concatWith(array, '.');
+ if (result == null)
+ return ""; //$NON-NLS-1$
+ return new String(result);
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.util;
+
+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();
+}
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+
+ 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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.util;
+
+/**
+ * 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.prefixEquals(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.prefixEquals(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.prefixEquals(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.prefixEquals(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;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.util;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.PackageBinding;
+
+public final class HashtableOfPackage {
+ // to avoid using Enumerations, walk the individual tables skipping nulls
+ public char[] keyTable[];
+ public PackageBinding valueTable[];
+
+ 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.prefixEquals(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.prefixEquals(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.prefixEquals(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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.util;
+
+import net.sourceforge.phpdt.internal.compiler.lookup.ReferenceBinding;
+
+public final class HashtableOfType {
+ // to avoid using Enumerations, walk the individual tables skipping nulls
+ public char[] keyTable[];
+ public ReferenceBinding valueTable[];
+
+ 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.prefixEquals(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.prefixEquals(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.prefixEquals(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;
+}
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.internal.compiler.util;
+
+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();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2000, 2001, 2002 International Business Machines Corp. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package net.sourceforge.phpdt.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;
+
+public class Util {
+
+ public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
+ public static char[] LINE_SEPARATOR_CHARS = LINE_SEPARATOR.toCharArray();
+ public final static char[] SUFFIX_class = ".class".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_CLASS = ".CLASS".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_java = ".java".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_JAVA = ".JAVA".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_jar = ".jar".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_JAR = ".JAR".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_zip = ".zip".toCharArray(); //$NON-NLS-1$
+ public final static char[] SUFFIX_ZIP = ".ZIP".toCharArray(); //$NON-NLS-1$
+
+ private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+ private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+
+ /* 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);
+ message = new String(messageWithNoDoubleQuotes);
+
+ if (bindings == null)
+ return message;
+
+ int length = message.length();
+ int start = -1;
+ int end = length;
+ StringBuffer output = new StringBuffer(80);
+ while (true) {
+ if ((end = message.indexOf('{', start)) > -1) {
+ output.append(message.substring(start + 1, end));
+ if ((start = message.indexOf('}', end)) > -1) {
+ int index = -1;
+ try {
+ index = Integer.parseInt(message.substring(end + 1, start));
+ output.append(bindings[index]);
+ } catch (NumberFormatException nfe) {
+ output.append(message.substring(end + 1, start + 1));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ } else {
+ output.append(message.substring(end, length));
+ break;
+ }
+ } else {
+ output.append(message.substring(start + 1, length));
+ break;
+ }
+ }
+ return output.toString();
+ }
+ /**
+ * Lookup the message with the given ID in this catalog
+ */
+ public static String bind(String id) {
+ return bind(id, (String[]) null);
+ }
+ /**
+ * Creates a NLS catalog for the given locale.
+ */
+ public static void relocalize() {
+ bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
+ }
+ /**
+ * 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) {
+ }
+ }
+ }
+ }
+ /**
+ * 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 Util.getInputStreamAsCharArray(stream, (int) file.length(), encoding);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+ /**
+ * 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 bytesRead = -1;
+ do {
+ int available = stream.available();
+
+ // resize contents if needed
+ if (contentsLength + available > contents.length) {
+ System.arraycopy(
+ contents,
+ 0,
+ contents = new byte[contentsLength + available],
+ 0,
+ contentsLength);
+ }
+
+ // read as many bytes as possible
+ bytesRead = stream.read(contents, contentsLength, available);
+
+ if (bytesRead > 0) {
+ // remember length of contents
+ contentsLength += bytesRead;
+ }
+ } while (bytesRead > 0);
+
+ // 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;
+ }
+ /**
+ * 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 = new char[0];
+ int contentsLength = 0;
+ int charsRead = -1;
+ do {
+ int available = stream.available();
+
+ // resize contents if needed
+ if (contentsLength + available > contents.length) {
+ System.arraycopy(
+ contents,
+ 0,
+ contents = new char[contentsLength + available],
+ 0,
+ contentsLength);
+ }
+
+ // read as many chars as possible
+ charsRead = reader.read(contents, contentsLength, available);
+
+ if (charsRead > 0) {
+ // remember length of contents
+ contentsLength += charsRead;
+ }
+ } while (charsRead > 0);
+
+ // resize contents if necessary
+ if (contentsLength < contents.length) {
+ System.arraycopy(
+ contents,
+ 0,
+ 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);
+ }
+ // 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, 0, (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) {
+ }
+ }
+ }
+ }
+ /**
+ * 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(".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;
+ }
+}
\ No newline at end of file