mirror of
https://github.com/revanced/smali.git
synced 2025-05-06 09:24:33 +02:00
Remove code duplication - extract Labels and debugItems from MethodLocation.
This commit is contained in:
parent
7542a6b531
commit
dd242aa735
@ -33,10 +33,7 @@ package org.jf.dexlib2.builder;
|
|||||||
|
|
||||||
import org.jf.dexlib2.iface.debug.DebugItem;
|
import org.jf.dexlib2.iface.debug.DebugItem;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
public abstract class BuilderDebugItem extends ItemWithLocation implements DebugItem {
|
||||||
|
|
||||||
public abstract class BuilderDebugItem implements DebugItem {
|
|
||||||
@Nullable MethodLocation location;
|
|
||||||
|
|
||||||
public BuilderDebugItem() {
|
public BuilderDebugItem() {
|
||||||
}
|
}
|
||||||
@ -48,5 +45,4 @@ public abstract class BuilderDebugItem implements DebugItem {
|
|||||||
}
|
}
|
||||||
return location.getCodeAddress();
|
return location.getCodeAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.jf.dexlib2.builder;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public abstract class ItemWithLocation {
|
||||||
|
@Nullable
|
||||||
|
MethodLocation location;
|
||||||
|
|
||||||
|
public boolean isPlaced() {
|
||||||
|
return location != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocation(MethodLocation methodLocation) {
|
||||||
|
location = methodLocation;
|
||||||
|
}
|
||||||
|
}
|
@ -32,11 +32,8 @@
|
|||||||
package org.jf.dexlib2.builder;
|
package org.jf.dexlib2.builder;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
public class Label {
|
|
||||||
@Nullable MethodLocation location;
|
|
||||||
|
|
||||||
|
public class Label extends ItemWithLocation {
|
||||||
Label() {
|
Label() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,8 +52,4 @@ public class Label {
|
|||||||
}
|
}
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPlaced() {
|
|
||||||
return location != null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package org.jf.dexlib2.builder;
|
||||||
|
|
||||||
|
public class LocatedDebugItems extends LocatedItems<BuilderDebugItem> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String addLocatedItemError() {
|
||||||
|
return "Cannot add a debug item that has already been added to a method." +
|
||||||
|
"You must remove it from its current location first.";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
package org.jf.dexlib2.builder;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public abstract class LocatedItems<T extends ItemWithLocation> {
|
||||||
|
// We end up creating and keeping around a *lot* of MethodLocation objects
|
||||||
|
// when building a new dex file, so it's worth the trouble of lazily creating
|
||||||
|
// the labels and debugItems lists only when they are needed
|
||||||
|
@Nullable
|
||||||
|
private List<T> items = null;
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private List<T> getMutableItems() {
|
||||||
|
if (items == null) {
|
||||||
|
items = new ArrayList<>(1);
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private List<T> getImmutableItems() {
|
||||||
|
if (items == null) {
|
||||||
|
return ImmutableList.of();
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<T> getModifiableItems(MethodLocation newItemsLocation) {
|
||||||
|
return new AbstractSet<T>() {
|
||||||
|
@Nonnull
|
||||||
|
@Override public Iterator<T> iterator() {
|
||||||
|
final Iterator<T> it = getImmutableItems().iterator();
|
||||||
|
|
||||||
|
return new Iterator<T>() {
|
||||||
|
private @Nullable
|
||||||
|
T currentItem = null;
|
||||||
|
|
||||||
|
@Override public boolean hasNext() {
|
||||||
|
return it.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public T next() {
|
||||||
|
currentItem = it.next();
|
||||||
|
return currentItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void remove() {
|
||||||
|
if (currentItem != null) {
|
||||||
|
currentItem.setLocation(null);
|
||||||
|
}
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public int size() {
|
||||||
|
return getImmutableItems().size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean add(@Nonnull T item) {
|
||||||
|
if (item.isPlaced()) {
|
||||||
|
throw new IllegalArgumentException(addLocatedItemError());
|
||||||
|
}
|
||||||
|
item.setLocation(newItemsLocation);
|
||||||
|
getMutableItems().add(item);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String addLocatedItemError();
|
||||||
|
|
||||||
|
public void mergeItemsInto(@Nonnull MethodLocation newLocation, LocatedItems<T> otherLocatedItems) {
|
||||||
|
if (items != null || otherLocatedItems.items != null) {
|
||||||
|
List<T> otherItems = otherLocatedItems.getMutableItems();
|
||||||
|
for (T item: getImmutableItems()) {
|
||||||
|
item.setLocation(newLocation);
|
||||||
|
otherItems.add(item);
|
||||||
|
}
|
||||||
|
items = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.jf.dexlib2.builder;
|
||||||
|
|
||||||
|
public class LocatedLabels extends LocatedItems<Label> {
|
||||||
|
@Override
|
||||||
|
protected String addLocatedItemError() {
|
||||||
|
return "Cannot add a label that is already placed." +
|
||||||
|
"You must remove it from its current location first.";
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
package org.jf.dexlib2.builder;
|
package org.jf.dexlib2.builder;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import org.jf.dexlib2.builder.debug.*;
|
import org.jf.dexlib2.builder.debug.*;
|
||||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||||
import org.jf.dexlib2.iface.reference.StringReference;
|
import org.jf.dexlib2.iface.reference.StringReference;
|
||||||
@ -46,16 +45,13 @@ public class MethodLocation {
|
|||||||
int codeAddress;
|
int codeAddress;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
// We end up creating and keeping around a *lot* of MethodLocation objects
|
private final LocatedItems<Label> labels;
|
||||||
// when building a new dex file, so it's worth the trouble of lazily creating
|
|
||||||
// the labels and debugItems lists only when they are needed
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private List<Label> labels = null;
|
private final LocatedItems<BuilderDebugItem> debugItems;
|
||||||
@Nullable
|
|
||||||
private List<BuilderDebugItem> debugItems = null;
|
|
||||||
|
|
||||||
MethodLocation(@Nullable BuilderInstruction instruction, int codeAddress, int index) {
|
MethodLocation(@Nullable BuilderInstruction instruction, int codeAddress, int index) {
|
||||||
|
this.debugItems = new LocatedDebugItems();
|
||||||
|
this.labels = new LocatedLabels();
|
||||||
this.instruction = instruction;
|
this.instruction = instruction;
|
||||||
this.codeAddress = codeAddress;
|
this.codeAddress = codeAddress;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
@ -74,166 +70,26 @@ public class MethodLocation {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private List<Label> getMutableLabels() {
|
|
||||||
if (labels == null) {
|
|
||||||
labels = new ArrayList<>(1);
|
|
||||||
}
|
|
||||||
return labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private List<Label> getImmutableLabels() {
|
|
||||||
if (labels == null) {
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
return labels;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private List<BuilderDebugItem> getMutableDebugItems() {
|
|
||||||
if (debugItems == null) {
|
|
||||||
debugItems = new ArrayList<>(1);
|
|
||||||
}
|
|
||||||
return debugItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private List<BuilderDebugItem> getImmutableDebugItems() {
|
|
||||||
if (debugItems == null) {
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
return debugItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private List<BuilderDebugItem> getDebugItems(boolean mutable) {
|
|
||||||
if (debugItems == null) {
|
|
||||||
if (mutable) {
|
|
||||||
debugItems = new ArrayList<>(1);
|
|
||||||
return debugItems;
|
|
||||||
}
|
|
||||||
return ImmutableList.of();
|
|
||||||
}
|
|
||||||
return debugItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mergeInto(@Nonnull MethodLocation other) {
|
void mergeInto(@Nonnull MethodLocation other) {
|
||||||
if (this.labels != null || other.labels != null) {
|
labels.mergeItemsInto(other, other.labels);
|
||||||
List<Label> otherLabels = other.getMutableLabels();
|
debugItems.mergeItemsInto(other, other.debugItems);
|
||||||
for (Label label: this.getImmutableLabels()) {
|
|
||||||
label.location = other;
|
|
||||||
otherLabels.add(label);
|
|
||||||
}
|
|
||||||
this.labels = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.debugItems != null || other.labels != null) {
|
|
||||||
// We need to keep the debug items in the same order. We add the other debug items to this list, then reassign
|
|
||||||
// the list.
|
|
||||||
List<BuilderDebugItem> debugItems = getMutableDebugItems();
|
|
||||||
for (BuilderDebugItem debugItem: debugItems) {
|
|
||||||
debugItem.location = other;
|
|
||||||
}
|
|
||||||
debugItems.addAll(other.getImmutableDebugItems());
|
|
||||||
other.debugItems = debugItems;
|
|
||||||
this.debugItems = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public Set<Label> getLabels() {
|
public Set<Label> getLabels() {
|
||||||
return new AbstractSet<Label>() {
|
return labels.getModifiableItems(MethodLocation.this);
|
||||||
@Nonnull
|
|
||||||
@Override public Iterator<Label> iterator() {
|
|
||||||
final Iterator<Label> it = getImmutableLabels().iterator();
|
|
||||||
|
|
||||||
return new Iterator<Label>() {
|
|
||||||
private @Nullable Label currentLabel = null;
|
|
||||||
|
|
||||||
@Override public boolean hasNext() {
|
|
||||||
return it.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Label next() {
|
|
||||||
currentLabel = it.next();
|
|
||||||
return currentLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void remove() {
|
|
||||||
if (currentLabel != null) {
|
|
||||||
currentLabel.location = null;
|
|
||||||
}
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public int size() {
|
|
||||||
return getImmutableLabels().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean add(@Nonnull Label label) {
|
|
||||||
if (label.isPlaced()) {
|
|
||||||
throw new IllegalArgumentException("Cannot add a label that is already placed. You must remove " +
|
|
||||||
"it from its current location first.");
|
|
||||||
}
|
|
||||||
label.location = MethodLocation.this;
|
|
||||||
getMutableLabels().add(label);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public Label addNewLabel() {
|
public Label addNewLabel() {
|
||||||
Label label = new Label(this);
|
Label newLabel = new Label();
|
||||||
getMutableLabels().add(label);
|
getLabels().add(newLabel);
|
||||||
return label;
|
return newLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public Set<BuilderDebugItem> getDebugItems() {
|
public Set<BuilderDebugItem> getDebugItems() {
|
||||||
return new AbstractSet<BuilderDebugItem>() {
|
return debugItems.getModifiableItems(MethodLocation.this);
|
||||||
@Nonnull
|
|
||||||
@Override public Iterator<BuilderDebugItem> iterator() {
|
|
||||||
final Iterator<BuilderDebugItem> it = getImmutableDebugItems().iterator();
|
|
||||||
|
|
||||||
return new Iterator<BuilderDebugItem>() {
|
|
||||||
private @Nullable BuilderDebugItem currentDebugItem = null;
|
|
||||||
|
|
||||||
@Override public boolean hasNext() {
|
|
||||||
return it.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public BuilderDebugItem next() {
|
|
||||||
currentDebugItem = it.next();
|
|
||||||
return currentDebugItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void remove() {
|
|
||||||
if (currentDebugItem != null) {
|
|
||||||
currentDebugItem.location = null;
|
|
||||||
}
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public int size() {
|
|
||||||
return getImmutableDebugItems().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean add(@Nonnull BuilderDebugItem debugItem) {
|
|
||||||
if (debugItem.location != null) {
|
|
||||||
throw new IllegalArgumentException("Cannot add a debug item that has already been added to a " +
|
|
||||||
"method. You must remove it from its current location first.");
|
|
||||||
}
|
|
||||||
debugItem.location = MethodLocation.this;
|
|
||||||
getMutableDebugItems().add(debugItem);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLineNumber(int lineNumber) {
|
public void addLineNumber(int lineNumber) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user