diff options
author | Olivier Thomann | 2010-01-13 20:35:56 +0000 |
---|---|---|
committer | Olivier Thomann | 2010-01-13 20:35:56 +0000 |
commit | 76fb97f33d9c5e3f0d862cb54201de8db813dfbf (patch) | |
tree | fc8818e46ddb50f5cfa76020fcd2c481d04b4e0e /org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java | |
parent | bc5bbdf71d28e3f4a538e7c912b3ca6d3b9a783d (diff) | |
download | eclipse.jdt.core-76fb97f33d9c5e3f0d862cb54201de8db813dfbf.tar.gz eclipse.jdt.core-76fb97f33d9c5e3f0d862cb54201de8db813dfbf.tar.xz eclipse.jdt.core-76fb97f33d9c5e3f0d862cb54201de8db813dfbf.zip |
JSR_308 - Continue work on type annotation code generation
Diffstat (limited to 'org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java')
-rw-r--r-- | org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java | 181 |
1 files changed, 159 insertions, 22 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java index 0c46b6c7ef..b012a7c500 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java @@ -30,6 +30,7 @@ import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; +import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; @@ -251,6 +252,9 @@ public class ClassFile implements TypeConstants, TypeIds { if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; this.codeStream = new StackMapFrameCodeStream(this); + if (this.targetJDK >= ClassFileConstants.JDK1_7) { + this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; + } } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) { this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3 this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP; @@ -542,9 +546,11 @@ public class ClassFile implements TypeConstants, TypeIds { annotationContext.typeIndex = -1; if (isRuntimeTypeInvisible(annotationContext.annotation)) { invisibleTypeAnnotationsCounter++; + annotationContext.visibility = AnnotationContext.INVISIBLE; allTypeAnnotationContexts.add(annotationContext); } else if (isRuntimeTypeVisible(annotationContext.annotation)) { visibleTypeAnnotationsCounter++; + annotationContext.visibility = AnnotationContext.VISIBLE; allTypeAnnotationContexts.add(annotationContext); } } @@ -1456,7 +1462,7 @@ public class ClassFile implements TypeConstants, TypeIds { } // debug attributes int codeAttributeAttributeOffset = localContentsOffset; - int attributeNumber = 0; + int attributesNumber = 0; // leave two bytes for the attribute_length localContentsOffset += 2; if (localContentsOffset + 2 >= this.contents.length) { @@ -1507,7 +1513,7 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length; this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8); this.contents[lineNumberTableOffset++] = (byte) numberOfEntries; - attributeNumber++; + attributesNumber++; } } // then we do the local variable attribute @@ -1558,17 +1564,19 @@ public class ClassFile implements TypeConstants, TypeIds { for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { LocalVariableBinding localVariable = this.codeStream.locals[i]; + int initializationCount = localVariable.initializationCount; + if (initializationCount == 0) continue; if (localVariable.declaration == null) continue; final TypeBinding localVariableTypeBinding = localVariable.type; boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable(); - if (localVariable.initializationCount != 0 && isParameterizedType) { + if (isParameterizedType) { if (genericLocalVariables == null) { // we cannot have more than max locals genericLocalVariables = new LocalVariableBinding[max]; } genericLocalVariables[genericLocalVariablesCounter++] = localVariable; } - for (int j = 0; j < localVariable.initializationCount; j++) { + for (int j = 0; j < initializationCount; j++) { int startPC = localVariable.initializationPCs[j << 1]; int endPC = localVariable.initializationPCs[(j << 1) + 1]; if (startPC != endPC) { // only entries for non zero length @@ -1606,7 +1614,7 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[localVariableTableOffset++] = (byte) value; this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8); this.contents[localVariableTableOffset] = (byte) numberOfEntries; - attributeNumber++; + attributesNumber++; final boolean currentInstanceIsGeneric = !methodDeclarationIsStatic @@ -1671,7 +1679,7 @@ public class ClassFile implements TypeConstants, TypeIds { } } } - attributeNumber++; + attributesNumber++; } } @@ -2016,7 +2024,7 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength; - attributeNumber++; + attributesNumber++; } else { localContentsOffset = stackMapTableAttributeOffset; } @@ -2184,16 +2192,15 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16); this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8); this.contents[stackMapAttributeLengthOffset] = (byte) attributeLength; - attributeNumber++; + attributesNumber++; } else { localContentsOffset = stackMapTableAttributeOffset; } } } } - - this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber; + this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); + this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; // update the attribute length int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6); @@ -2383,17 +2390,19 @@ public class ClassFile implements TypeConstants, TypeIds { for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { LocalVariableBinding localVariable = this.codeStream.locals[i]; + int initializationCount = localVariable.initializationCount; + if (initializationCount == 0) continue; if (localVariable.declaration == null) continue; final TypeBinding localVariableTypeBinding = localVariable.type; boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable(); - if (localVariable.initializationCount != 0 && isParameterizedType) { + if (isParameterizedType) { if (genericLocalVariables == null) { // we cannot have more than max locals genericLocalVariables = new LocalVariableBinding[max]; } genericLocalVariables[genericLocalVariablesCounter++] = localVariable; } - for (int j = 0; j < localVariable.initializationCount; j++) { + for (int j = 0; j < initializationCount; j++) { int startPC = localVariable.initializationPCs[j << 1]; int endPC = localVariable.initializationPCs[(j << 1) + 1]; if (startPC != endPC) { // only entries for non zero length @@ -5255,17 +5264,19 @@ public class ClassFile implements TypeConstants, TypeIds { for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { LocalVariableBinding localVariable = this.codeStream.locals[i]; + int initializationCount = localVariable.initializationCount; + if (initializationCount == 0) continue; if (localVariable.declaration == null) continue; final TypeBinding localVariableTypeBinding = localVariable.type; boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable(); - if (localVariable.initializationCount != 0 && isParameterizedType) { + if (isParameterizedType) { if (genericLocalVariables == null) { // we cannot have more than max locals genericLocalVariables = new LocalVariableBinding[max]; } genericLocalVariables[genericLocalVariablesCounter++] = localVariable; } - for (int j = 0; j < localVariable.initializationCount; j++) { + for (int j = 0; j < initializationCount; j++) { int startPC = localVariable.initializationPCs[j << 1]; int endPC = localVariable.initializationPCs[(j << 1) + 1]; if (startPC != endPC) { // only entries for non zero length @@ -5919,14 +5930,56 @@ public class ClassFile implements TypeConstants, TypeIds { * 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> + * @param attributesNumber <CODE>int</CODE> */ public void completeMethodInfo( int methodAttributeOffset, - int attributeNumber) { + int attributesNumber) { + + if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { + List allTypeAnnotationContexts = new ArrayList(); + int invisibleTypeAnnotationsCounter = 0; + int visibleTypeAnnotationsCounter = 0; + for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { + LocalVariableBinding localVariable = this.codeStream.locals[i]; + LocalDeclaration declaration = localVariable.declaration; + if (declaration == null + || (localVariable.initializationCount == 0) + || ((declaration.bits & ASTNode.HasTypeAnnotations) == 0)) { + continue; + } + AnnotationContext[] annotationContexts = declaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.LOCAL_VARIABLE); + if (annotationContexts != null && annotationContexts.length != 0) { + for (int j = 0, max2 = annotationContexts.length; j < max2; j++) { + AnnotationContext annotationContext = annotationContexts[j]; + if (isRuntimeTypeInvisible(annotationContext.annotation)) { + annotationContext.visibility = AnnotationContext.INVISIBLE; + annotationContext.variableBinding = localVariable; + invisibleTypeAnnotationsCounter++; + allTypeAnnotationContexts.add(annotationContext); + } else if (isRuntimeTypeVisible(annotationContext.annotation)) { + annotationContext.visibility = AnnotationContext.VISIBLE; + annotationContext.variableBinding = localVariable; + allTypeAnnotationContexts.add(annotationContext); + visibleTypeAnnotationsCounter++; + } + } + } + } + int size = allTypeAnnotationContexts.size(); + if (size != 0) { + AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; + allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); + attributesNumber += generateRuntimeTypeAnnotations( + allTypeAnnotationContextsArray, + visibleTypeAnnotationsCounter, + invisibleTypeAnnotationsCounter); + } + } + // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; + this.contents[methodAttributeOffset++] = (byte) (attributesNumber >> 8); + this.contents[methodAttributeOffset] = (byte) attributesNumber; } /** @@ -6021,7 +6074,7 @@ public class ClassFile implements TypeConstants, TypeIds { // error occurred while generating the annotation return; } - int[] locations = Annotation.getLocations(annotationContext.typeReference, null, annotationContext.annotation); + int[] locations = Annotation.getLocations(annotationContext.typeReference, annotationContext.primaryAnnotations, annotationContext.annotation); int targetType = annotationContext.targetType; if (locations != null) { // convert to GENERIC_OR_ARRAY type @@ -6029,8 +6082,14 @@ public class ClassFile implements TypeConstants, TypeIds { case AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS : targetType = AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS_GENERIC_OR_ARRAY; break; + case AnnotationTargetTypeConstants.LOCAL_VARIABLE : + targetType = AnnotationTargetTypeConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY; } } + // reserve enough space + if (this.contentsOffset + 3 >= this.contents.length) { + resizeContents(3); + } this.contents[this.contentsOffset++] = (byte) targetType; switch(targetType) { case AnnotationTargetTypeConstants.CLASS_EXTENDS_IMPLEMENTS : @@ -6041,12 +6100,87 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[this.contentsOffset++] = (byte) (annotationContext.typeIndex >> 8); this.contents[this.contentsOffset++] = (byte) annotationContext.typeIndex; int length = locations.length; + int actualSize = 2 + length; + if (this.contentsOffset + actualSize >= this.contents.length) { + resizeContents(actualSize); + } this.contents[this.contentsOffset++] = (byte) (length >> 8); this.contents[this.contentsOffset++] = (byte) length; for (int i = 0; i < length; i++) { this.contents[this.contentsOffset++] = (byte) locations[i]; } break; + case AnnotationTargetTypeConstants.LOCAL_VARIABLE : + int localVariableTableOffset = this.contentsOffset; + LocalVariableBinding localVariable = annotationContext.variableBinding; + actualSize = 0; + int initializationCount = localVariable.initializationCount; + actualSize += 6 * initializationCount; + // reserve enough space + if (this.contentsOffset + actualSize >= this.contents.length) { + resizeContents(actualSize); + } + this.contentsOffset += 2; + int numberOfEntries = 0; + for (int j = 0; j < initializationCount; j++) { + int startPC = localVariable.initializationPCs[j << 1]; + int endPC = localVariable.initializationPCs[(j << 1) + 1]; + if (startPC != endPC) { // only entries for non zero length + // now we can safely add the local entry + numberOfEntries++; + this.contents[this.contentsOffset++] = (byte) (startPC >> 8); + this.contents[this.contentsOffset++] = (byte) startPC; + length = endPC - startPC; + this.contents[this.contentsOffset++] = (byte) (length >> 8); + this.contents[this.contentsOffset++] = (byte) length; + int resolvedPosition = localVariable.resolvedPosition; + this.contents[this.contentsOffset++] = (byte) (resolvedPosition >> 8); + this.contents[this.contentsOffset++] = (byte) resolvedPosition; + } + } + this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8); + this.contents[localVariableTableOffset] = (byte) numberOfEntries; + break; + case AnnotationTargetTypeConstants.LOCAL_VARIABLE_GENERIC_OR_ARRAY : + localVariableTableOffset = this.contentsOffset; + localVariable = annotationContext.variableBinding; + actualSize = 0; + initializationCount = localVariable.initializationCount; + actualSize += 6 * initializationCount; + // reserve enough space + if (this.contentsOffset + actualSize >= this.contents.length) { + resizeContents(actualSize); + } + this.contentsOffset += 2; + numberOfEntries = 0; + for (int j = 0; j < initializationCount; j++) { + int startPC = localVariable.initializationPCs[j << 1]; + int endPC = localVariable.initializationPCs[(j << 1) + 1]; + if (startPC != endPC) { // only entries for non zero length + // now we can safely add the local entry + numberOfEntries++; + this.contents[this.contentsOffset++] = (byte) (startPC >> 8); + this.contents[this.contentsOffset++] = (byte) startPC; + length = endPC - startPC; + this.contents[this.contentsOffset++] = (byte) (length >> 8); + this.contents[this.contentsOffset++] = (byte) length; + int resolvedPosition = localVariable.resolvedPosition; + this.contents[this.contentsOffset++] = (byte) (resolvedPosition >> 8); + this.contents[this.contentsOffset++] = (byte) resolvedPosition; + } + } + this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8); + this.contents[localVariableTableOffset] = (byte) numberOfEntries; + length = locations.length; + actualSize = 2 + length; + if (this.contentsOffset + actualSize >= this.contents.length) { + resizeContents(actualSize); + } + this.contents[this.contentsOffset++] = (byte) (length >> 8); + this.contents[this.contentsOffset++] = (byte) length; + for (int i = 0; i < length; i++) { + this.contents[this.contentsOffset++] = (byte) locations[i]; + } } } /** @@ -6736,7 +6870,7 @@ public class ClassFile implements TypeConstants, TypeIds { loop: for (int i = 0; i < length; i++) { if (invisibleTypeAnnotationsCounter == 0) break loop; AnnotationContext annotationContext = annotationContexts[i]; - if (isRuntimeTypeInvisible(annotationContext.annotation)) { + if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { int currentAnnotationOffset = this.contentsOffset; generateTypeAnnotation(annotationContext, currentAnnotationOffset); invisibleTypeAnnotationsCounter--; @@ -6783,7 +6917,7 @@ public class ClassFile implements TypeConstants, TypeIds { loop: for (int i = 0; i < length; i++) { if (visibleTypeAnnotationsCounter == 0) break loop; AnnotationContext annotationContext = annotationContexts[i]; - if (isRuntimeTypeVisible(annotationContext.annotation)) { + if ((annotationContext.visibility & AnnotationContext.VISIBLE) != 0) { visibleTypeAnnotationsCounter--; int currentAnnotationOffset = this.contentsOffset; generateTypeAnnotation(annotationContext, currentAnnotationOffset); @@ -7412,6 +7546,9 @@ public class ClassFile implements TypeConstants, TypeIds { this.produceAttributes = options.produceDebugAttributes; if (this.targetJDK >= ClassFileConstants.JDK1_6) { this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; + if (this.targetJDK >= ClassFileConstants.JDK1_7) { + this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; + } } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) { this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3 this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP; |