mirror of
https://github.com/revanced/Apktool.git
synced 2025-05-01 14:44:26 +02:00
Make smali respect order of implements
Previously smali would reorder implements directives to be alphabetical in the dex file. In the Java 8 Language the order of interfaces may affect the order of initializer invocation when using default methods. Therefore we will preserve this order in smali/baksmai. Bug: 24338722 Change-Id: I6851b02a5402c7d4cd4b60af54052c320e48d0bf
This commit is contained in:
parent
7a3d09cc47
commit
89ef73b927
@ -146,8 +146,7 @@ public class ClassDefinition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeInterfaces(IndentingWriter writer) throws IOException {
|
private void writeInterfaces(IndentingWriter writer) throws IOException {
|
||||||
List<String> interfaces = Lists.newArrayList(classDef.getInterfaces());
|
List<String> interfaces = classDef.getInterfaces();
|
||||||
Collections.sort(interfaces);
|
|
||||||
|
|
||||||
if (interfaces.size() != 0) {
|
if (interfaces.size() != 0) {
|
||||||
writer.write('\n');
|
writer.write('\n');
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2015, Google Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are
|
||||||
|
* met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * 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.
|
||||||
|
* * Neither the name of Google Inc. 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.jf.baksmali;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class InterfaceOrderTest extends IdenticalRoundtripTest {
|
||||||
|
@Test
|
||||||
|
public void testInterfaceOrder() {
|
||||||
|
runTest("InterfaceOrder", new baksmaliOptions());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
.class public LInterfaceOrder;
|
||||||
|
.super Ljava/lang/Object;
|
||||||
|
|
||||||
|
# Note how these two interfaces are not in alphabetical order
|
||||||
|
.implements Ljava/io/Serializable;
|
||||||
|
.implements Ljava/util/EventListener;
|
||||||
|
.implements Ljava/lang/Runnable;
|
||||||
|
.implements Ljava/io/Flushable;
|
||||||
|
.implements Ljava/lang/Clonable;
|
||||||
|
.implements Ljava/util/Observer;
|
||||||
|
.implements Ljava/io/Closeable;
|
||||||
|
|
||||||
|
# direct methods
|
||||||
|
.method public constructor <init>()V
|
||||||
|
.registers 1
|
||||||
|
return-void
|
||||||
|
.end method
|
||||||
|
|
||||||
|
.method public close()V
|
||||||
|
.registers 1
|
||||||
|
return-void
|
||||||
|
.end method
|
||||||
|
|
||||||
|
.method public flush()V
|
||||||
|
.registers 1
|
||||||
|
return-void
|
||||||
|
.end method
|
||||||
|
|
||||||
|
.method public run()V
|
||||||
|
.registers 1
|
||||||
|
return-void
|
||||||
|
.end method
|
||||||
|
|
||||||
|
.method public update(Ljava/util/Observable;Ljava/lang/Object;)V
|
||||||
|
.registers 3
|
||||||
|
return-void
|
||||||
|
.end method
|
@ -33,6 +33,7 @@ package org.jf.dexlib2.analysis.reflection;
|
|||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterators;
|
import com.google.common.collect.Iterators;
|
||||||
import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils;
|
import org.jf.dexlib2.analysis.reflection.util.ReflectionUtils;
|
||||||
@ -48,6 +49,7 @@ import java.lang.reflect.Constructor;
|
|||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.AbstractSet;
|
import java.util.AbstractSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,23 +80,17 @@ public class ReflectionClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
return ReflectionUtils.javaToDexName(superClass.getName());
|
return ReflectionUtils.javaToDexName(superClass.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public Set<String> getInterfaces() {
|
@Nonnull @Override public List<String> getInterfaces() {
|
||||||
return new AbstractSet<String>() {
|
return ImmutableList.copyOf(Iterators.transform(Iterators.forArray(cls.getInterfaces()), new Function<Class, String>() {
|
||||||
@Nonnull @Override public Iterator<String> iterator() {
|
@Nullable
|
||||||
return Iterators.transform(Iterators.forArray(cls.getInterfaces()), new Function<Class, String>() {
|
@Override
|
||||||
@Nullable @Override public String apply(@Nullable Class input) {
|
public String apply(@Nullable Class input) {
|
||||||
if (input == null) {
|
if (input == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ReflectionUtils.javaToDexName(input.getName());
|
return ReflectionUtils.javaToDexName(input.getName());
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}));
|
||||||
@Override public int size() {
|
|
||||||
return cls.getInterfaces().length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @Override public String getSourceFile() {
|
@Nullable @Override public String getSourceFile() {
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.dexbacked;
|
package org.jf.dexlib2.dexbacked;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import org.jf.dexlib2.base.reference.BaseTypeReference;
|
import org.jf.dexlib2.base.reference.BaseTypeReference;
|
||||||
@ -47,7 +48,9 @@ import org.jf.dexlib2.immutable.reference.ImmutableMethodReference;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.AbstractList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
|
public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
|
||||||
@ -114,21 +117,21 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getInterfaces() {
|
public List<String> getInterfaces() {
|
||||||
final int interfacesOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.INTERFACES_OFFSET);
|
final int interfacesOffset = dexFile.readSmallUint(classDefOffset + ClassDefItem.INTERFACES_OFFSET);
|
||||||
if (interfacesOffset > 0) {
|
if (interfacesOffset > 0) {
|
||||||
final int size = dexFile.readSmallUint(interfacesOffset);
|
final int size = dexFile.readSmallUint(interfacesOffset);
|
||||||
return new FixedSizeSet<String>() {
|
return new AbstractList<String>() {
|
||||||
@Nonnull
|
|
||||||
@Override
|
@Override
|
||||||
public String readItem(int index) {
|
@Nonnull
|
||||||
|
public String get(int index) {
|
||||||
return dexFile.getType(dexFile.readUshort(interfacesOffset + 4 + (2*index)));
|
return dexFile.getType(dexFile.readUshort(interfacesOffset + 4 + (2*index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public int size() { return size; }
|
@Override public int size() { return size; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return ImmutableSet.of();
|
return ImmutableList.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -35,6 +35,7 @@ import org.jf.dexlib2.iface.reference.TypeReference;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,11 +73,11 @@ public interface ClassDef extends TypeReference, Annotatable {
|
|||||||
@Nullable String getSuperclass();
|
@Nullable String getSuperclass();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of the interfaces that this class implements.
|
* Gets a list of the interfaces that this class implements.
|
||||||
*
|
*
|
||||||
* @return A set of the interfaces that this class implements
|
* @return A list of the interfaces that this class implements
|
||||||
*/
|
*/
|
||||||
@Nonnull Set<String> getInterfaces();
|
@Nonnull List<String> getInterfaces();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name of the primary source file that this class is defined in, if available.
|
* Gets the name of the primary source file that this class is defined in, if available.
|
||||||
|
@ -47,12 +47,13 @@ import javax.annotation.Nullable;
|
|||||||
import java.util.AbstractCollection;
|
import java.util.AbstractCollection;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
|
public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
|
||||||
@Nonnull protected final String type;
|
@Nonnull protected final String type;
|
||||||
protected final int accessFlags;
|
protected final int accessFlags;
|
||||||
@Nullable protected final String superclass;
|
@Nullable protected final String superclass;
|
||||||
@Nonnull protected final ImmutableSet<String> interfaces;
|
@Nonnull protected final ImmutableList<String> interfaces;
|
||||||
@Nullable protected final String sourceFile;
|
@Nullable protected final String sourceFile;
|
||||||
@Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations;
|
@Nonnull protected final ImmutableSet<? extends ImmutableAnnotation> annotations;
|
||||||
@Nonnull protected final ImmutableSortedSet<? extends ImmutableField> staticFields;
|
@Nonnull protected final ImmutableSortedSet<? extends ImmutableField> staticFields;
|
||||||
@ -78,7 +79,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
this.accessFlags = accessFlags;
|
this.accessFlags = accessFlags;
|
||||||
this.superclass = superclass;
|
this.superclass = superclass;
|
||||||
this.interfaces = interfaces==null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(interfaces);
|
this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces);
|
||||||
this.sourceFile = sourceFile;
|
this.sourceFile = sourceFile;
|
||||||
this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
|
this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
|
||||||
this.staticFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC));
|
this.staticFields = ImmutableField.immutableSetOf(Iterables.filter(fields, FieldUtil.FIELD_IS_STATIC));
|
||||||
@ -100,7 +101,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
this.accessFlags = accessFlags;
|
this.accessFlags = accessFlags;
|
||||||
this.superclass = superclass;
|
this.superclass = superclass;
|
||||||
this.interfaces = interfaces==null ? ImmutableSet.<String>of() : ImmutableSet.copyOf(interfaces);
|
this.interfaces = interfaces==null ? ImmutableList.<String>of() : ImmutableList.copyOf(interfaces);
|
||||||
this.sourceFile = sourceFile;
|
this.sourceFile = sourceFile;
|
||||||
this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
|
this.annotations = ImmutableAnnotation.immutableSetOf(annotations);
|
||||||
this.staticFields = ImmutableField.immutableSetOf(staticFields);
|
this.staticFields = ImmutableField.immutableSetOf(staticFields);
|
||||||
@ -112,7 +113,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
public ImmutableClassDef(@Nonnull String type,
|
public ImmutableClassDef(@Nonnull String type,
|
||||||
int accessFlags,
|
int accessFlags,
|
||||||
@Nullable String superclass,
|
@Nullable String superclass,
|
||||||
@Nullable ImmutableSet<String> interfaces,
|
@Nullable ImmutableList<String> interfaces,
|
||||||
@Nullable String sourceFile,
|
@Nullable String sourceFile,
|
||||||
@Nullable ImmutableSet<? extends ImmutableAnnotation> annotations,
|
@Nullable ImmutableSet<? extends ImmutableAnnotation> annotations,
|
||||||
@Nullable ImmutableSortedSet<? extends ImmutableField> staticFields,
|
@Nullable ImmutableSortedSet<? extends ImmutableField> staticFields,
|
||||||
@ -122,7 +123,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
this.accessFlags = accessFlags;
|
this.accessFlags = accessFlags;
|
||||||
this.superclass = superclass;
|
this.superclass = superclass;
|
||||||
this.interfaces = ImmutableUtils.nullToEmptySet(interfaces);
|
this.interfaces = ImmutableUtils.nullToEmptyList(interfaces);
|
||||||
this.sourceFile = sourceFile;
|
this.sourceFile = sourceFile;
|
||||||
this.annotations = ImmutableUtils.nullToEmptySet(annotations);
|
this.annotations = ImmutableUtils.nullToEmptySet(annotations);
|
||||||
this.staticFields = ImmutableUtils.nullToEmptySortedSet(staticFields);
|
this.staticFields = ImmutableUtils.nullToEmptySortedSet(staticFields);
|
||||||
@ -151,7 +152,7 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
@Nonnull @Override public String getType() { return type; }
|
@Nonnull @Override public String getType() { return type; }
|
||||||
@Override public int getAccessFlags() { return accessFlags; }
|
@Override public int getAccessFlags() { return accessFlags; }
|
||||||
@Nullable @Override public String getSuperclass() { return superclass; }
|
@Nullable @Override public String getSuperclass() { return superclass; }
|
||||||
@Nonnull @Override public ImmutableSet<String> getInterfaces() { return interfaces; }
|
@Nonnull @Override public ImmutableList<String> getInterfaces() { return interfaces; }
|
||||||
@Nullable @Override public String getSourceFile() { return sourceFile; }
|
@Nullable @Override public String getSourceFile() { return sourceFile; }
|
||||||
@Nonnull @Override public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; }
|
@Nonnull @Override public ImmutableSet<? extends ImmutableAnnotation> getAnnotations() { return annotations; }
|
||||||
@Nonnull @Override public ImmutableSet<? extends ImmutableField> getStaticFields() { return staticFields; }
|
@Nonnull @Override public ImmutableSet<? extends ImmutableField> getStaticFields() { return staticFields; }
|
||||||
|
@ -41,6 +41,7 @@ import org.jf.dexlib2.iface.Method;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ClassDefRewriter implements Rewriter<ClassDef> {
|
public class ClassDefRewriter implements Rewriter<ClassDef> {
|
||||||
@ -73,8 +74,8 @@ public class ClassDefRewriter implements Rewriter<ClassDef> {
|
|||||||
return RewriterUtils.rewriteNullable(rewriters.getTypeRewriter(), classDef.getSuperclass());
|
return RewriterUtils.rewriteNullable(rewriters.getTypeRewriter(), classDef.getSuperclass());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override @Nonnull public Set<String> getInterfaces() {
|
@Override @Nonnull public List<String> getInterfaces() {
|
||||||
return RewriterUtils.rewriteSet(rewriters.getTypeRewriter(), classDef.getInterfaces());
|
return RewriterUtils.rewriteList(rewriters.getTypeRewriter(), classDef.getInterfaces());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override @Nullable public String getSourceFile() {
|
@Override @Nullable public String getSourceFile() {
|
||||||
|
@ -53,7 +53,7 @@ public interface ClassSection<StringKey extends CharSequence, TypeKey extends Ch
|
|||||||
@Nonnull TypeKey getType(@Nonnull ClassKey key);
|
@Nonnull TypeKey getType(@Nonnull ClassKey key);
|
||||||
int getAccessFlags(@Nonnull ClassKey key);
|
int getAccessFlags(@Nonnull ClassKey key);
|
||||||
@Nullable TypeKey getSuperclass(@Nonnull ClassKey key);
|
@Nullable TypeKey getSuperclass(@Nonnull ClassKey key);
|
||||||
@Nullable TypeListKey getSortedInterfaces(@Nonnull ClassKey key);
|
@Nullable TypeListKey getInterfaces(@Nonnull ClassKey key);
|
||||||
@Nullable StringKey getSourceFile(@Nonnull ClassKey key);
|
@Nullable StringKey getSourceFile(@Nonnull ClassKey key);
|
||||||
@Nullable Collection<? extends EncodedValue> getStaticInitializers(@Nonnull ClassKey key);
|
@Nullable Collection<? extends EncodedValue> getStaticInitializers(@Nonnull ClassKey key);
|
||||||
|
|
||||||
|
@ -433,7 +433,7 @@ public abstract class DexWriter<
|
|||||||
nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, superEntry);
|
nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, superEntry);
|
||||||
|
|
||||||
// then, try to write interfaces
|
// then, try to write interfaces
|
||||||
for (TypeKey interfaceTypeKey: typeListSection.getTypes(classSection.getSortedInterfaces(key))) {
|
for (TypeKey interfaceTypeKey: typeListSection.getTypes(classSection.getInterfaces(key))) {
|
||||||
Map.Entry<? extends ClassKey, Integer> interfaceEntry = classSection.getClassEntryByType(interfaceTypeKey);
|
Map.Entry<? extends ClassKey, Integer> interfaceEntry = classSection.getClassEntryByType(interfaceTypeKey);
|
||||||
nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, interfaceEntry);
|
nextIndex = writeClass(indexWriter, offsetWriter, nextIndex, interfaceEntry);
|
||||||
}
|
}
|
||||||
@ -446,7 +446,7 @@ public abstract class DexWriter<
|
|||||||
indexWriter.writeInt(typeSection.getItemIndex(classSection.getType(key)));
|
indexWriter.writeInt(typeSection.getItemIndex(classSection.getType(key)));
|
||||||
indexWriter.writeInt(classSection.getAccessFlags(key));
|
indexWriter.writeInt(classSection.getAccessFlags(key));
|
||||||
indexWriter.writeInt(typeSection.getNullableItemIndex(classSection.getSuperclass(key)));
|
indexWriter.writeInt(typeSection.getNullableItemIndex(classSection.getSuperclass(key)));
|
||||||
indexWriter.writeInt(typeListSection.getNullableItemOffset(classSection.getSortedInterfaces(key)));
|
indexWriter.writeInt(typeListSection.getNullableItemOffset(classSection.getInterfaces(key)));
|
||||||
indexWriter.writeInt(stringSection.getNullableItemIndex(classSection.getSourceFile(key)));
|
indexWriter.writeInt(stringSection.getNullableItemIndex(classSection.getSourceFile(key)));
|
||||||
indexWriter.writeInt(classSection.getAnnotationDirectoryOffset(key));
|
indexWriter.writeInt(classSection.getAnnotationDirectoryOffset(key));
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.writer.builder;
|
package org.jf.dexlib2.writer.builder;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Functions;
|
import com.google.common.base.Functions;
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.*;
|
||||||
import org.jf.dexlib2.base.reference.BaseTypeReference;
|
import org.jf.dexlib2.base.reference.BaseTypeReference;
|
||||||
@ -101,16 +102,8 @@ public class BuilderClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
@Nonnull @Override public SortedSet<BuilderMethod> getVirtualMethods() { return virtualMethods; }
|
@Nonnull @Override public SortedSet<BuilderMethod> getVirtualMethods() { return virtualMethods; }
|
||||||
|
|
||||||
@Nonnull @Override
|
@Nonnull @Override
|
||||||
public Set<String> getInterfaces() {
|
public List<String> getInterfaces() {
|
||||||
return new AbstractSet<String>() {
|
return Lists.transform(this.interfaces, Functions.toStringFunction());
|
||||||
@Nonnull @Override public Iterator<String> iterator() {
|
|
||||||
return Iterators.transform(interfaces.iterator(), Functions.toStringFunction());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public int size() {
|
|
||||||
return interfaces.size();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public Collection<BuilderField> getFields() {
|
@Nonnull @Override public Collection<BuilderField> getFields() {
|
||||||
|
@ -122,7 +122,7 @@ public class BuilderClassPool implements ClassSection<BuilderStringReference, Bu
|
|||||||
return builderClassDef.superclass;
|
return builderClassDef.superclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @Override public BuilderTypeList getSortedInterfaces(@Nonnull BuilderClassDef builderClassDef) {
|
@Nullable @Override public BuilderTypeList getInterfaces(@Nonnull BuilderClassDef builderClassDef) {
|
||||||
return builderClassDef.interfaces;
|
return builderClassDef.interfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ import com.google.common.base.Function;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Iterators;
|
import com.google.common.collect.Iterators;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import org.jf.dexlib2.ValueType;
|
import org.jf.dexlib2.ValueType;
|
||||||
import org.jf.dexlib2.iface.Annotation;
|
import org.jf.dexlib2.iface.Annotation;
|
||||||
import org.jf.dexlib2.iface.MethodImplementation;
|
import org.jf.dexlib2.iface.MethodImplementation;
|
||||||
@ -117,16 +118,15 @@ public class DexBuilder extends DexWriter<BuilderStringReference, BuilderStringR
|
|||||||
if (interfaces == null) {
|
if (interfaces == null) {
|
||||||
interfaces = ImmutableList.of();
|
interfaces = ImmutableList.of();
|
||||||
} else {
|
} else {
|
||||||
interfaces = Lists.newArrayList(interfaces);
|
Set<String> interfaces_copy = Sets.newHashSet(interfaces);
|
||||||
Collections.sort(interfaces);
|
|
||||||
String prev = null;
|
|
||||||
Iterator<String> interfaceIterator = interfaces.iterator();
|
Iterator<String> interfaceIterator = interfaces.iterator();
|
||||||
while (interfaceIterator.hasNext()) {
|
while (interfaceIterator.hasNext()) {
|
||||||
String iface = interfaceIterator.next();
|
String iface = interfaceIterator.next();
|
||||||
if (prev != null && iface.equals(prev)) {
|
if (!interfaces_copy.contains(iface)) {
|
||||||
interfaceIterator.remove();
|
interfaceIterator.remove();
|
||||||
|
} else {
|
||||||
|
interfaces_copy.remove(iface);
|
||||||
}
|
}
|
||||||
prev = iface;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ public class ClassPool implements ClassSection<CharSequence, CharSequence,
|
|||||||
return classDef.getSuperclass();
|
return classDef.getSuperclass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @Override public TypeListPool.Key<SortedSet<String>> getSortedInterfaces(@Nonnull PoolClassDef classDef) {
|
@Nullable @Override public TypeListPool.Key<List<String>> getInterfaces(@Nonnull PoolClassDef classDef) {
|
||||||
return classDef.interfaces;
|
return classDef.interfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ import java.util.*;
|
|||||||
|
|
||||||
class PoolClassDef extends BaseTypeReference implements ClassDef {
|
class PoolClassDef extends BaseTypeReference implements ClassDef {
|
||||||
@Nonnull final ClassDef classDef;
|
@Nonnull final ClassDef classDef;
|
||||||
@Nonnull final TypeListPool.Key<SortedSet<String>> interfaces;
|
@Nonnull final TypeListPool.Key<List<String>> interfaces;
|
||||||
@Nonnull final ImmutableSortedSet<Field> staticFields;
|
@Nonnull final ImmutableSortedSet<Field> staticFields;
|
||||||
@Nonnull final ImmutableSortedSet<Field> instanceFields;
|
@Nonnull final ImmutableSortedSet<Field> instanceFields;
|
||||||
@Nonnull final ImmutableSortedSet<PoolMethod> directMethods;
|
@Nonnull final ImmutableSortedSet<PoolMethod> directMethods;
|
||||||
@ -56,7 +56,7 @@ class PoolClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
PoolClassDef(@Nonnull ClassDef classDef) {
|
PoolClassDef(@Nonnull ClassDef classDef) {
|
||||||
this.classDef = classDef;
|
this.classDef = classDef;
|
||||||
|
|
||||||
interfaces = new TypeListPool.Key<SortedSet<String>>(ImmutableSortedSet.copyOf(classDef.getInterfaces()));
|
interfaces = new TypeListPool.Key<List<String>>(ImmutableList.copyOf(classDef.getInterfaces()));
|
||||||
staticFields = ImmutableSortedSet.copyOf(classDef.getStaticFields());
|
staticFields = ImmutableSortedSet.copyOf(classDef.getStaticFields());
|
||||||
instanceFields = ImmutableSortedSet.copyOf(classDef.getInstanceFields());
|
instanceFields = ImmutableSortedSet.copyOf(classDef.getInstanceFields());
|
||||||
directMethods = ImmutableSortedSet.copyOf(
|
directMethods = ImmutableSortedSet.copyOf(
|
||||||
@ -77,7 +77,7 @@ class PoolClassDef extends BaseTypeReference implements ClassDef {
|
|||||||
return classDef.getSuperclass();
|
return classDef.getSuperclass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull @Override public SortedSet<String> getInterfaces() {
|
@Nonnull @Override public List<String> getInterfaces() {
|
||||||
return interfaces.types;
|
return interfaces.types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user