blob: 684dd7d2555eca58b364648a7fe3716c1528e3e5 [file] [log] [blame]
// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
import static com.android.tools.r8.utils.PredicateUtils.not;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.Iterators;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class DexTypeList extends DexItem implements Iterable<DexType>, StructuralItem<DexTypeList> {
private static final DexTypeList theEmptyTypeList = new DexTypeList();
public final DexType[] values;
private static void specify(StructuralSpecification<DexTypeList, ?> spec) {
spec.withItemArray(ts -> ts.values);
}
public static DexTypeList empty() {
return theEmptyTypeList;
}
private DexTypeList() {
this.values = DexType.EMPTY_ARRAY;
}
public DexTypeList(DexType[] values) {
assert values != null && values.length > 0;
this.values = values;
}
public DexTypeList(Collection<DexType> values) {
this(values.toArray(DexType.EMPTY_ARRAY));
}
public static DexTypeList create(DexType[] values) {
return values.length == 0 ? DexTypeList.empty() : new DexTypeList(values);
}
public static DexTypeList create(Collection<DexType> values) {
return values.isEmpty() ? DexTypeList.empty() : new DexTypeList(values);
}
public DexType get(int index) {
return values[index];
}
public DexTypeList keepIf(Predicate<DexType> predicate) {
DexType[] filtered = ArrayUtils.filter(DexType[].class, values, predicate);
if (filtered != values) {
return DexTypeList.create(filtered);
}
return this;
}
public DexTypeList map(Function<DexType, DexType> fn) {
if (isEmpty()) {
return DexTypeList.empty();
}
DexType[] newTypes = ArrayUtils.map(values, fn, DexType.EMPTY_ARRAY);
return newTypes != values ? create(newTypes) : this;
}
public DexTypeList removeIf(Predicate<DexType> predicate) {
return keepIf(not(predicate));
}
@Override
public DexTypeList self() {
return this;
}
@Override
public StructuralMapping<DexTypeList> getStructuralMapping() {
return DexTypeList::specify;
}
public boolean contains(DexType type) {
return ArrayUtils.contains(values, type);
}
@Override
public void forEach(Consumer<? super DexType> consumer) {
for (DexType value : values) {
consumer.accept(value);
}
}
@Override
public int hashCode() {
return Arrays.hashCode(values);
}
void collectIndexedItems(IndexedItemCollection indexedItems) {
for (DexType type : values) {
type.collectIndexedItems(indexedItems);
}
}
@Override
void collectMixedSectionItems(MixedSectionCollection mixedItems) {
mixedItems.add(this);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
return (other instanceof DexTypeList)
&& Arrays.equals(values, ((DexTypeList) other).values);
}
public boolean isEmpty() {
return values.length == 0;
}
public int size() {
return values.length;
}
public Stream<DexType> stream() {
return Stream.of(values);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
if (values.length > 0) {
builder.append(values[0]);
for (int i = 1; i < values.length; i++) {
builder.append(' ').append(values[i]);
}
}
return builder.toString();
}
@Override
public Iterator<DexType> iterator() {
return Iterators.forArray(values);
}
public DexTypeList getSorted() {
if (values.length <= 1) {
return this;
}
DexType[] newValues = values.clone();
Arrays.sort(newValues);
return new DexTypeList(newValues);
}
}