### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java,v retrieving revision 1.13 diff -u -r1.13 CodeSnippetTypeDeclaration.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java 10 May 2006 18:03:48 -0000 1.13 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java 24 Jan 2007 18:56:58 -0000 @@ -39,21 +39,18 @@ ClassFile classFile = new CodeSnippetClassFile(this.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 (this.binding.isMemberType()) - classFile.recordEnclosingTypeAttributes(this.binding); - if (this.binding.isLocalType()) { - enclosingClassFile.recordNestedLocalAttribute(this.binding); - classFile.recordNestedLocalAttribute(this.binding); + if (this.binding.isMemberType()) { + classFile.recordInnerClasses(this.binding); + } else if (this.binding.isLocalType()) { + enclosingClassFile.recordInnerClasses(this.binding); + classFile.recordInnerClasses(this.binding); } + if (this.memberTypes != null) { for (int i = 0, max = this.memberTypes.length; i < max; i++) { - // record the inner type inside its own .class file to be able - // to generate inner classes attributes - classFile.recordNestedMemberAttribute(this.memberTypes[i].binding); - this.memberTypes[i].generateCode(this.scope, classFile); + TypeDeclaration memberType = this.memberTypes[i]; + classFile.recordInnerClasses(memberType.binding); + memberType.generateCode(this.scope, classFile); } } // generate all methods Index: eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java,v retrieving revision 1.39 diff -u -r1.39 CodeSnippetClassFile.java --- eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java 23 Aug 2006 16:32:56 -0000 1.39 +++ eval/org/eclipse/jdt/internal/eval/CodeSnippetClassFile.java 24 Jan 2007 18:56:58 -0000 @@ -88,7 +88,7 @@ // now we continue to generate the bytes inside the contents array this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); this.contents[this.contentsOffset++] = (byte) accessFlags; - int classNameIndex = this.constantPool.literalIndexForType(aType.constantPoolName()); + int classNameIndex = this.constantPool.literalIndexForType(aType); this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) classNameIndex; int superclassNameIndex; @@ -96,7 +96,7 @@ superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); } else { superclassNameIndex = - (aType.superclass == null ? 0 : this.constantPool.literalIndexForType(aType.superclass.constantPoolName())); + (aType.superclass == null ? 0 : this.constantPool.literalIndexForType(aType.superclass)); } this.contents[this.contentsOffset++] = (byte) (superclassNameIndex >> 8); this.contents[this.contentsOffset++] = (byte) superclassNameIndex; @@ -106,13 +106,12 @@ this.contents[this.contentsOffset++] = (byte) interfacesCount; if (superInterfacesBinding != null) { for (int i = 0; i < interfacesCount; i++) { - int interfaceIndex = this.constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName()); + int interfaceIndex = this.constantPool.literalIndexForType(superInterfacesBinding[i]); this.contents[this.contentsOffset++] = (byte) (interfaceIndex >> 8); this.contents[this.contentsOffset++] = (byte) interfaceIndex; } } this.produceAttributes = this.referenceBinding.scope.compilerOptions().produceDebugAttributes; - this.innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE]; this.creatingProblemType = creatingProblemType; if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.codeStream = new StackMapFrameCodeStream(this); @@ -141,8 +140,9 @@ ClassFile classFile = new CodeSnippetClassFile(typeBinding, null, true); // inner attributes - if (typeBinding.isMemberType()) - classFile.recordEnclosingTypeAttributes(typeBinding); + if (typeBinding.isNestedType()) { + classFile.recordInnerClasses(typeBinding); + } // add its fields FieldBinding[] fields = typeBinding.fields(); @@ -195,7 +195,6 @@ 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); } } Index: compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java,v retrieving revision 1.29 diff -u -r1.29 TagBits.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java 10 Jan 2007 17:56:47 -0000 1.29 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java 24 Jan 2007 18:56:58 -0000 @@ -31,6 +31,7 @@ // for the type cycle hierarchy check used by ClassScope long BeginHierarchyCheck = ASTNode.Bit9; // type long EndHierarchyCheck = ASTNode.Bit10; // type + long ContainsNestedTypesInSignature = ASTNode.Bit10; // method long HasParameterAnnotations = ASTNode.Bit11; // method // test bit to see if default abstract methods were computed Index: compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java,v retrieving revision 1.86 diff -u -r1.86 MethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 27 Nov 2006 17:23:19 -0000 1.86 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java 24 Jan 2007 18:56:58 -0000 @@ -11,6 +11,7 @@ package org.eclipse.jdt.internal.compiler.lookup; import org.eclipse.jdt.core.compiler.CharOperation; +import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; @@ -771,6 +772,141 @@ return signature; } +/* + * This method is used to record references to nested types inside the method signature. + * This is the one that must be used during code generation. + * + * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=171184 + */ +public final char[] signature(ClassFile classFile) { + if (signature != null) { + if ((this.tagBits & TagBits.ContainsNestedTypesInSignature) != 0) { + // we need to record inner classes references + boolean isConstructor = isConstructor(); + TypeBinding[] targetParameters = this.parameters; + boolean needSynthetics = isConstructor && declaringClass.isNestedType(); + if (needSynthetics) { + // take into account the synthetic argument type signatures as well + ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes(); + if (syntheticArgumentTypes != null) { + for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) { + ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i]; + if (syntheticArgumentType.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(syntheticArgumentType); + } + } + } + + if (this instanceof SyntheticMethodBinding) { + targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters; + } + } + + if (targetParameters != Binding.NO_PARAMETERS) { + for (int i = 0; i < targetParameters.length; i++) { + TypeBinding targetParameter = targetParameters[i]; + TypeBinding leafTargetParameterType = targetParameter.leafComponentType(); + if (leafTargetParameterType.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(leafTargetParameterType); + } + } + } + if (needSynthetics) { + // move the extra padding arguments of the synthetic constructor invocation to the end + for (int i = targetParameters.length, extraLength = parameters.length; i < extraLength; i++) { + TypeBinding parameter = parameters[i]; + TypeBinding leafParameterType = parameter.leafComponentType(); + if (leafParameterType.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(leafParameterType); + } + } + } + if (this.returnType != null) { + TypeBinding ret = this.returnType.leafComponentType(); + if (ret.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(ret); + } + } + } + return signature; + } + + StringBuffer buffer = new StringBuffer(parameters.length + 1 * 20); + buffer.append('('); + + TypeBinding[] targetParameters = this.parameters; + boolean isConstructor = isConstructor(); + if (isConstructor && declaringClass.isEnum()) { // insert String name,int ordinal + buffer.append(ConstantPool.JavaLangStringSignature); + buffer.append(TypeBinding.INT.signature()); + } + boolean needSynthetics = isConstructor && declaringClass.isNestedType(); + if (needSynthetics) { + // take into account the synthetic argument type signatures as well + ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes(); + if (syntheticArgumentTypes != null) { + for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) { + ReferenceBinding syntheticArgumentType = syntheticArgumentTypes[i]; + if (syntheticArgumentType.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(syntheticArgumentType); + } + buffer.append(syntheticArgumentType.signature()); + } + } + + if (this instanceof SyntheticMethodBinding) { + targetParameters = ((SyntheticMethodBinding)this).targetMethod.parameters; + } + } + + if (targetParameters != Binding.NO_PARAMETERS) { + for (int i = 0; i < targetParameters.length; i++) { + TypeBinding targetParameter = targetParameters[i]; + TypeBinding leafTargetParameterType = targetParameter.leafComponentType(); + if (leafTargetParameterType.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(leafTargetParameterType); + } + buffer.append(targetParameter.signature()); + } + } + if (needSynthetics) { + SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass.syntheticOuterLocalVariables(); + int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length; + for (int i = 0; i < count; i++) { + buffer.append(syntheticOuterArguments[i].type.signature()); + } + // move the extra padding arguments of the synthetic constructor invocation to the end + for (int i = targetParameters.length, extraLength = parameters.length; i < extraLength; i++) { + TypeBinding parameter = parameters[i]; + TypeBinding leafParameterType = parameter.leafComponentType(); + if (leafParameterType.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(leafParameterType); + } + buffer.append(parameter.signature()); + } + } + buffer.append(')'); + if (this.returnType != null) { + TypeBinding ret = this.returnType.leafComponentType(); + if (ret.isNestedType()) { + this.tagBits |= TagBits.ContainsNestedTypesInSignature; + classFile.recordInnerClasses(ret); + } + buffer.append(this.returnType.signature()); + } + int nameLength = buffer.length(); + signature = new char[nameLength]; + buffer.getChars(0, nameLength, signature, 0); + + return signature; +} public final int sourceEnd() { AbstractMethodDeclaration method = sourceMethod(); if (method == null) { Index: compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java,v retrieving revision 1.132 diff -u -r1.132 TypeDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java 15 Jan 2007 09:50:06 -0000 1.132 +++ compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java 24 Jan 2007 18:56:57 -0000 @@ -504,23 +504,21 @@ // create the result for a compiled type ClassFile classFile = ClassFile.getNewInstance(this.binding); classFile.initialize(this.binding, enclosingClassFile, false); + if (this.binding.isMemberType()) { + classFile.recordInnerClasses(this.binding); + } else if (this.binding.isLocalType()) { + enclosingClassFile.recordInnerClasses(this.binding); + classFile.recordInnerClasses(this.binding); + } + // generate all fiels classFile.addFieldInfos(); - // record the inner type inside its own .class file to be able - // to generate inner classes attributes - if (this.binding.isMemberType()) - classFile.recordEnclosingTypeAttributes(this.binding); - if (this.binding.isLocalType()) { - enclosingClassFile.recordNestedLocalAttribute(this.binding); - classFile.recordNestedLocalAttribute(this.binding); - } if (this.memberTypes != null) { for (int i = 0, max = this.memberTypes.length; i < max; i++) { - // record the inner type inside its own .class file to be able - // to generate inner classes attributes - classFile.recordNestedMemberAttribute(this.memberTypes[i].binding); - this.memberTypes[i].generateCode(this.scope, classFile); + TypeDeclaration memberType = this.memberTypes[i]; + classFile.recordInnerClasses(memberType.binding); + memberType.generateCode(this.scope, classFile); } } // generate all methods Index: compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java,v retrieving revision 1.88 diff -u -r1.88 AbstractMethodDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java 28 Mar 2006 20:29:56 -0000 1.88 +++ compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java 24 Jan 2007 18:56:57 -0000 @@ -73,7 +73,7 @@ public abstract void analyseCode(ClassScope classScope, InitializationFlowContext initializationContext, FlowInfo info); - /** + /** * Bind and add argument's binding into the scope of the method */ public void bindArguments() { Index: compiler/org/eclipse/jdt/internal/compiler/ClassFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java,v retrieving revision 1.144 diff -u -r1.144 ClassFile.java --- compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 5 Dec 2006 22:02:24 -0000 1.144 +++ compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 24 Jan 2007 18:56:57 -0000 @@ -15,7 +15,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; import java.util.Set; import java.util.StringTokenizer; @@ -106,10 +109,9 @@ public byte[] header; // that collection contains all the remaining bytes of the .class file public int headerOffset; - public ReferenceBinding[] innerClassesBindings; + public Set innerClassesBindings; public int methodCount; public int methodCountOffset; - public int numberOfInnerClasses; // pool managment public boolean isShared = false; // used to generate private access methods @@ -256,9 +258,10 @@ // TODO (olivier) handle cases where a field cannot be generated (name too long) // TODO (olivier) handle too many methods // inner attributes - if (typeBinding.isMemberType()) - classFile.recordEnclosingTypeAttributes(typeBinding); - + if (typeBinding.isNestedType()) { + classFile.recordInnerClasses(typeBinding); + } + // add its fields FieldBinding[] fields = typeBinding.fields(); if ((fields != null) && (fields != Binding.NO_FIELDS)) { @@ -312,7 +315,6 @@ 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); } } @@ -496,65 +498,6 @@ contents[contentsOffset++] = 0; attributeNumber++; } - // Inner class attribute - if (numberOfInnerClasses != 0) { - // Generate the inner class attribute - int exSize = 8 * numberOfInnerClasses + 8; - if (exSize + contentsOffset >= this.contents.length) { - resizeContents(exSize); - } - // Now we now the size of the attribute and the number of entries - // attribute name - int attributeNameIndex = - constantPool.literalIndex(AttributeNamesConstants.InnerClassName); - contents[contentsOffset++] = (byte) (attributeNameIndex >> 8); - contents[contentsOffset++] = (byte) attributeNameIndex; - int value = (numberOfInnerClasses << 3) + 2; - contents[contentsOffset++] = (byte) (value >> 24); - contents[contentsOffset++] = (byte) (value >> 16); - contents[contentsOffset++] = (byte) (value >> 8); - contents[contentsOffset++] = (byte) value; - contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8); - contents[contentsOffset++] = (byte) numberOfInnerClasses; - for (int i = 0; i < numberOfInnerClasses; i++) { - ReferenceBinding innerClass = innerClassesBindings[i]; - int accessFlags = innerClass.getAccessFlags(); - int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName()); - // inner class index - contents[contentsOffset++] = (byte) (innerClassIndex >> 8); - contents[contentsOffset++] = (byte) innerClassIndex; - // outer class index: anonymous and local have no outer class index - if (innerClass.isMemberType()) { - // member or member of local - int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName()); - 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 &= ~ClassFileConstants.AccFinal; - } else if (innerClass.isMemberType() && innerClass.isInterface()) { - accessFlags |= ClassFileConstants.AccStatic; // implicitely static - } - contents[contentsOffset++] = (byte) (accessFlags >> 8); - contents[contentsOffset++] = (byte) accessFlags; - } - attributeNumber++; - } // add signature attribute char[] genericSignature = referenceBinding.genericSignature(); if (genericSignature != null) { @@ -603,7 +546,7 @@ if (this.referenceBinding instanceof LocalTypeBinding) { MethodBinding methodBinding = ((LocalTypeBinding) this.referenceBinding).enclosingMethod; if (methodBinding != null) { - int enclosingMethodIndex = constantPool.literalIndexForNameAndType(methodBinding.selector, methodBinding.signature()); + int enclosingMethodIndex = constantPool.literalIndexForNameAndType(methodBinding.selector, methodBinding.signature(this)); methodIndexByte1 = (byte) (enclosingMethodIndex >> 8); methodIndexByte2 = (byte) enclosingMethodIndex; } @@ -638,6 +581,75 @@ contents[contentsOffset++] = 0; attributeNumber++; } + // Inner class attribute + int numberOfInnerClasses = this.innerClassesBindings == null ? 0 : this.innerClassesBindings.size(); + if (numberOfInnerClasses != 0) { + ReferenceBinding[] innerClasses = new ReferenceBinding[numberOfInnerClasses]; + this.innerClassesBindings.toArray(innerClasses); + Arrays.sort(innerClasses, new Comparator() { + public int compare(Object o1, Object o2) { + TypeBinding binding1 = (TypeBinding) o1; + TypeBinding binding2 = (TypeBinding) o2; + return CharOperation.compareTo(binding1.constantPoolName(), binding2.constantPoolName()); + } + }); + // Generate the inner class attribute + int exSize = 8 * numberOfInnerClasses + 8; + if (exSize + contentsOffset >= this.contents.length) { + resizeContents(exSize); + } + // Now we now the size of the attribute and the number of entries + // attribute name + int attributeNameIndex = + constantPool.literalIndex(AttributeNamesConstants.InnerClassName); + contents[contentsOffset++] = (byte) (attributeNameIndex >> 8); + contents[contentsOffset++] = (byte) attributeNameIndex; + int value = (numberOfInnerClasses << 3) + 2; + contents[contentsOffset++] = (byte) (value >> 24); + contents[contentsOffset++] = (byte) (value >> 16); + contents[contentsOffset++] = (byte) (value >> 8); + contents[contentsOffset++] = (byte) value; + contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8); + contents[contentsOffset++] = (byte) numberOfInnerClasses; + for (int i = 0; i < numberOfInnerClasses; i++) { + ReferenceBinding innerClass = innerClasses[i]; + int accessFlags = innerClass.getAccessFlags(); + int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName()); + // inner class index + contents[contentsOffset++] = (byte) (innerClassIndex >> 8); + contents[contentsOffset++] = (byte) innerClassIndex; + // outer class index: anonymous and local have no outer class index + if (innerClass.isMemberType()) { + // member or member of local + int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName()); + 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 &= ~ClassFileConstants.AccFinal; + } else if (innerClass.isMemberType() && innerClass.isInterface()) { + accessFlags |= ClassFileConstants.AccStatic; // implicitely static + } + contents[contentsOffset++] = (byte) (accessFlags >> 8); + contents[contentsOffset++] = (byte) accessFlags; + } + attributeNumber++; + } // update the number of attributes if (attributeOffset + 2 >= this.contents.length) { resizeContents(2); @@ -840,7 +852,7 @@ contents[contentsOffset++] = (byte) (nameIndex >> 8); contents[contentsOffset++] = (byte) nameIndex; // Then the descriptorIndex - int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature()); + int descriptorIndex = constantPool.literalIndex(fieldBinding.type); contents[contentsOffset++] = (byte) (descriptorIndex >> 8); contents[contentsOffset++] = (byte) descriptorIndex; int fieldAttributeOffset = contentsOffset; @@ -896,31 +908,6 @@ } } } - - /** - * INTERNAL USE-ONLY - * This methods stores the bindings for each inner class. They will be used to know which entries - * have to be generated for the inner classes attributes. - * @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding - */ - private void addInnerClasses(ReferenceBinding refBinding) { - // check first if that reference binding is there - for (int i = 0; i < numberOfInnerClasses; i++) { - if (innerClassesBindings[i] == refBinding) - return; - } - int length = innerClassesBindings.length; - if (numberOfInnerClasses == length) { - System.arraycopy( - innerClassesBindings, - 0, - innerClassesBindings = new ReferenceBinding[length * 2], - 0, - length); - } - innerClassesBindings[numberOfInnerClasses++] = refBinding; - } - private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, CategorizedProblem problem, CompilationResult compilationResult) { // always clear the strictfp/native/abstract bit for a problem method generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract)); @@ -1532,7 +1519,7 @@ /* represents ClassNotFoundException, see class literal access*/ nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); } else { - nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType.constantPoolName()); + nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType); } this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; @@ -2212,7 +2199,7 @@ /* represents denote ClassNotFoundException, see class literal access*/ nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); } else { - nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType.constantPoolName()); + nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType); } this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; @@ -4407,7 +4394,7 @@ nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName); break; default: - nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType.constantPoolName()); + nameIndex = constantPool.literalIndexForType(exceptionLabel.exceptionType); } this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); this.contents[localContentsOffset++] = (byte) nameIndex; @@ -5330,7 +5317,7 @@ contents[contentsOffset++] = (byte) (length >> 8); contents[contentsOffset++] = (byte) length; for (int i = 0; i < length; i++) { - int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i].constantPoolName()); + int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i]); contents[contentsOffset++] = (byte) (exceptionIndex >> 8); contents[contentsOffset++] = (byte) exceptionIndex; } @@ -5457,7 +5444,7 @@ int nameIndex = constantPool.literalIndex(methodBinding.selector); contents[contentsOffset++] = (byte) (nameIndex >> 8); contents[contentsOffset++] = (byte) nameIndex; - int descriptorIndex = constantPool.literalIndex(methodBinding.signature()); + int descriptorIndex = constantPool.literalIndex(methodBinding.signature(this)); contents[contentsOffset++] = (byte) (descriptorIndex >> 8); contents[contentsOffset++] = (byte) descriptorIndex; } @@ -5832,7 +5819,7 @@ // now we continue to generate the bytes inside the contents array contents[contentsOffset++] = (byte) (accessFlags >> 8); contents[contentsOffset++] = (byte) accessFlags; - int classNameIndex = constantPool.literalIndexForType(aType.constantPoolName()); + int classNameIndex = constantPool.literalIndexForType(aType); contents[contentsOffset++] = (byte) (classNameIndex >> 8); contents[contentsOffset++] = (byte) classNameIndex; int superclassNameIndex; @@ -5840,7 +5827,7 @@ superclassNameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); } else { superclassNameIndex = - (aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass.constantPoolName())); + (aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass)); } contents[contentsOffset++] = (byte) (superclassNameIndex >> 8); contents[contentsOffset++] = (byte) superclassNameIndex; @@ -5849,11 +5836,10 @@ contents[contentsOffset++] = (byte) (interfacesCount >> 8); contents[contentsOffset++] = (byte) interfacesCount; for (int i = 0; i < interfacesCount; i++) { - int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName()); + int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i]); contents[contentsOffset++] = (byte) (interfaceIndex >> 8); contents[contentsOffset++] = (byte) interfaceIndex; } - innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE]; this.creatingProblemType = createProblemType; // retrieve the enclosing one guaranteed to be the one matching the propagated flow info @@ -5904,78 +5890,20 @@ 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++; + public void recordInnerClasses(TypeBinding binding) { + if (this.innerClassesBindings == null) { + this.innerClassesBindings = new HashSet(INNER_CLASSES_SIZE); + } + ReferenceBinding innerClass = (ReferenceBinding) binding; + this.innerClassesBindings.add(innerClass.erasure()); + ReferenceBinding enclosingType = innerClass.enclosingType(); + while (enclosingType != null + && enclosingType.isNestedType()) { + this.innerClassesBindings.add(enclosingType.erasure()); 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); - } - public void reset(SourceTypeBinding typeBinding) { // the code stream is reinitialized for each method final CompilerOptions options = typeBinding.scope.compilerOptions(); @@ -5995,7 +5923,9 @@ this.headerOffset = 0; this.methodCount = 0; this.methodCountOffset = 0; - this.numberOfInnerClasses = 0; + if (this.innerClassesBindings != null) { + this.innerClassesBindings.clear(); + } } /** Index: compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java,v retrieving revision 1.148 diff -u -r1.148 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 22 Jan 2007 19:48:50 -0000 1.148 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 24 Jan 2007 18:56:58 -0000 @@ -339,7 +339,7 @@ } position++; bCodeStream[classFileOffset++] = Opcodes.OPC_anewarray; - writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName())); + writeUnsignedShort(constantPool.literalIndexForType(typeBinding)); } public void areturn() { if (DEBUG) System.out.println(position + "\t\tareturn"); //$NON-NLS-1$ @@ -615,7 +615,7 @@ } position++; bCodeStream[classFileOffset++] = Opcodes.OPC_checkcast; - writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName())); + writeUnsignedShort(constantPool.literalIndexForType(typeBinding)); } public void d2f() { if (DEBUG) System.out.println(position + "\t\td2f"); //$NON-NLS-1$ @@ -1903,6 +1903,16 @@ bCodeStream[classFileOffset++] = opcode; writeUnsignedShort(constantPool.literalIndexForField(declaringClass, name, signature)); } +private void generateFieldAccess(byte opcode, int returnTypeSize, ReferenceBinding binding, char[] name, TypeBinding type) { + if (binding.isNestedType()) { + this.classFile.recordInnerClasses(binding); + } + TypeBinding leafComponentType = type.leafComponentType(); + if (leafComponentType.isNestedType()) { + this.classFile.recordInnerClasses(leafComponentType); + } + this.generateFieldAccess(opcode, returnTypeSize, binding.constantPoolName(), name, type.signature()); +} /** * Generates the sequence of instructions which will perform the conversion of the expression * on the stack into a different type (e.g. long l = someInt; --> i2l must be inserted). @@ -2835,9 +2845,9 @@ generateFieldAccess( Opcodes.OPC_getfield, returnTypeSize, - fieldBinding.declaringClass.constantPoolName(), + fieldBinding.declaringClass, fieldBinding.name, - fieldBinding.type.signature()); + fieldBinding.type); } protected int getPosition() { return this.position; @@ -2851,9 +2861,9 @@ generateFieldAccess( Opcodes.OPC_getstatic, returnTypeSize, - fieldBinding.declaringClass.constantPoolName(), + fieldBinding.declaringClass, fieldBinding.name, - fieldBinding.type.signature()); + fieldBinding.type); } public void getTYPE(int baseTypeID) { countLabels = 0; @@ -3712,7 +3722,7 @@ } position++; bCodeStream[classFileOffset++] = Opcodes.OPC_instanceof; - writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName())); + writeUnsignedShort(constantPool.literalIndexForType(typeBinding)); } protected void invoke(int opcode, int argsSize, int returnTypeSize, char[] declaringClass, char[] selector, char[] signature) { countLabels = 0; @@ -3837,9 +3847,9 @@ bCodeStream[classFileOffset++] = Opcodes.OPC_invokeinterface; writeUnsignedShort( constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass().constantPoolName(), + methodBinding.constantPoolDeclaringClass(), methodBinding.selector, - methodBinding.signature(), + methodBinding.signature(classFile), true)); for (int i = methodBinding.parameters.length - 1; i >= 0; i--) if (((id = methodBinding.parameters[i].id) == TypeIds.T_double) || (id == TypeIds.T_long)) @@ -4135,9 +4145,9 @@ bCodeStream[classFileOffset++] = Opcodes.OPC_invokespecial; writeUnsignedShort( constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass().constantPoolName(), + methodBinding.constantPoolDeclaringClass(), methodBinding.selector, - methodBinding.signature(), + methodBinding.signature(classFile), false)); if (methodBinding.isConstructor()) { final ReferenceBinding declaringClass = methodBinding.declaringClass; @@ -4198,9 +4208,9 @@ bCodeStream[classFileOffset++] = Opcodes.OPC_invokestatic; writeUnsignedShort( constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass().constantPoolName(), + methodBinding.constantPoolDeclaringClass(), methodBinding.selector, - methodBinding.signature(), + methodBinding.signature(classFile), false)); for (int i = methodBinding.parameters.length - 1; i >= 0; i--) if (((id = methodBinding.parameters[i].id) == TypeIds.T_double) || (id == TypeIds.T_long)) @@ -4472,9 +4482,9 @@ bCodeStream[classFileOffset++] = Opcodes.OPC_invokevirtual; writeUnsignedShort( constantPool.literalIndexForMethod( - methodBinding.constantPoolDeclaringClass().constantPoolName(), + methodBinding.constantPoolDeclaringClass(), methodBinding.selector, - methodBinding.signature(), + methodBinding.signature(classFile), false)); for (int i = methodBinding.parameters.length - 1; i >= 0; i--) if (((id = methodBinding.parameters[i].id) == TypeIds.T_double) || (id == TypeIds.T_long)) @@ -4949,7 +4959,7 @@ } public void ldc(TypeBinding typeBinding) { countLabels = 0; - int index = constantPool.literalIndexForType(typeBinding.constantPoolName()); + int index = constantPool.literalIndexForType(typeBinding); stackDepth++; if (stackDepth > stackMax) stackMax = stackDepth; @@ -5464,7 +5474,7 @@ } position += 2; bCodeStream[classFileOffset++] = Opcodes.OPC_multianewarray; - writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName())); + writeUnsignedShort(constantPool.literalIndexForType(typeBinding)); bCodeStream[classFileOffset++] = (byte) dimensions; } // We didn't call it new, because there is a conflit with the new keyword @@ -5479,7 +5489,7 @@ } position++; bCodeStream[classFileOffset++] = Opcodes.OPC_new; - writeUnsignedShort(constantPool.literalIndexForType(typeBinding.constantPoolName())); + writeUnsignedShort(constantPool.literalIndexForType(typeBinding)); } public void newarray(int array_Type) { if (DEBUG) System.out.println(position + "\t\tnewarray:"+array_Type); //$NON-NLS-1$ @@ -5702,9 +5712,9 @@ generateFieldAccess( Opcodes.OPC_putfield, returnTypeSize, - fieldBinding.declaringClass.constantPoolName(), + fieldBinding.declaringClass, fieldBinding.name, - fieldBinding.type.signature()); + fieldBinding.type); } public void putstatic(FieldBinding fieldBinding) { if (DEBUG) System.out.println(position + "\t\tputstatic:"+fieldBinding); //$NON-NLS-1$ @@ -5715,9 +5725,9 @@ generateFieldAccess( Opcodes.OPC_putstatic, returnTypeSize, - fieldBinding.declaringClass.constantPoolName(), + fieldBinding.declaringClass, fieldBinding.name, - fieldBinding.type.signature()); + fieldBinding.type); } public void record(LocalVariableBinding local) { if ((this.generateAttributes & (ClassFileConstants.ATTR_VARS | ClassFileConstants.ATTR_STACK_MAP)) == 0) Index: compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java,v retrieving revision 1.52 diff -u -r1.52 ConstantPool.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java 8 Jun 2006 15:39:27 -0000 1.52 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java 24 Jan 2007 18:56:58 -0000 @@ -13,6 +13,7 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFile; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.util.HashtableOfObject; @@ -285,6 +286,13 @@ } return index; } +public int literalIndex(TypeBinding binding) { + TypeBinding typeBinding = binding.leafComponentType(); + if (typeBinding.isNestedType()) { + this.classFile.recordInnerClasses(typeBinding); + } + return literalIndex(binding.signature()); +} /** * This method returns the index into the constantPool corresponding to the type descriptor. * @@ -551,10 +559,6 @@ } return index; } -/** - * This method returns the index into the constantPool corresponding to the type descriptor - * corresponding to a type constant pool name. - */ public int literalIndexForType(final char[] constantPoolName) { int index; if ((index = classCache.putIfAbsent(constantPoolName, this.currentIndex)) < 0) { @@ -577,6 +581,18 @@ } return index; } +/* + * This method returns the index into the constantPool corresponding to the type descriptor + * corresponding to a type constant pool name + * binding must not be an array type. + */ +public int literalIndexForType(final TypeBinding binding) { + TypeBinding typeBinding = binding.leafComponentType(); + if (typeBinding.isNestedType()) { + this.classFile.recordInnerClasses(typeBinding); + } + return this.literalIndexForType(binding.constantPoolName()); +} public int literalIndexForMethod(char[] declaringClass, char[] selector, char[] signature, boolean isInterface) { int index; if ((index = putInCacheIfAbsent(declaringClass, selector, signature, this.currentIndex)) < 0) { @@ -605,6 +621,12 @@ } return index; } +public int literalIndexForMethod(TypeBinding binding, char[] selector, char[] signature, boolean isInterface) { + if (binding.isNestedType()) { + this.classFile.recordInnerClasses(binding); + } + return this.literalIndexForMethod(binding.constantPoolName(), selector, signature, isInterface); +} public int literalIndexForNameAndType(char[] name, char[] signature) { int index; if ((index = putInNameAndTypeCacheIfAbsent(name, signature, currentIndex)) < 0) { Index: compiler/org/eclipse/jdt/core/compiler/CharOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/CharOperation.java,v retrieving revision 1.75 diff -u -r1.75 CharOperation.java --- compiler/org/eclipse/jdt/core/compiler/CharOperation.java 6 Oct 2006 16:41:07 -0000 1.75 +++ compiler/org/eclipse/jdt/core/compiler/CharOperation.java 24 Jan 2007 18:56:56 -0000 @@ -484,7 +484,30 @@ result[length] = second; return result; } - +/** + * Compares the two char arrays lexicographically. + * + * Returns a negative integer if array1 lexicographically precedes the array2, + * a positive integer if this array1 lexicographically follows the array2, or + * zero if both arrays are equal. + * + * @param array1 the first given array + * @param array2 the second given array + * @return the returned value of the comparison between array1 and array2 + * @throws NullPointerException if one of the arrays is null + * @since 3.3 + */ +public static final int compareTo(char[] array1, char[] array2) { + int length1 = array1.length; + int length2 = array2.length; + int min = Math.min(length1, length2); + for (int i = 0; i < min; i++) { + if (array1[i] != array2[i]) { + return array1[i] - array2[i]; + } + } + return length1 - length2; +} /** * Compares the contents of the two arrays array and prefix. Returns *