Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 57466 Details for
Bug 171184
[compiler] Java compiler does not generate InnerClass attribute as per JVMS
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
First draft
patch_171184.txt (text/plain), 45.28 KB, created by
Olivier Thomann
on 2007-01-24 14:43:49 EST
(
hide
)
Description:
First draft
Filename:
MIME Type:
Creator:
Olivier Thomann
Created:
2007-01-24 14:43:49 EST
Size:
45.28 KB
patch
obsolete
>### 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 > * <ul>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 171184
: 57466