15 changed files with 870 additions and 22 deletions
@ -0,0 +1,169 @@
@@ -0,0 +1,169 @@
|
||||
// ASM: a very small and fast Java bytecode manipulation framework
|
||||
// Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holders nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
package org.springframework.asm; |
||||
|
||||
/** |
||||
* A visitor to visit a record component. The methods of this class must be called in the following |
||||
* order: ( {@code visitAnnotation} | {@code visitTypeAnnotation} | {@code visitAttribute} )* {@code |
||||
* visitEnd}. |
||||
* |
||||
* @author Remi Forax |
||||
* @author Eric Bruneton |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public abstract class RecordComponentVisitor { |
||||
/** |
||||
* The ASM API version implemented by this visitor. The value of this field must be {@link |
||||
* Opcodes#ASM8_EXPERIMENTAL}. |
||||
*/ |
||||
protected final int api; |
||||
|
||||
/** |
||||
* The record visitor to which this visitor must delegate method calls. May be {@literal null}. |
||||
*/ |
||||
/*package-private*/ RecordComponentVisitor delegate; |
||||
|
||||
/** |
||||
* Constructs a new {@link RecordComponentVisitor}. |
||||
* |
||||
* @param api the ASM API version implemented by this visitor. Must be {@link |
||||
* Opcodes#ASM8_EXPERIMENTAL}. |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public RecordComponentVisitor(final int api) { |
||||
this(api, null); |
||||
} |
||||
|
||||
/** |
||||
* Constructs a new {@link RecordComponentVisitor}. |
||||
* |
||||
* @param api the ASM API version implemented by this visitor. Must be {@link |
||||
* Opcodes#ASM8_EXPERIMENTAL}. |
||||
* @param recordComponentVisitor the record component visitor to which this visitor must delegate |
||||
* method calls. May be null. |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public RecordComponentVisitor( |
||||
final int api, final RecordComponentVisitor recordComponentVisitor) { |
||||
if (api != Opcodes.ASM7 |
||||
&& api != Opcodes.ASM6 |
||||
&& api != Opcodes.ASM5 |
||||
&& api != Opcodes.ASM4 |
||||
&& api != Opcodes.ASM8_EXPERIMENTAL) { |
||||
throw new IllegalArgumentException("Unsupported api " + api); |
||||
} |
||||
if (api == Opcodes.ASM8_EXPERIMENTAL) { |
||||
Constants.checkAsm8Experimental(this); |
||||
} |
||||
this.api = api; |
||||
this.delegate = recordComponentVisitor; |
||||
} |
||||
|
||||
/** |
||||
* The record visitor to which this visitor must delegate method calls. May be {@literal null}. |
||||
* |
||||
* @return the record visitor to which this visitor must delegate method calls or {@literal null}. |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public RecordComponentVisitor getDelegateExperimental() { |
||||
return delegate; |
||||
} |
||||
|
||||
/** |
||||
* Visits an annotation of the record component. |
||||
* |
||||
* @param descriptor the class descriptor of the annotation class. |
||||
* @param visible {@literal true} if the annotation is visible at runtime. |
||||
* @return a visitor to visit the annotation values, or {@literal null} if this visitor is not |
||||
* interested in visiting this annotation. |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public AnnotationVisitor visitAnnotationExperimental( |
||||
final String descriptor, final boolean visible) { |
||||
if (delegate != null) { |
||||
return delegate.visitAnnotationExperimental(descriptor, visible); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Visits an annotation on a type in the record component signature. |
||||
* |
||||
* @param typeRef a reference to the annotated type. The sort of this type reference must be |
||||
* {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link |
||||
* TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See |
||||
* {@link TypeReference}. |
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or |
||||
* static inner type within 'typeRef'. May be {@literal null} if the annotation targets |
||||
* 'typeRef' as a whole. |
||||
* @param descriptor the class descriptor of the annotation class. |
||||
* @param visible {@literal true} if the annotation is visible at runtime. |
||||
* @return a visitor to visit the annotation values, or {@literal null} if this visitor is not |
||||
* interested in visiting this annotation. |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public AnnotationVisitor visitTypeAnnotationExperimental( |
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { |
||||
if (delegate != null) { |
||||
return delegate.visitTypeAnnotationExperimental(typeRef, typePath, descriptor, visible); |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/** |
||||
* Visits a non standard attribute of the record component. |
||||
* |
||||
* @param attribute an attribute. |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public void visitAttributeExperimental(final Attribute attribute) { |
||||
if (delegate != null) { |
||||
delegate.visitAttributeExperimental(attribute); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Visits the end of the record component. This method, which is the last one to be called, is |
||||
* used to inform the visitor that everything have been visited. |
||||
* |
||||
* @deprecated this API is experimental. |
||||
*/ |
||||
@Deprecated |
||||
public void visitEndExperimental() { |
||||
if (delegate != null) { |
||||
delegate.visitEndExperimental(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,242 @@
@@ -0,0 +1,242 @@
|
||||
// ASM: a very small and fast Java bytecode manipulation framework
|
||||
// Copyright (c) 2000-2011 INRIA, France Telecom
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. Neither the name of the copyright holders nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
package org.springframework.asm; |
||||
|
||||
@SuppressWarnings("deprecation") |
||||
final class RecordComponentWriter extends RecordComponentVisitor { |
||||
/** Where the constants used in this RecordComponentWriter must be stored. */ |
||||
private final SymbolTable symbolTable; |
||||
|
||||
// Note: fields are ordered as in the component_info structure, and those related to attributes
|
||||
// are ordered as in Section TODO of the JVMS.
|
||||
// The field accessFlag doesn't exist in the component_info structure but is used to carry
|
||||
// ACC_DEPRECATED which is represented by an attribute in the structure and as an access flag by
|
||||
// ASM.
|
||||
|
||||
/** The access_flags field can only be {@link Opcodes#ACC_DEPRECATED}. */ |
||||
private final int accessFlags; |
||||
|
||||
/** The name_index field of the Record attribute. */ |
||||
private final int nameIndex; |
||||
|
||||
/** The descriptor_index field of the the Record attribute. */ |
||||
private final int descriptorIndex; |
||||
|
||||
/** |
||||
* The signature_index field of the Signature attribute of this record component, or 0 if there is |
||||
* no Signature attribute. |
||||
*/ |
||||
private int signatureIndex; |
||||
|
||||
/** |
||||
* The last runtime visible annotation of this record component. The previous ones can be accessed |
||||
* with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. |
||||
*/ |
||||
private AnnotationWriter lastRuntimeVisibleAnnotation; |
||||
|
||||
/** |
||||
* The last runtime invisible annotation of this record component. The previous ones can be |
||||
* accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. |
||||
*/ |
||||
private AnnotationWriter lastRuntimeInvisibleAnnotation; |
||||
|
||||
/** |
||||
* The last runtime visible type annotation of this record component. The previous ones can be |
||||
* accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. |
||||
*/ |
||||
private AnnotationWriter lastRuntimeVisibleTypeAnnotation; |
||||
|
||||
/** |
||||
* The last runtime invisible type annotation of this record component. The previous ones can be |
||||
* accessed with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. |
||||
*/ |
||||
private AnnotationWriter lastRuntimeInvisibleTypeAnnotation; |
||||
|
||||
/** |
||||
* The first non standard attribute of this record component. The next ones can be accessed with |
||||
* the {@link Attribute#nextAttribute} field. May be {@literal null}. |
||||
* |
||||
* <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit. |
||||
* firstAttribute is actually the last attribute visited in {@link |
||||
* #visitAttributeExperimental(Attribute)}. The {@link #putRecordComponentInfo(ByteVector)} method |
||||
* writes the attributes in the order defined by this list, i.e. in the reverse order specified by |
||||
* the user. |
||||
*/ |
||||
private Attribute firstAttribute; |
||||
|
||||
/** |
||||
* Constructs a new {@link RecordComponentWriter}. |
||||
* |
||||
* @param symbolTable where the constants used in this RecordComponentWriter must be stored. |
||||
* @param accessFlags the record component access flags, only synthetic and/or deprecated. |
||||
* @param name the record component name. |
||||
* @param descriptor the record component descriptor (see {@link Type}). |
||||
* @param signature the record component signature. May be {@literal null}. |
||||
*/ |
||||
RecordComponentWriter( |
||||
final SymbolTable symbolTable, |
||||
final int accessFlags, |
||||
final String name, |
||||
final String descriptor, |
||||
final String signature) { |
||||
super(/* latest api = */ Opcodes.ASM7); |
||||
this.symbolTable = symbolTable; |
||||
this.accessFlags = accessFlags; |
||||
this.nameIndex = symbolTable.addConstantUtf8(name); |
||||
this.descriptorIndex = symbolTable.addConstantUtf8(descriptor); |
||||
if (signature != null) { |
||||
this.signatureIndex = symbolTable.addConstantUtf8(signature); |
||||
} |
||||
} |
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the FieldVisitor abstract class
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override |
||||
public AnnotationVisitor visitAnnotationExperimental( |
||||
final String descriptor, final boolean visible) { |
||||
if (visible) { |
||||
return lastRuntimeVisibleAnnotation = |
||||
AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation); |
||||
} else { |
||||
return lastRuntimeInvisibleAnnotation = |
||||
AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public AnnotationVisitor visitTypeAnnotationExperimental( |
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { |
||||
if (visible) { |
||||
return lastRuntimeVisibleTypeAnnotation = |
||||
AnnotationWriter.create( |
||||
symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation); |
||||
} else { |
||||
return lastRuntimeInvisibleTypeAnnotation = |
||||
AnnotationWriter.create( |
||||
symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void visitAttributeExperimental(final Attribute attribute) { |
||||
// Store the attributes in the <i>reverse</i> order of their visit by this method.
|
||||
attribute.nextAttribute = firstAttribute; |
||||
firstAttribute = attribute; |
||||
} |
||||
|
||||
@Override |
||||
public void visitEndExperimental() { |
||||
// Nothing to do.
|
||||
} |
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* Returns the size of the record component JVMS structure generated by this |
||||
* RecordComponentWriter. Also adds the names of the attributes of this record component in the |
||||
* constant pool. |
||||
* |
||||
* @return the size in bytes of the record_component_info of the Record attribute. |
||||
*/ |
||||
int computeRecordComponentInfoSize() { |
||||
// name_index, descriptor_index and attributes_count fields use 6 bytes.
|
||||
int size = 6; |
||||
size += |
||||
Attribute.computeAttributesSize( |
||||
symbolTable, accessFlags & Opcodes.ACC_DEPRECATED, signatureIndex); |
||||
size += |
||||
AnnotationWriter.computeAnnotationsSize( |
||||
lastRuntimeVisibleAnnotation, |
||||
lastRuntimeInvisibleAnnotation, |
||||
lastRuntimeVisibleTypeAnnotation, |
||||
lastRuntimeInvisibleTypeAnnotation); |
||||
if (firstAttribute != null) { |
||||
size += firstAttribute.computeAttributesSize(symbolTable); |
||||
} |
||||
return size; |
||||
} |
||||
|
||||
/** |
||||
* Puts the content of the record component generated by this RecordComponentWriter into the given |
||||
* ByteVector. |
||||
* |
||||
* @param output where the record_component_info structure must be put. |
||||
*/ |
||||
void putRecordComponentInfo(final ByteVector output) { |
||||
output.putShort(nameIndex).putShort(descriptorIndex); |
||||
// Compute and put the attributes_count field.
|
||||
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
|
||||
int attributesCount = 0; |
||||
if (signatureIndex != 0) { |
||||
++attributesCount; |
||||
} |
||||
if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { |
||||
++attributesCount; |
||||
} |
||||
if (lastRuntimeVisibleAnnotation != null) { |
||||
++attributesCount; |
||||
} |
||||
if (lastRuntimeInvisibleAnnotation != null) { |
||||
++attributesCount; |
||||
} |
||||
if (lastRuntimeVisibleTypeAnnotation != null) { |
||||
++attributesCount; |
||||
} |
||||
if (lastRuntimeInvisibleTypeAnnotation != null) { |
||||
++attributesCount; |
||||
} |
||||
if (firstAttribute != null) { |
||||
attributesCount += firstAttribute.getAttributeCount(); |
||||
} |
||||
output.putShort(attributesCount); |
||||
Attribute.putAttributes(symbolTable, accessFlags, signatureIndex, output); |
||||
AnnotationWriter.putAnnotations( |
||||
symbolTable, |
||||
lastRuntimeVisibleAnnotation, |
||||
lastRuntimeInvisibleAnnotation, |
||||
lastRuntimeVisibleTypeAnnotation, |
||||
lastRuntimeInvisibleTypeAnnotation, |
||||
output); |
||||
if (firstAttribute != null) { |
||||
firstAttribute.putAttributes(symbolTable, output); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Collects the attributes of this record component into the given set of attribute prototypes. |
||||
* |
||||
* @param attributePrototypes a set of attribute prototypes. |
||||
*/ |
||||
final void collectAttributePrototypes(final Attribute.Set attributePrototypes) { |
||||
attributePrototypes.addAttributes(firstAttribute); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue