Use collections instead of lists for variable size "lists" in the dex file

Only things that can be accessed in the dex file in a random access manner
should be exposed as a list. If the list must be read sequentially, it is
exposed in the interface as a Collection if the size is available up-front
or as an Iterable if the size can only be determined by iterating over the
list.
This commit is contained in:
Ben Gruver 2012-11-11 14:18:10 -08:00
parent 65d969c23b
commit 12b970ed4d
37 changed files with 203 additions and 374 deletions

View File

@ -33,7 +33,7 @@ import org.jf.dexlib2.iface.value.AnnotationEncodedValue;
import org.jf.util.IndentingWriter; import org.jf.util.IndentingWriter;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.Collection;
public abstract class AnnotationEncodedValueAdaptor { public abstract class AnnotationEncodedValueAdaptor {
@ -47,8 +47,8 @@ public abstract class AnnotationEncodedValueAdaptor {
writer.write(".end subannotation"); writer.write(".end subannotation");
} }
public static void writeElementsTo(IndentingWriter writer, List<? extends AnnotationElement> annotationElements) public static void writeElementsTo(IndentingWriter writer,
throws IOException { Collection<? extends AnnotationElement> annotationElements) throws IOException {
writer.indent(4); writer.indent(4);
for (AnnotationElement annotationElement: annotationElements) { for (AnnotationElement annotationElement: annotationElements) {
writer.write(annotationElement.getName()); writer.write(annotationElement.getName());

View File

@ -33,12 +33,12 @@ import org.jf.dexlib2.iface.value.ArrayEncodedValue;
import org.jf.dexlib2.iface.value.EncodedValue; import org.jf.dexlib2.iface.value.EncodedValue;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.Collection;
public class ArrayEncodedValueAdaptor { public class ArrayEncodedValueAdaptor {
public static void writeTo(IndentingWriter writer, ArrayEncodedValue arrayEncodedValue) throws IOException { public static void writeTo(IndentingWriter writer, ArrayEncodedValue arrayEncodedValue) throws IOException {
writer.write('{'); writer.write('{');
List<? extends EncodedValue> values = arrayEncodedValue.getValue(); Collection<? extends EncodedValue> values = arrayEncodedValue.getValue();
if (values.size() == 0) { if (values.size() == 0) {
writer.write('}'); writer.write('}');
return; return;

View File

@ -31,12 +31,11 @@
package org.jf.dexlib2.dexbacked; package org.jf.dexlib2.dexbacked;
import org.jf.dexlib2.dexbacked.util.VariableSizeList; import org.jf.dexlib2.dexbacked.util.VariableSizeCollection;
import org.jf.dexlib2.iface.Annotation; import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.AnnotationElement;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public class DexBackedAnnotation implements Annotation { public class DexBackedAnnotation implements Annotation {
@Nonnull public final DexBuffer dexBuf; @Nonnull public final DexBuffer dexBuf;
@ -60,23 +59,16 @@ public class DexBackedAnnotation implements Annotation {
@Nonnull @Nonnull
@Override @Override
public List<? extends AnnotationElement> getElements() { public Collection<? extends DexBackedAnnotationElement> getElements() {
DexReader reader = dexBuf.readerAt(elementsOffset); DexReader reader = dexBuf.readerAt(elementsOffset);
final int size = reader.readSmallUleb128(); final int size = reader.readSmallUleb128();
return new VariableSizeList<AnnotationElement>(dexBuf, reader.getOffset()) { return new VariableSizeCollection<DexBackedAnnotationElement>(dexBuf, reader.getOffset(), size) {
@Nonnull @Nonnull
@Override @Override
protected AnnotationElement readItem(@Nonnull DexReader reader, int index) { protected DexBackedAnnotationElement readNextItem(@Nonnull DexReader reader, int index) {
return new DexBackedAnnotationElement(reader); return new DexBackedAnnotationElement(reader);
} }
@Override
protected void skipItem(@Nonnull DexReader reader, int index) {
DexBackedAnnotationElement.skipFrom(reader);
}
@Override public int size() { return size;}
}; };
} }
} }

View File

@ -48,11 +48,6 @@ public class DexBackedAnnotationElement implements AnnotationElement {
this.value = DexBackedEncodedValue.readFrom(reader); this.value = DexBackedEncodedValue.readFrom(reader);
} }
public static void skipFrom(@Nonnull DexReader reader) {
reader.skipUleb128();
DexBackedEncodedValue.skipFrom(reader);
}
@Nonnull @Override public String getName() { return dexBuffer.getString(nameIndex); } @Nonnull @Override public String getName() { return dexBuffer.getString(nameIndex); }
@Nonnull @Override public EncodedValue getValue() { return value; } @Nonnull @Override public EncodedValue getValue() { return value; }
} }

View File

@ -45,6 +45,4 @@ public class DexBackedCatchAllExceptionHandler implements ExceptionHandler {
@Nullable @Override public String getExceptionType() { return null; } @Nullable @Override public String getExceptionType() { return null; }
@Override public int getHandlerCodeOffset() { return handlerCodeOffset; } @Override public int getHandlerCodeOffset() { return handlerCodeOffset; }
public static void skipFrom(@Nonnull DexReader reader) { reader.skipUleb128(); }
} }

View File

@ -33,14 +33,14 @@ package org.jf.dexlib2.dexbacked;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import org.jf.dexlib2.base.reference.BaseTypeReference; import org.jf.dexlib2.base.reference.BaseTypeReference;
import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory; import org.jf.dexlib2.dexbacked.util.*;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.dexbacked.util.StaticInitialValueIterator;
import org.jf.dexlib2.dexbacked.util.VariableSizeListWithContext;
import org.jf.dexlib2.iface.ClassDef; import org.jf.dexlib2.iface.ClassDef;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.List; import java.util.List;
public class DexBackedClassDef extends BaseTypeReference implements ClassDef { public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@ -117,7 +117,7 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Nonnull @Nonnull
@Override @Override
public List<? extends DexBackedField> getFields() { public Collection<? extends DexBackedField> getFields() {
int classDataOffset = getClassDataOffset(); int classDataOffset = getClassDataOffset();
if (getClassDataOffset() != 0) { if (getClassDataOffset() != 0) {
DexReader reader = dexBuf.readerAt(classDataOffset); DexReader reader = dexBuf.readerAt(classDataOffset);
@ -133,11 +133,11 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
dexBuf.readSmallUint(classDefOffset + STATIC_INITIAL_VALUES_OFFSET); dexBuf.readSmallUint(classDefOffset + STATIC_INITIAL_VALUES_OFFSET);
final int fieldsStartOffset = reader.getOffset(); final int fieldsStartOffset = reader.getOffset();
return new VariableSizeListWithContext<DexBackedField>() { return new AbstractCollection<DexBackedField>() {
@Nonnull @Nonnull
@Override @Override
public VariableSizeListIterator listIterator() { public Iterator<DexBackedField> iterator() {
return new VariableSizeListIterator(dexBuf, fieldsStartOffset) { return new VariableSizeIterator<DexBackedField>(dexBuf, fieldsStartOffset, fieldCount) {
private int previousFieldIndex = 0; private int previousFieldIndex = 0;
@Nonnull private final AnnotationsDirectory.AnnotationIterator annotationIterator = @Nonnull private final AnnotationsDirectory.AnnotationIterator annotationIterator =
annotationsDirectory.getFieldAnnotationIterator(); annotationsDirectory.getFieldAnnotationIterator();
@ -146,7 +146,7 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Nonnull @Nonnull
@Override @Override
protected DexBackedField readItem(@Nonnull DexReader reader, int index) { protected DexBackedField readNextItem(@Nonnull DexReader reader, int index) {
if (index == staticFieldCount) { if (index == staticFieldCount) {
// We reached the end of the static field, restart the numbering for // We reached the end of the static field, restart the numbering for
// instance fields // instance fields
@ -158,18 +158,6 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
previousFieldIndex = item.fieldIndex; previousFieldIndex = item.fieldIndex;
return item; return item;
} }
@Override
protected void skipItem(@Nonnull DexReader reader, int index) {
if (index == staticFieldCount) {
// We reached the end of the static field, restart the numbering for
// instance fields
previousFieldIndex = 0;
annotationIterator.reset();
}
previousFieldIndex = DexBackedField.skipEncodedField(reader, previousFieldIndex);
staticInitialValueIterator.skipNext();
}
}; };
} }
@ -182,7 +170,7 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Nonnull @Nonnull
@Override @Override
public List<? extends DexBackedMethod> getMethods() { public Collection<? extends DexBackedMethod> getMethods() {
int classDataOffset = getClassDataOffset(); int classDataOffset = getClassDataOffset();
if (classDataOffset > 0) { if (classDataOffset > 0) {
DexReader reader = dexBuf.readerAt(classDataOffset); DexReader reader = dexBuf.readerAt(classDataOffset);
@ -197,11 +185,11 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory(); final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory();
final int methodsStartOffset = reader.getOffset(); final int methodsStartOffset = reader.getOffset();
return new VariableSizeListWithContext<DexBackedMethod>() { return new AbstractCollection<DexBackedMethod>() {
@Nonnull @Nonnull
@Override @Override
public VariableSizeListIterator listIterator() { public Iterator<DexBackedMethod> iterator() {
return new VariableSizeListIterator(dexBuf, methodsStartOffset) { return new VariableSizeIterator<DexBackedMethod>(dexBuf, methodsStartOffset, methodCount) {
private int previousMethodIndex = 0; private int previousMethodIndex = 0;
@Nonnull private final AnnotationsDirectory.AnnotationIterator methodAnnotationIterator = @Nonnull private final AnnotationsDirectory.AnnotationIterator methodAnnotationIterator =
annotationsDirectory.getMethodAnnotationIterator(); annotationsDirectory.getMethodAnnotationIterator();
@ -210,7 +198,7 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Nonnull @Nonnull
@Override @Override
protected DexBackedMethod readItem(@Nonnull DexReader reader, int index) { protected DexBackedMethod readNextItem(@Nonnull DexReader reader, int index) {
if (index == directMethodCount) { if (index == directMethodCount) {
// We reached the end of the direct methods, restart the numbering for // We reached the end of the direct methods, restart the numbering for
// virtual methods // virtual methods
@ -223,18 +211,6 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
previousMethodIndex = item.methodIndex; previousMethodIndex = item.methodIndex;
return item; return item;
} }
@Override
protected void skipItem(@Nonnull DexReader reader, int index) {
if (index == directMethodCount) {
// We reached the end of the direct methods, restart the numbering for
// virtual methods
previousMethodIndex = 0;
methodAnnotationIterator.reset();
parameterAnnotationIterator.reset();
}
previousMethodIndex = DexBackedMethod.skipEncodedMethod(reader, previousMethodIndex);
}
}; };
} }

View File

@ -49,9 +49,4 @@ public class DexBackedExceptionHandler implements ExceptionHandler {
@Nonnull @Override public String getExceptionType() { return dexBuf.getType(typeId); } @Nonnull @Override public String getExceptionType() { return dexBuf.getType(typeId); }
@Override public int getHandlerCodeOffset() { return handlerCodeOffset; } @Override public int getHandlerCodeOffset() { return handlerCodeOffset; }
public static void skipFrom(@Nonnull DexReader reader) {
reader.skipUleb128();
reader.skipUleb128();
}
} }

View File

@ -96,18 +96,6 @@ public class DexBackedField extends BaseFieldReference implements Field {
return AnnotationsDirectory.getAnnotations(dexBuf, annotationSetOffset); return AnnotationsDirectory.getAnnotations(dexBuf, annotationSetOffset);
} }
/**
* Skips the reader over a single encoded_field structure.
* @param reader The {@code DexFileReader} to skip
* @param previousFieldIndex The field index of the previous field, or 0 if this is the first
* @return The field index of the field that was skipped
*/
public static int skipEncodedField(@Nonnull DexReader reader, int previousFieldIndex) {
int idxDiff = reader.readSmallUleb128();
reader.skipUleb128();
return previousFieldIndex + idxDiff;
}
/** /**
* Skips the reader over the specified number of encoded_field structures * Skips the reader over the specified number of encoded_field structures
* *

View File

@ -41,6 +41,7 @@ import org.jf.dexlib2.iface.MethodParameter;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List; import java.util.List;
public class DexBackedMethod extends BaseMethodReference implements Method { public class DexBackedMethod extends BaseMethodReference implements Method {
@ -116,7 +117,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
@Nonnull @Nonnull
@Override @Override
public List<? extends MethodParameter> getParameters() { public Collection<? extends MethodParameter> getParameters() {
if (getParametersOffset() > 0) { if (getParametersOffset() > 0) {
DexBackedMethodImplementation methodImpl = getImplementation(); DexBackedMethodImplementation methodImpl = getImplementation();
if (methodImpl != null) { if (methodImpl != null) {
@ -205,17 +206,4 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
} }
return parametersOffset; return parametersOffset;
} }
/**
* Skips the reader over a single encoded_method structure.
* @param reader The {@code DexFileReader} to skip
* @param previousMethodIndex The method index of the previous field, or 0 if this is the first
* @return The method index of the field that was skipped
*/
public static int skipEncodedMethod(@Nonnull DexReader reader, int previousMethodIndex) {
int idxDiff = reader.readSmallUleb128();
reader.skipUleb128();
reader.skipUleb128();
return previousMethodIndex + idxDiff;
}
} }

View File

@ -44,6 +44,7 @@ import org.jf.dexlib2.iface.instruction.Instruction;
import org.jf.util.AlignmentUtils; import org.jf.util.AlignmentUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -131,7 +132,7 @@ public class DexBackedMethodImplementation implements MethodImplementation {
} }
@Nonnull @Nonnull
public List<? extends MethodParameter> getParametersWithNames() { public Collection<? extends MethodParameter> getParametersWithNames() {
return getDebugInfo().getParametersWithNames(); return getDebugInfo().getParametersWithNames();
} }
} }

View File

@ -31,12 +31,12 @@
package org.jf.dexlib2.dexbacked; package org.jf.dexlib2.dexbacked;
import org.jf.dexlib2.dexbacked.util.VariableSizeList; import org.jf.dexlib2.dexbacked.util.VariableSizeCollection;
import org.jf.dexlib2.iface.ExceptionHandler; import org.jf.dexlib2.iface.ExceptionHandler;
import org.jf.dexlib2.iface.TryBlock; import org.jf.dexlib2.iface.TryBlock;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public class DexBackedTryBlock implements TryBlock { public class DexBackedTryBlock implements TryBlock {
@Nonnull public final DexBuffer dexBuf; @Nonnull public final DexBuffer dexBuf;
@ -60,52 +60,33 @@ public class DexBackedTryBlock implements TryBlock {
@Nonnull @Nonnull
@Override @Override
public List<? extends ExceptionHandler> getExceptionHandlers() { public Collection<? extends ExceptionHandler> getExceptionHandlers() {
DexReader reader = DexReader reader =
dexBuf.readerAt(handlersStartOffset + dexBuf.readUshort(tryItemOffset + HANDLER_OFFSET_OFFSET)); dexBuf.readerAt(handlersStartOffset + dexBuf.readUshort(tryItemOffset + HANDLER_OFFSET_OFFSET));
final int encodedSize = reader.readSleb128(); final int encodedSize = reader.readSleb128();
if (encodedSize > 0) { if (encodedSize > 0) {
//no catch-all //no catch-all
return new VariableSizeList<ExceptionHandler>(dexBuf, reader.getOffset()) { return new VariableSizeCollection<ExceptionHandler>(dexBuf, reader.getOffset(), encodedSize) {
@Nonnull @Nonnull
@Override @Override
protected ExceptionHandler readItem(@Nonnull DexReader reader, int index) { protected DexBackedExceptionHandler readNextItem(@Nonnull DexReader reader, int index) {
return new DexBackedExceptionHandler(reader); return new DexBackedExceptionHandler(reader);
} }
@Override
protected void skipItem(@Nonnull DexReader dexReader, int index) {
DexBackedExceptionHandler.skipFrom(dexReader);
}
@Override public int size() { return encodedSize; }
}; };
} else { } else {
//with catch-all //with catch-all
final int sizeWithCatchAll = (-1 * encodedSize) + 1; final int sizeWithCatchAll = (-1 * encodedSize) + 1;
return new VariableSizeList<ExceptionHandler>(dexBuf, reader.getOffset()) { return new VariableSizeCollection<ExceptionHandler>(dexBuf, reader.getOffset(), sizeWithCatchAll) {
@Nonnull @Nonnull
@Override @Override
protected ExceptionHandler readItem(@Nonnull DexReader dexReader, int index) { protected ExceptionHandler readNextItem(@Nonnull DexReader dexReader, int index) {
if (index == sizeWithCatchAll-1) { if (index == sizeWithCatchAll-1) {
return new DexBackedCatchAllExceptionHandler(dexReader); return new DexBackedCatchAllExceptionHandler(dexReader);
} else { } else {
return new DexBackedExceptionHandler(dexReader); return new DexBackedExceptionHandler(dexReader);
} }
} }
@Override
protected void skipItem(@Nonnull DexReader dexReader, int index) {
if (index == sizeWithCatchAll-1) {
DexBackedCatchAllExceptionHandler.skipFrom(dexReader);
} else {
DexBackedExceptionHandler.skipFrom(dexReader);
}
}
@Override public int size() { return sizeWithCatchAll; }
}; };
} }
} }

View File

@ -74,6 +74,8 @@ public class DexBackedMethodReference extends BaseMethodReference {
@Nonnull @Nonnull
@Override @Override
public TypeReference readItem(final int index) { public TypeReference readItem(final int index) {
// Can't use DexBackedTypeReference, because we don't want to read in the type index until it
// is asked for
return new TypeReference() { return new TypeReference() {
@Nonnull @Nonnull
@Override @Override

View File

@ -48,11 +48,12 @@ import org.jf.dexlib2.immutable.debug.*;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public abstract class DebugInfo implements Iterable<DebugItem> { public abstract class DebugInfo implements Iterable<DebugItem> {
@Nonnull public abstract List<? extends MethodParameter> getParametersWithNames(); @Nonnull public abstract Collection<? extends MethodParameter> getParametersWithNames();
public static DebugInfo newOrEmpty(@Nonnull DexBuffer dexBuf, int debugInfoOffset, public static DebugInfo newOrEmpty(@Nonnull DexBuffer dexBuf, int debugInfoOffset,
@Nonnull DexBackedMethodImplementation methodImpl) { @Nonnull DexBackedMethodImplementation methodImpl) {
@ -102,8 +103,8 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
final LocalInfo[] locals = new LocalInfo[registerCount]; final LocalInfo[] locals = new LocalInfo[registerCount];
Arrays.fill(locals, EMPTY_LOCAL_INFO); Arrays.fill(locals, EMPTY_LOCAL_INFO);
VariableSizeList<? extends MethodParameter> parameters = getParametersWithNames(); final VariableSizeIterator<? extends MethodParameter> parameterIterator =
final VariableSizeList<? extends MethodParameter>.Iterator parameterIterator = parameters.listIterator(); getParametersWithNames().iterator();
// first, we grab all the parameters and temporarily store them at the beginning of locals, // first, we grab all the parameters and temporarily store them at the beginning of locals,
// disregarding any wide types // disregarding any wide types
@ -232,7 +233,7 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
@Nonnull @Nonnull
@Override @Override
public VariableSizeList<MethodParameter> getParametersWithNames() { public VariableSizeCollection<MethodParameter> getParametersWithNames() {
DexReader reader = dexBuf.readerAt(debugInfoOffset); DexReader reader = dexBuf.readerAt(debugInfoOffset);
reader.skipUleb128(); reader.skipUleb128();
final int parameterNameCount = reader.readSmallUleb128(); final int parameterNameCount = reader.readSmallUleb128();
@ -240,10 +241,11 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
methodImpl.method.getParametersWithoutNames(); methodImpl.method.getParametersWithoutNames();
//TODO: make sure dalvik doesn't allow more parameter names than we have parameters //TODO: make sure dalvik doesn't allow more parameter names than we have parameters
return new VariableSizeList<MethodParameter>(dexBuf, reader.getOffset()) { return new VariableSizeCollection<MethodParameter>(dexBuf, reader.getOffset(),
methodParametersWithoutNames.size()) {
@Nonnull @Nonnull
@Override @Override
protected MethodParameter readItem(@Nonnull DexReader reader, int index) { protected MethodParameter readNextItem(@Nonnull DexReader reader, int index) {
final MethodParameter methodParameter = methodParametersWithoutNames.get(index); final MethodParameter methodParameter = methodParametersWithoutNames.get(index);
String _name = null; String _name = null;
if (index < parameterNameCount) { if (index < parameterNameCount) {
@ -260,8 +262,6 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
} }
}; };
} }
@Override public int size() { return methodParametersWithoutNames.size(); }
}; };
} }
} }

View File

@ -33,78 +33,34 @@ package org.jf.dexlib2.dexbacked.util;
import org.jf.dexlib2.dexbacked.DexBuffer; import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.DexReader; import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.util.AbstractListIterator;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.AbstractSequentialList; import java.util.AbstractCollection;
import java.util.NoSuchElementException; import java.util.Iterator;
/** public abstract class VariableSizeCollection<T> extends AbstractCollection<T> {
* Provides a base class for a list that is backed by variable size items in a dex file
* @param <T> The type of the item that this list contains
*/
public abstract class VariableSizeList<T> extends AbstractSequentialList<T> {
@Nonnull private final DexBuffer dexBuf; @Nonnull private final DexBuffer dexBuf;
private final int offset; private final int offset;
private final int size;
public VariableSizeList(@Nonnull DexBuffer dexBuf, int offset) { public VariableSizeCollection(@Nonnull DexBuffer dexBuf, int offset, int size) {
this.dexBuf = dexBuf; this.dexBuf = dexBuf;
this.offset = offset; this.offset = offset;
this.size = size;
} }
@Nonnull @Nonnull protected abstract T readNextItem(@Nonnull DexReader reader, int index);
protected abstract T readItem(@Nonnull DexReader reader, int index);
protected void skipItem(@Nonnull DexReader reader, int index) {
readItem(reader, index);
}
@Nonnull
@Override @Override
public Iterator listIterator(int startIndex) { public VariableSizeIterator<T> iterator() {
Iterator iterator = listIterator(); return new VariableSizeIterator<T>(dexBuf, offset, size) {
if (startIndex < 0 || startIndex >= size()) { @Nonnull
throw new IndexOutOfBoundsException(); @Override
} protected T readNextItem(@Nonnull DexReader reader, int index) {
for (int i=0; i<startIndex; i++) { return VariableSizeCollection.this.readNextItem(reader, index);
iterator.skip();
}
return iterator;
}
@Nonnull
@Override
public Iterator listIterator() {
return new Iterator();
}
public class Iterator extends AbstractListIterator<T> {
private int index = 0;
@Nonnull private final DexReader reader = dexBuf.readerAt(offset);
@Override public boolean hasNext() { return index < size(); }
@Override public int nextIndex() { return index; }
protected void checkBounds(int index) {
if (index >= size()) {
throw new NoSuchElementException();
} }
} };
@Nonnull
@Override
public T next() {
checkBounds(index);
return readItem(reader, index++);
}
public void skip() {
checkBounds(index);
skipItem(reader, index++);
}
public int getReaderOffset() {
return reader.getOffset();
}
} }
@Override public int size() { return size; }
} }

View File

@ -0,0 +1,81 @@
/*
* Copyright 2012, 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.dexlib2.dexbacked.util;
import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.DexReader;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.NoSuchElementException;
public abstract class VariableSizeIterator<T> implements Iterator<T> {
@Nonnull private final DexReader reader;
protected final int size;
private int index;
protected VariableSizeIterator(@Nonnull DexBuffer dexBuf, int offset, int size) {
this.reader = dexBuf.readerAt(offset);
this.size = size;
}
/**
* Reads the next item from reader.
*
* @param reader The {@code DexReader} to read the next item from
* @param index The index of the item being read. This is guaranteed to be less than {@code size}
* @return The item that was read
*/
@Nonnull protected abstract T readNextItem(@Nonnull DexReader reader, int index);
public int getReaderOffset() {
return reader.getOffset();
}
@Override
public boolean hasNext() {
return index < size;
}
@Override
@Nonnull
public T next() {
if (index >= size) {
throw new NoSuchElementException();
}
return readNextItem(reader, index++);
}
@Override public void remove() { throw new UnsupportedOperationException(); }
}

View File

@ -1,117 +0,0 @@
/*
* Copyright 2012, 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.dexlib2.dexbacked.util;
import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.util.AbstractListIterator;
import javax.annotation.Nonnull;
import java.util.AbstractSequentialList;
import java.util.NoSuchElementException;
/**
* Provides a base class for a list that is backed by variable size items in a dex file.
*
* This class is similar to VariableSizeList, except that it requires the implementing
* class to implement {@code listIterator}. This allows the base class to extend
* {@code Iterator}, when it needs to store additional context while iterating the list.
*
* @param <T> The type of the item that this list contains
*/
public abstract class VariableSizeListWithContext<T> extends AbstractSequentialList<T> {
@Nonnull
@Override
public VariableSizeListIterator listIterator(int startIndex) {
VariableSizeListIterator iterator = listIterator();
if (startIndex < 0 || startIndex >= size()) {
throw new IndexOutOfBoundsException();
}
for (int i=0; i<startIndex; i++) {
iterator.skip();
}
return iterator;
}
@Nonnull @Override public abstract VariableSizeListIterator listIterator();
public abstract class VariableSizeListIterator extends AbstractListIterator<T> {
private int index = 0;
@Nonnull private final DexReader reader;
public VariableSizeListIterator(@Nonnull DexBuffer dexBuf, int offset) {
this.reader = dexBuf.readerAt(offset);
}
/**
* Read the next item from {@code reader}.
*
* The index field will contain the index of the item being read.
*
* @return The next item that was read from {@code reader}
*/
@Nonnull protected abstract T readItem(@Nonnull DexReader reader, int index);
/**
* Skip the next item in {@code reader}.
*
* The default implementation simply calls readNextItem and throws away the result. This
* can be overridden if skipping an item can be implemented more efficiently than reading
* the same item.
*/
protected void skipItem(@Nonnull DexReader reader, int index) {
readItem(reader, index);
}
@Override public boolean hasNext() { return index < size(); }
@Override public int nextIndex() { return index; }
protected void checkBounds(int index) {
if (index >= size()) {
throw new NoSuchElementException();
}
}
@Nonnull
@Override
public T next() {
checkBounds(index);
return readItem(reader, index++);
}
public void skip() {
checkBounds(index);
skipItem(reader, index++);
}
}
}

View File

@ -31,37 +31,37 @@
package org.jf.dexlib2.dexbacked.value; package org.jf.dexlib2.dexbacked.value;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.base.value.BaseAnnotationEncodedValue; import org.jf.dexlib2.base.value.BaseAnnotationEncodedValue;
import org.jf.dexlib2.dexbacked.DexBackedAnnotationElement; import org.jf.dexlib2.dexbacked.DexBackedAnnotationElement;
import org.jf.dexlib2.dexbacked.DexBuffer; import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.DexReader; import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.dexlib2.dexbacked.util.VariableSizeList; import org.jf.dexlib2.dexbacked.util.VariableSizeCollection;
import org.jf.dexlib2.iface.AnnotationElement;
import org.jf.dexlib2.iface.value.AnnotationEncodedValue; import org.jf.dexlib2.iface.value.AnnotationEncodedValue;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public class DexBackedAnnotationEncodedValue extends BaseAnnotationEncodedValue implements AnnotationEncodedValue { public class DexBackedAnnotationEncodedValue extends BaseAnnotationEncodedValue implements AnnotationEncodedValue {
@Nonnull public final DexBuffer dexBuf; @Nonnull public final DexBuffer dexBuf;
@Nonnull public final String type; @Nonnull public final String type;
private final int elementCount;
private final int elementsOffset; private final int elementsOffset;
public DexBackedAnnotationEncodedValue(@Nonnull DexReader reader) { public DexBackedAnnotationEncodedValue(@Nonnull DexReader reader) {
this.dexBuf = reader.getDexBuffer(); this.dexBuf = reader.getDexBuffer();
this.type = reader.getType(reader.readSmallUleb128()); this.type = reader.getType(reader.readSmallUleb128());
this.elementCount = reader.readSmallUleb128();
this.elementsOffset = reader.getOffset(); this.elementsOffset = reader.getOffset();
skipElements(reader); skipElements(reader, elementCount);
} }
public static void skipFrom(@Nonnull DexReader reader) { public static void skipFrom(@Nonnull DexReader reader) {
reader.skipUleb128(); reader.skipUleb128(); // type
skipElements(reader); int elementCount = reader.readSmallUleb128();
skipElements(reader, elementCount);
} }
private static void skipElements(@Nonnull DexReader reader) { private static void skipElements(@Nonnull DexReader reader, int elementCount) {
int elementCount = reader.readSmallUleb128();
for (int i=0; i<elementCount; i++) { for (int i=0; i<elementCount; i++) {
reader.skipUleb128(); reader.skipUleb128();
DexBackedEncodedValue.skipFrom(reader); DexBackedEncodedValue.skipFrom(reader);
@ -72,23 +72,13 @@ public class DexBackedAnnotationEncodedValue extends BaseAnnotationEncodedValue
@Nonnull @Nonnull
@Override @Override
public List<? extends AnnotationElement> getElements() { public Collection<? extends DexBackedAnnotationElement> getElements() {
DexReader reader = dexBuf.readerAt(elementsOffset); return new VariableSizeCollection<DexBackedAnnotationElement>(dexBuf, elementsOffset, elementCount) {
final int size = reader.readSmallUleb128();
return new VariableSizeList<AnnotationElement>(dexBuf, reader.getOffset()) {
@Nonnull @Nonnull
@Override @Override
protected AnnotationElement readItem(@Nonnull DexReader dexReader, int index) { protected DexBackedAnnotationElement readNextItem(@Nonnull DexReader dexReader, int index) {
return new DexBackedAnnotationElement(dexReader); return new DexBackedAnnotationElement(dexReader);
} }
@Override
protected void skipItem(@Nonnull DexReader reader, int index) {
DexBackedAnnotationElement.skipFrom(reader);
}
@Override public int size() { return size;}
}; };
} }
} }

View File

@ -31,29 +31,34 @@
package org.jf.dexlib2.dexbacked.value; package org.jf.dexlib2.dexbacked.value;
import org.jf.dexlib2.ValueType;
import org.jf.dexlib2.base.value.BaseArrayEncodedValue; import org.jf.dexlib2.base.value.BaseArrayEncodedValue;
import org.jf.dexlib2.dexbacked.DexBuffer; import org.jf.dexlib2.dexbacked.DexBuffer;
import org.jf.dexlib2.dexbacked.DexReader; import org.jf.dexlib2.dexbacked.DexReader;
import org.jf.dexlib2.dexbacked.util.VariableSizeList; import org.jf.dexlib2.dexbacked.util.VariableSizeCollection;
import org.jf.dexlib2.iface.value.ArrayEncodedValue; import org.jf.dexlib2.iface.value.ArrayEncodedValue;
import org.jf.dexlib2.iface.value.EncodedValue; import org.jf.dexlib2.iface.value.EncodedValue;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public class DexBackedArrayEncodedValue extends BaseArrayEncodedValue implements ArrayEncodedValue { public class DexBackedArrayEncodedValue extends BaseArrayEncodedValue implements ArrayEncodedValue {
@Nonnull public final DexBuffer dexBuf; @Nonnull public final DexBuffer dexBuf;
private final int elementCount;
private final int encodedArrayOffset; private final int encodedArrayOffset;
public DexBackedArrayEncodedValue(@Nonnull DexReader reader) { public DexBackedArrayEncodedValue(@Nonnull DexReader reader) {
this.dexBuf = reader.getDexBuffer(); this.dexBuf = reader.getDexBuffer();
this.elementCount = reader.readSmallUleb128();
this.encodedArrayOffset = reader.getOffset(); this.encodedArrayOffset = reader.getOffset();
skipFrom(reader); skipElementsFrom(reader, elementCount);
} }
public static void skipFrom(@Nonnull DexReader reader) { public static void skipFrom(@Nonnull DexReader reader) {
int elementCount = reader.readSmallUleb128(); int elementCount = reader.readSmallUleb128();
skipElementsFrom(reader, elementCount);
}
private static void skipElementsFrom(@Nonnull DexReader reader, int elementCount) {
for (int i=0; i<elementCount; i++) { for (int i=0; i<elementCount; i++) {
DexBackedEncodedValue.skipFrom(reader); DexBackedEncodedValue.skipFrom(reader);
} }
@ -61,23 +66,13 @@ public class DexBackedArrayEncodedValue extends BaseArrayEncodedValue implements
@Nonnull @Nonnull
@Override @Override
public List<? extends EncodedValue> getValue() { public Collection<? extends EncodedValue> getValue() {
DexReader reader = dexBuf.readerAt(encodedArrayOffset); return new VariableSizeCollection<EncodedValue>(dexBuf, encodedArrayOffset, elementCount) {
final int size = reader.readSmallUleb128();
return new VariableSizeList<EncodedValue>(dexBuf, reader.getOffset()) {
@Nonnull @Nonnull
@Override @Override
protected EncodedValue readItem(@Nonnull DexReader dexReader, int index) { protected EncodedValue readNextItem(@Nonnull DexReader dexReader, int index) {
return DexBackedEncodedValue.readFrom(dexReader); return DexBackedEncodedValue.readFrom(dexReader);
} }
@Override
protected void skipItem(@Nonnull DexReader reader, int index) {
DexBackedEncodedValue.skipFrom(reader);
}
@Override public int size() { return size;}
}; };
} }
} }

View File

@ -32,6 +32,7 @@
package org.jf.dexlib2.iface; package org.jf.dexlib2.iface;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List; import java.util.List;
public interface Annotation { public interface Annotation {
@ -42,5 +43,5 @@ public interface Annotation {
int getVisibility(); int getVisibility();
@Nonnull String getType(); @Nonnull String getType();
@Nonnull List<? extends AnnotationElement> getElements(); @Nonnull Collection<? extends AnnotationElement> getElements();
} }

View File

@ -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.Collection;
import java.util.List; import java.util.List;
public interface ClassDef extends TypeReference { public interface ClassDef extends TypeReference {
@ -44,6 +45,6 @@ public interface ClassDef extends TypeReference {
@Nonnull List<String> getInterfaces(); @Nonnull List<String> getInterfaces();
@Nullable String getSourceFile(); @Nullable String getSourceFile();
@Nonnull List<? extends Annotation> getAnnotations(); @Nonnull List<? extends Annotation> getAnnotations();
@Nonnull List<? extends Field> getFields(); @Nonnull Collection<? extends Field> getFields();
@Nonnull List<? extends Method> getMethods(); @Nonnull Collection<? extends Method> getMethods();
} }

View File

@ -35,12 +35,13 @@ import org.jf.dexlib2.iface.reference.MethodReference;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List; import java.util.List;
public interface Method extends MethodReference { public interface Method extends MethodReference {
@Nonnull String getContainingClass(); @Nonnull String getContainingClass();
@Nonnull String getName(); @Nonnull String getName();
@Nonnull List<? extends MethodParameter> getParameters(); @Nonnull Collection<? extends MethodParameter> getParameters();
@Nonnull String getReturnType(); @Nonnull String getReturnType();
int getAccessFlags(); int getAccessFlags();
@Nonnull List<? extends Annotation> getAnnotations(); @Nonnull List<? extends Annotation> getAnnotations();

View File

@ -34,9 +34,9 @@ package org.jf.dexlib2.iface;
import org.jf.dexlib2.iface.reference.TypeReference; import org.jf.dexlib2.iface.reference.TypeReference;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public interface MethodPrototype { public interface MethodPrototype {
@Nonnull List<? extends TypeReference> getParameters(); @Nonnull Collection<? extends TypeReference> getParameters();
@Nonnull String getReturnType(); @Nonnull String getReturnType();
} }

View File

@ -32,10 +32,10 @@
package org.jf.dexlib2.iface; package org.jf.dexlib2.iface;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public interface TryBlock { public interface TryBlock {
int getStartCodeOffset(); int getStartCodeOffset();
int getCodeUnitCount(); int getCodeUnitCount();
@Nonnull List<? extends ExceptionHandler> getExceptionHandlers(); @Nonnull Collection<? extends ExceptionHandler> getExceptionHandlers();
} }

View File

@ -34,11 +34,11 @@ package org.jf.dexlib2.iface.reference;
import org.jf.dexlib2.iface.MethodPrototype; import org.jf.dexlib2.iface.MethodPrototype;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public interface MethodReference extends Reference, MethodPrototype { public interface MethodReference extends Reference, MethodPrototype {
@Nonnull String getContainingClass(); @Nonnull String getContainingClass();
@Nonnull String getName(); @Nonnull String getName();
@Nonnull List<? extends TypeReference> getParameters(); @Nonnull Collection<? extends TypeReference> getParameters();
@Nonnull String getReturnType(); @Nonnull String getReturnType();
} }

View File

@ -34,9 +34,10 @@ package org.jf.dexlib2.iface.value;
import org.jf.dexlib2.iface.AnnotationElement; import org.jf.dexlib2.iface.AnnotationElement;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List; import java.util.List;
public interface AnnotationEncodedValue extends EncodedValue { public interface AnnotationEncodedValue extends EncodedValue {
@Nonnull String getType(); @Nonnull String getType();
@Nonnull List<? extends AnnotationElement> getElements(); @Nonnull Collection<? extends AnnotationElement> getElements();
} }

View File

@ -32,8 +32,9 @@
package org.jf.dexlib2.iface.value; package org.jf.dexlib2.iface.value;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List; import java.util.List;
public interface ArrayEncodedValue extends EncodedValue { public interface ArrayEncodedValue extends EncodedValue {
@Nonnull List<? extends EncodedValue> getValue(); @Nonnull Collection<? extends EncodedValue> getValue();
} }

View File

@ -39,6 +39,7 @@ import org.jf.util.ImmutableListUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List; import java.util.List;
public class ImmutableAnnotation implements Annotation { public class ImmutableAnnotation implements Annotation {
@ -48,7 +49,7 @@ public class ImmutableAnnotation implements Annotation {
public ImmutableAnnotation(int visibility, public ImmutableAnnotation(int visibility,
@Nonnull String type, @Nonnull String type,
@Nullable List<? extends AnnotationElement> elements) { @Nullable Collection<? extends AnnotationElement> elements) {
this.visibility = visibility; this.visibility = visibility;
this.type = type; this.type = type;
this.elements = ImmutableAnnotationElement.immutableListOf(elements); this.elements = ImmutableAnnotationElement.immutableListOf(elements);

View File

@ -72,7 +72,7 @@ public class ImmutableAnnotationElement implements AnnotationElement {
@Nonnull @Nonnull
public static ImmutableList<ImmutableAnnotationElement> immutableListOf( public static ImmutableList<ImmutableAnnotationElement> immutableListOf(
@Nullable List<? extends AnnotationElement> list) { @Nullable Iterable<? extends AnnotationElement> list) {
return CONVERTER.convert(list); return CONVERTER.convert(list);
} }

View File

@ -42,6 +42,7 @@ import org.jf.util.ImmutableListUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List; import java.util.List;
public class ImmutableClassDef extends BaseTypeReference implements ClassDef { public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
@ -60,8 +61,8 @@ public class ImmutableClassDef extends BaseTypeReference implements ClassDef {
@Nullable List<String> interfaces, @Nullable List<String> interfaces,
@Nullable String sourceFile, @Nullable String sourceFile,
@Nullable List<? extends Annotation> annotations, @Nullable List<? extends Annotation> annotations,
@Nullable List<? extends Field> fields, @Nullable Collection<? extends Field> fields,
@Nullable List<? extends Method> methods) { @Nullable Collection<? extends Method> methods) {
this.type = type; this.type = type;
this.accessFlags = accessFlags; this.accessFlags = accessFlags;
this.superclass = superclass; this.superclass = superclass;

View File

@ -37,7 +37,6 @@ import org.jf.util.ImmutableListConverter;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
public class ImmutableExceptionHandler implements ExceptionHandler { public class ImmutableExceptionHandler implements ExceptionHandler {
@Nullable public final String exceptionType; @Nullable public final String exceptionType;
@ -63,7 +62,7 @@ public class ImmutableExceptionHandler implements ExceptionHandler {
@Nonnull @Nonnull
public static ImmutableList<ImmutableExceptionHandler> immutableListOf( public static ImmutableList<ImmutableExceptionHandler> immutableListOf(
@Nullable List<? extends ExceptionHandler> list) { @Nullable Iterable<? extends ExceptionHandler> list) {
return CONVERTER.convert(list); return CONVERTER.convert(list);
} }

View File

@ -102,7 +102,7 @@ public class ImmutableField extends BaseFieldReference implements Field {
@Nonnull @Override public ImmutableList<? extends ImmutableAnnotation> getAnnotations() { return annotations; } @Nonnull @Override public ImmutableList<? extends ImmutableAnnotation> getAnnotations() { return annotations; }
@Nonnull @Nonnull
public static ImmutableList<ImmutableField> immutableListOf(@Nullable List<? extends Field> list) { public static ImmutableList<ImmutableField> immutableListOf(@Nullable Iterable<? extends Field> list) {
return CONVERTER.convert(list); return CONVERTER.convert(list);
} }

View File

@ -42,6 +42,7 @@ import org.jf.util.ImmutableListUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List; import java.util.List;
public class ImmutableMethod extends BaseMethodReference implements Method { public class ImmutableMethod extends BaseMethodReference implements Method {
@ -55,7 +56,7 @@ public class ImmutableMethod extends BaseMethodReference implements Method {
public ImmutableMethod(@Nonnull String containingClass, public ImmutableMethod(@Nonnull String containingClass,
@Nonnull String name, @Nonnull String name,
@Nullable List<? extends MethodParameter> parameters, @Nullable Collection<? extends MethodParameter> parameters,
@Nonnull String returnType, @Nonnull String returnType,
int accessFlags, int accessFlags,
@Nullable List<? extends Annotation> annotations, @Nullable List<? extends Annotation> annotations,
@ -108,7 +109,7 @@ public class ImmutableMethod extends BaseMethodReference implements Method {
@Nullable public ImmutableMethodImplementation getImplementation() { return methodImplementation; } @Nullable public ImmutableMethodImplementation getImplementation() { return methodImplementation; }
@Nonnull @Nonnull
public static ImmutableList<ImmutableMethod> immutableListOf(@Nullable List<? extends Method> list) { public static ImmutableList<ImmutableMethod> immutableListOf(@Nullable Iterable<? extends Method> list) {
return CONVERTER.convert(list); return CONVERTER.convert(list);
} }

View File

@ -82,7 +82,7 @@ public class ImmutableMethodParameter extends BaseTypeReference implements Metho
@Nonnull @Nonnull
public static ImmutableList<ImmutableMethodParameter> immutableListOf( public static ImmutableList<ImmutableMethodParameter> immutableListOf(
@Nullable List<? extends MethodParameter> list) { @Nullable Iterable<? extends MethodParameter> list) {
return CONVERTER.convert(list); return CONVERTER.convert(list);
} }

View File

@ -39,6 +39,7 @@ import org.jf.util.ImmutableListUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List; import java.util.List;
public class ImmutableTryBlock implements TryBlock { public class ImmutableTryBlock implements TryBlock {
@ -48,7 +49,7 @@ public class ImmutableTryBlock implements TryBlock {
public ImmutableTryBlock(int startCodeOffset, public ImmutableTryBlock(int startCodeOffset,
int codeUnitCount, int codeUnitCount,
@Nullable List<? extends ExceptionHandler> exceptionHandlers) { @Nullable Collection<? extends ExceptionHandler> exceptionHandlers) {
this.startCodeOffset = startCodeOffset; this.startCodeOffset = startCodeOffset;
this.codeUnitCount = codeUnitCount; this.codeUnitCount = codeUnitCount;
this.exceptionHandlers = ImmutableExceptionHandler.immutableListOf(exceptionHandlers); this.exceptionHandlers = ImmutableExceptionHandler.immutableListOf(exceptionHandlers);

View File

@ -40,7 +40,7 @@ import org.jf.util.ImmutableListUtils;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.Collection;
public class ImmutableAnnotationEncodedValue extends BaseAnnotationEncodedValue public class ImmutableAnnotationEncodedValue extends BaseAnnotationEncodedValue
implements ImmutableEncodedValue, AnnotationEncodedValue { implements ImmutableEncodedValue, AnnotationEncodedValue {
@ -48,7 +48,7 @@ public class ImmutableAnnotationEncodedValue extends BaseAnnotationEncodedValue
@Nonnull public final ImmutableList<? extends ImmutableAnnotationElement> elements; @Nonnull public final ImmutableList<? extends ImmutableAnnotationElement> elements;
public ImmutableAnnotationEncodedValue(@Nonnull String type, public ImmutableAnnotationEncodedValue(@Nonnull String type,
@Nullable List<? extends AnnotationElement> elements) { @Nullable Collection<? extends AnnotationElement> elements) {
this.type = type; this.type = type;
this.elements = ImmutableAnnotationElement.immutableListOf(elements); this.elements = ImmutableAnnotationElement.immutableListOf(elements);
} }

View File

@ -37,13 +37,13 @@ import org.jf.dexlib2.iface.value.ArrayEncodedValue;
import org.jf.dexlib2.iface.value.EncodedValue; import org.jf.dexlib2.iface.value.EncodedValue;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.Collection;
public class ImmutableArrayEncodedValue extends BaseArrayEncodedValue public class ImmutableArrayEncodedValue extends BaseArrayEncodedValue
implements ImmutableEncodedValue, ArrayEncodedValue { implements ImmutableEncodedValue, ArrayEncodedValue {
@Nonnull public final ImmutableList<? extends ImmutableEncodedValue> value; @Nonnull public final ImmutableList<? extends ImmutableEncodedValue> value;
public ImmutableArrayEncodedValue(@Nonnull List<? extends EncodedValue> value) { public ImmutableArrayEncodedValue(@Nonnull Collection<? extends EncodedValue> value) {
this.value = ImmutableEncodedValueFactory.immutableListOf(value); this.value = ImmutableEncodedValueFactory.immutableListOf(value);
} }

View File

@ -39,7 +39,6 @@ import org.jf.util.ImmutableListConverter;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
public class ImmutableEncodedValueFactory { public class ImmutableEncodedValueFactory {
@Nullable @Nullable
@ -87,7 +86,8 @@ public class ImmutableEncodedValueFactory {
} }
@Nonnull @Nonnull
public static ImmutableList<ImmutableEncodedValue> immutableListOf(@Nullable List<? extends EncodedValue> list) { public static ImmutableList<ImmutableEncodedValue> immutableListOf
(@Nullable Iterable<? extends EncodedValue> list) {
return CONVERTER.convert(list); return CONVERTER.convert(list);
} }