mirror of
https://github.com/revanced/smali.git
synced 2025-05-19 15:37:06 +02:00
Change how the parent is determined for AnnotationDirectoryItem and ClassDataItem
This commit is contained in:
parent
097b40531b
commit
a59fe7e523
@ -48,16 +48,6 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private ParameterAnnotation[] parameterAnnotations;
|
private ParameterAnnotation[] parameterAnnotations;
|
||||||
|
|
||||||
/**
|
|
||||||
* typically each AnnotationDirectoryItem will have a distinct parent. The only case that isn't true is when
|
|
||||||
* the AnnotationDirectoryItem *only* contains class annotations, with no other type of annotation. In that
|
|
||||||
* case, the same AnnotationDirectoryItem could be referenced from multiple classes.
|
|
||||||
* This isn't a problem though, because this field is only used in compareTo to determine the sort order, which
|
|
||||||
* which knows it should handle a null value as a special case
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
private ClassDefItem parent = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new uninitialized <code>AnnotationDirectoryItem</code>
|
* Creates a new uninitialized <code>AnnotationDirectoryItem</code>
|
||||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||||
@ -211,8 +201,9 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
|||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
protected void writeItem(AnnotatedOutput out) {
|
protected void writeItem(AnnotatedOutput out) {
|
||||||
if (out.annotates()) {
|
if (out.annotates()) {
|
||||||
if (!isInternable() && parent != null) {
|
TypeIdItem parentType = getParentType();
|
||||||
out.annotate(0, parent.getClassType().getTypeDescriptor());
|
if (parentType != null) {
|
||||||
|
out.annotate(0, parentType.getTypeDescriptor());
|
||||||
}
|
}
|
||||||
if (classAnnotations != null) {
|
if (classAnnotations != null) {
|
||||||
out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset()));
|
out.annotate(4, "class_annotations_off: 0x" + Integer.toHexString(classAnnotations.getOffset()));
|
||||||
@ -303,29 +294,60 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
|||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public String getConciseIdentity() {
|
public String getConciseIdentity() {
|
||||||
if (parent == null) {
|
TypeIdItem parentType = getParentType();
|
||||||
|
if (parentType == null) {
|
||||||
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
|
return "annotation_directory_item @0x" + Integer.toHexString(getOffset());
|
||||||
}
|
}
|
||||||
return "annotation_directory_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() + ")";
|
return "annotation_directory_item @0x" + Integer.toHexString(getOffset()) +
|
||||||
|
" (" + parentType.getTypeDescriptor() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public int compareTo(AnnotationDirectoryItem o) {
|
public int compareTo(AnnotationDirectoryItem o) {
|
||||||
Preconditions.checkNotNull(o);
|
Preconditions.checkNotNull(o);
|
||||||
if (!isInternable()) {
|
|
||||||
if (!o.isInternable()) {
|
TypeIdItem parentType = getParentType();
|
||||||
Preconditions.checkState(parent != null && o.parent != null,
|
TypeIdItem otherParentType = o.getParentType();
|
||||||
"Must call setParent before comparing AnnotationDirectoryItem instances");
|
if (parentType != null) {
|
||||||
return parent.compareTo(o.parent);
|
if (otherParentType != null) {
|
||||||
|
return parentType.compareTo(otherParentType);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (otherParentType != null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classAnnotations != null) {
|
||||||
|
if (o.classAnnotations != null) {
|
||||||
|
return classAnnotations.compareTo(o.classAnnotations);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!o.isInternable()) {
|
/**
|
||||||
return 1;
|
* Returns the parent type for an AnnotationDirectoryItem that is guaranteed to have a single parent, or null
|
||||||
|
* for one that may be referenced by multiple classes.
|
||||||
|
*
|
||||||
|
* Specifically, the AnnotationDirectoryItem may be referenced by multiple classes if it has only class annotations,
|
||||||
|
* but not field/method/parameter annotations.
|
||||||
|
*
|
||||||
|
* @return The parent type for this AnnotationDirectoryItem, or null if it may have multiple parents
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public TypeIdItem getParentType() {
|
||||||
|
if (fieldAnnotations != null && fieldAnnotations.length > 0) {
|
||||||
|
return fieldAnnotations[0].field.getContainingClass();
|
||||||
}
|
}
|
||||||
|
if (methodAnnotations != null && methodAnnotations.length > 0) {
|
||||||
return classAnnotations.compareTo(o.classAnnotations);
|
return methodAnnotations[0].method.getContainingClass();
|
||||||
|
}
|
||||||
|
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
|
||||||
|
return parameterAnnotations[0].method.getContainingClass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -425,6 +447,17 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
|||||||
return parameterAnnotations[index].annotationSet;
|
return parameterAnnotations[index].annotationSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getClassAnnotationCount() {
|
||||||
|
if (classAnnotations == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
AnnotationItem[] annotations = classAnnotations.getAnnotations();
|
||||||
|
return annotations.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The number of field annotations in this <code>AnnotationDirectoryItem</code>
|
* @return The number of field annotations in this <code>AnnotationDirectoryItem</code>
|
||||||
*/
|
*/
|
||||||
@ -455,41 +488,18 @@ public class AnnotationDirectoryItem extends Item<AnnotationDirectoryItem> {
|
|||||||
return parameterAnnotations.length;
|
return parameterAnnotations.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if this <code>AnnotationDirectoryItem</code> is internable. It is only internable if it has
|
|
||||||
* only class annotations, but no field, method or parameter annotations
|
|
||||||
*/
|
|
||||||
private boolean isInternable() {
|
|
||||||
return classAnnotations != null &&
|
|
||||||
(fieldAnnotations == null || fieldAnnotations.length == 0) &&
|
|
||||||
(methodAnnotations == null || methodAnnotations.length == 0) &&
|
|
||||||
(parameterAnnotations == null || parameterAnnotations.length == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the <code>ClassDefItem</code> that this <code>AnnotationDirectoryItem</code> is associated with.
|
|
||||||
*
|
|
||||||
* @param classDefItem the <code>ClassDefItem</code> that this <code>AnnotationDirectoryItem</code> is associated
|
|
||||||
* with.
|
|
||||||
*/
|
|
||||||
protected void setParent(ClassDefItem classDefItem) {
|
|
||||||
// If this AnnotationDirectoryItem is internable, then setParent may be called multiple times, because it is
|
|
||||||
// reused for multiple classes. In this case, the parent field isn't used, so it doesn't matter if we overwrite
|
|
||||||
// it.
|
|
||||||
// If, on the other hand, it is not internable, we want to make sure that only a single parent is set. parent
|
|
||||||
// should either be null, or be equal to the new parent
|
|
||||||
Preconditions.checkState(this.isInternable() || (parent == null || parent.equals(classDefItem)));
|
|
||||||
this.parent = classDefItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
// An instance is internable only if it has only class annotations, but no other type of annotation
|
// If the item has a single parent, we can use the re-use the identity (hash) of that parent
|
||||||
if (!isInternable()) {
|
TypeIdItem parentType = getParentType();
|
||||||
return super.hashCode();
|
if (parentType != null) {
|
||||||
|
return parentType.hashCode();
|
||||||
}
|
}
|
||||||
|
if (classAnnotations != null) {
|
||||||
return classAnnotations.hashCode();
|
return classAnnotations.hashCode();
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
@ -45,9 +45,6 @@ public class ClassDataItem extends Item<ClassDataItem> {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private EncodedMethod[] virtualMethods = null;
|
private EncodedMethod[] virtualMethods = null;
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private ClassDefItem parent = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new uninitialized <code>ClassDataItem</code>
|
* Creates a new uninitialized <code>ClassDataItem</code>
|
||||||
* @param dexFile The <code>DexFile</code> that this item belongs to
|
* @param dexFile The <code>DexFile</code> that this item belongs to
|
||||||
@ -384,14 +381,17 @@ public class ClassDataItem extends Item<ClassDataItem> {
|
|||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public String getConciseIdentity() {
|
public String getConciseIdentity() {
|
||||||
if (parent == null) {
|
TypeIdItem parentType = getParentType();
|
||||||
|
if (parentType == null) {
|
||||||
return "class_data_item @0x" + Integer.toHexString(getOffset());
|
return "class_data_item @0x" + Integer.toHexString(getOffset());
|
||||||
}
|
}
|
||||||
return "class_data_item @0x" + Integer.toHexString(getOffset()) + " (" + parent.getClassType() +")";
|
return "class_data_item @0x" + Integer.toHexString(getOffset()) + " (" + parentType.getTypeDescriptor() +")";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
public int compareTo(ClassDataItem other) {
|
public int compareTo(ClassDataItem other) {
|
||||||
|
Preconditions.checkNotNull(other);
|
||||||
|
|
||||||
// An empty CodeDataItem may be shared by multiple ClassDefItems, so we can't use parent in this case
|
// An empty CodeDataItem may be shared by multiple ClassDefItems, so we can't use parent in this case
|
||||||
if (isEmpty()) {
|
if (isEmpty()) {
|
||||||
if (other.isEmpty()) {
|
if (other.isEmpty()) {
|
||||||
@ -403,25 +403,54 @@ public class ClassDataItem extends Item<ClassDataItem> {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent == null) {
|
TypeIdItem parentType = getParentType();
|
||||||
if (other.parent == null) {
|
TypeIdItem otherParentType= other.getParentType();
|
||||||
|
if (parentType == null) {
|
||||||
|
if (otherParentType == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (other.parent == null) {
|
if (otherParentType == null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return parent.compareTo(other.parent);
|
return parentType.compareTo(otherParentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
// If the item has a single parent, we can use the re-use the identity (hash) of that parent
|
||||||
|
TypeIdItem parentType = getParentType();
|
||||||
|
if (parentType != null) {
|
||||||
|
return parentType.hashCode();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the <code>ClassDefItem</code> that this <code>ClassDataItem</code> is associated with
|
* Returns the parent type for a non-empty ClassDataItem, or null for an empty one (which could be referenced by
|
||||||
* @param classDefItem the <code>ClassDefItem</code> that this <code>ClassDataItem</code> is associated with
|
* multiple ClassDefItem parents)
|
||||||
|
*
|
||||||
|
* Specifically, the AnnotationDirectoryItem may be referenced by multiple classes if it has only class annotations,
|
||||||
|
* but not field/method/parameter annotations.
|
||||||
|
*
|
||||||
|
* @return The parent type for this AnnotationDirectoryItem, or null if it may have multiple parents
|
||||||
*/
|
*/
|
||||||
protected void setParent(ClassDefItem classDefItem) {
|
@Nullable
|
||||||
Preconditions.checkState(parent == null || parent.compareTo(classDefItem) == 0 || isEmpty());
|
public TypeIdItem getParentType() {
|
||||||
parent = classDefItem;
|
if (staticFields != null && staticFields.length > 0) {
|
||||||
|
return staticFields[0].field.getContainingClass();
|
||||||
|
}
|
||||||
|
if (instanceFields != null && instanceFields.length > 0) {
|
||||||
|
return instanceFields[0].field.getContainingClass();
|
||||||
|
}
|
||||||
|
if (directMethods != null && directMethods.length > 0) {
|
||||||
|
return directMethods[0].method.getContainingClass();
|
||||||
|
}
|
||||||
|
if (virtualMethods != null && virtualMethods.length > 0) {
|
||||||
|
return virtualMethods[0].method.getContainingClass();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
package org.jf.dexlib;
|
package org.jf.dexlib;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
|
import org.jf.dexlib.EncodedValue.ArrayEncodedSubValue;
|
||||||
import org.jf.dexlib.EncodedValue.EncodedValue;
|
import org.jf.dexlib.EncodedValue.EncodedValue;
|
||||||
import org.jf.dexlib.Util.AccessFlags;
|
import org.jf.dexlib.Util.AccessFlags;
|
||||||
@ -88,13 +87,6 @@ public class ClassDefItem extends Item<ClassDefItem> {
|
|||||||
this.annotations = annotations;
|
this.annotations = annotations;
|
||||||
this.classData = classData;
|
this.classData = classData;
|
||||||
this.staticFieldInitializers = staticFieldInitializers;
|
this.staticFieldInitializers = staticFieldInitializers;
|
||||||
|
|
||||||
if (classData != null) {
|
|
||||||
classData.setParent(this);
|
|
||||||
}
|
|
||||||
if (annotations != null) {
|
|
||||||
annotations.setParent(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,13 +137,6 @@ public class ClassDefItem extends Item<ClassDefItem> {
|
|||||||
classData = (ClassDataItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
|
classData = (ClassDataItem)readContext.getOptionalOffsettedItemByOffset(ItemType.TYPE_CLASS_DATA_ITEM, in.readInt());
|
||||||
staticFieldInitializers = (EncodedArrayItem)readContext.getOptionalOffsettedItemByOffset(
|
staticFieldInitializers = (EncodedArrayItem)readContext.getOptionalOffsettedItemByOffset(
|
||||||
ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt());
|
ItemType.TYPE_ENCODED_ARRAY_ITEM, in.readInt());
|
||||||
|
|
||||||
if (classData != null) {
|
|
||||||
classData.setParent(this);
|
|
||||||
}
|
|
||||||
if (annotations != null) {
|
|
||||||
annotations.setParent(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@ -344,7 +329,7 @@ public class ClassDefItem extends Item<ClassDefItem> {
|
|||||||
*/
|
*/
|
||||||
private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
|
private static EncodedArrayItem makeStaticFieldInitializersItem(DexFile dexFile,
|
||||||
@Nonnull List<StaticFieldInitializer> staticFieldInitializers) {
|
@Nonnull List<StaticFieldInitializer> staticFieldInitializers) {
|
||||||
if (staticFieldInitializers == null || staticFieldInitializers.size() == 0) {
|
if (staticFieldInitializers.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user