Skip to content

Commit

Permalink
[DEX] Bulk type rename
Browse files Browse the repository at this point in the history
  • Loading branch information
REAndroid committed Mar 2, 2024
1 parent b7c16b4 commit 31834dc
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 248 deletions.
45 changes: 44 additions & 1 deletion src/main/java/com/reandroid/dex/key/KeyPair.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
package com.reandroid.dex.key;

import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.collection.ArrayCollection;
import com.reandroid.utils.collection.ComputeIterator;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

public class KeyPair<T1 extends Key, T2 extends Key> implements Comparable<KeyPair<Key, Key>>{
Expand Down Expand Up @@ -48,13 +53,42 @@ public void setSecond(T2 second) {
this.second = second;
}

public KeyPair<T2, T1> flip(){
return new KeyPair<>(getSecond(), getFirst());
}
public boolean isValid(){
T1 t1 = getFirst();
if(t1 == null){
return false;
}
T2 t2 = getSecond();
if(t2 == null){
return false;
}
return !t1.equals(t2);
}

@Override
public int compareTo(KeyPair<Key, Key> pair) {
if(pair == null){
return -1;
}
return CompareUtil.compare(getFirst(), pair.getFirst());
Key key1 = this.getFirst();
Key key2 = pair.getFirst();
if(key1 == null){
if(key2 == null){
return 0;
}
return 1;
}
if(key2 == null){
return -1;
}
int i = key1.getDeclaring().compareInnerFirst(key2.getDeclaring());
if(i == 0){
i = CompareUtil.compare(key1, key2);
}
return i;
}
@Override
public boolean equals(Object obj) {
Expand All @@ -80,4 +114,13 @@ public int hashCode() {
public String toString() {
return getFirst() + "=" + getSecond();
}

public static<E1 extends Key, E2 extends Key> Iterator<KeyPair<E2, E1>> flip(Iterator<KeyPair<E1, E2>> iterator){
return ComputeIterator.of(iterator, KeyPair::flip);
}
public static<E1 extends Key, E2 extends Key> List<KeyPair<E2, E1>> flip(Collection<KeyPair<E1, E2>> list){
ArrayCollection<KeyPair<E2, E1>> results = new ArrayCollection<>(list.size());
results.addAll(KeyPair.flip(list.iterator()));
return results;
}
}
13 changes: 13 additions & 0 deletions src/main/java/com/reandroid/dex/key/TypeKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.reandroid.dex.smali.SmaliReader;
import com.reandroid.dex.smali.SmaliWriter;
import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.ObjectsUtil;
import com.reandroid.utils.StringsUtil;
import com.reandroid.utils.collection.EmptyIterator;
import com.reandroid.utils.collection.SingleIterator;
Expand Down Expand Up @@ -230,6 +231,18 @@ public void append(SmaliWriter writer) throws IOException {
writer.append(getTypeName());
}

public int compareInnerFirst(TypeKey other) {
if(this.equals(other)){
return 0;
}
String name1 = this.getSimpleName();
String name2 = other.getSimpleName();
int diff = StringsUtil.diffStart(name1, name2);
if(diff > 0 && name1.charAt(diff) == '$' && diff > name1.lastIndexOf('/') + 1){
return CompareUtil.compare(name2, name1);
}
return CompareUtil.compare(name1, name2);
}
@Override
public int compareTo(Object obj) {
if(obj == null){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public interface DexClassRepository {
Iterator<DexClass> getDexClasses(Predicate<? super TypeKey> filter);
Iterator<DexClass> getDexClassesCloned(Predicate<? super TypeKey> filter);
<T extends SectionItem> Iterator<T> getItems(SectionType<T> sectionType);
<T extends SectionItem> Iterator<T> getClonedItems(SectionType<T> sectionType);
<T1 extends SectionItem> Iterator<T1> getItems(SectionType<T1> sectionType, Key key);
<T1 extends SectionItem> T1 getItem(SectionType<T1> sectionType, Key key);

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/reandroid/dex/model/DexDirectory.java
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ public Iterator<Key> iterator(DexFile element) {
}
};
}
@Override
public<T1 extends SectionItem> Iterator<T1> getClonedItems(SectionType<T1> sectionType) {
return new IterableIterator<DexFile, T1>(clonedIterator()) {
@Override
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/reandroid/dex/model/DexFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ public <T1 extends SectionItem> int removeEntries(SectionType<T1> sectionType, P
public <T1 extends SectionItem> Iterator<Key> removeWithKeys(SectionType<T1> sectionType, Predicate<Key> filter){
return getDexLayout().removeWithKeys(sectionType, filter);
}
@Override
public<T1 extends SectionItem> Iterator<T1> getClonedItems(SectionType<T1> sectionType) {
return getDexLayout().getClonedItems(sectionType);
}
Expand Down
80 changes: 36 additions & 44 deletions src/main/java/com/reandroid/dex/refactor/Rename.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,56 @@
*/
package com.reandroid.dex.refactor;

import com.reandroid.utils.collection.*;
import com.reandroid.dex.key.Key;
import com.reandroid.dex.key.KeyPair;
import com.reandroid.dex.model.DexClassRepository;
import com.reandroid.utils.CompareUtil;
import com.reandroid.utils.StringsUtil;
import com.reandroid.utils.collection.ArrayCollection;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import java.util.*;

public class Rename implements Iterable<RenameInfo<?>>{
private final List<RenameInfo<?>> renameInfoList;
public abstract class Rename<T extends Key, R extends Key> {

private final Set<KeyPair<T, R>> keyPairSet;

public Rename(){
this.renameInfoList = new ArrayCollection<>();
this.keyPairSet = new HashSet<>();
}

public Iterator<RenameInfo<?>> getAll(){
return new MergingIterator<>(ComputeIterator.of(iterator(),
RenameInfo::iterator));
public void add(KeyPair<T, R> keyPair){
addToSet(keyPair);
}

public void add(RenameInfo<?> renameInfo){
if(renameInfo == null || contains(renameInfo)){
return;
}
this.renameInfoList.add(renameInfo);
public void addAll(Collection<KeyPair<T, R>> keyPairs){
this.addAll(keyPairs.iterator());
}
public boolean contains(RenameInfo<?> renameInfo){
if(renameInfo == null){
return false;
public void addAll(Iterator<KeyPair<T, R>> iterator){
while (iterator.hasNext()){
addToSet(iterator.next());
}
if(this.renameInfoList.contains(renameInfo)){
return true;
}
for(RenameInfo<?> info : this){
if(info.contains(renameInfo)){
return true;
}
}
private void addToSet(KeyPair<T, R> keyPair){
if(keyPair != null && keyPair.isValid()){
this.keyPairSet.add(keyPair);
}
return false;
}
@Override
public Iterator<RenameInfo<?>> iterator(){
return renameInfoList.iterator();
public int size(){
return keyPairSet.size();
}
public void write(Writer writer) throws IOException {
for(RenameInfo<?> info : this){
info.write(writer, true);
}
public List<KeyPair<T, R>> sortedList(){
List<KeyPair<T, R>> results = new ArrayCollection<>(keyPairSet);
results.sort(CompareUtil.getComparableComparator());
return results;
}

public abstract int apply(DexClassRepository classRepository);

public Set<KeyPair<T, R>> getKeyPairSet() {
return keyPairSet;
}

@Override
public String toString() {
StringWriter writer = new StringWriter();
try {
write(writer);
writer.close();
} catch (IOException exception) {
return exception.toString();
}
return writer.toString();
return StringsUtil.join(sortedList(), '\n');
}
}
Loading

0 comments on commit 31834dc

Please sign in to comment.