blob: be5af32d21abd197e7451ee130c38cc0d85267f7 [file] [log] [blame]
// Copyright (c) 2022, 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.keepanno.ast;
import com.android.tools.r8.keepanno.utils.Unimplemented;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public abstract class KeepMembersPattern {
public static Builder builder() {
return new Builder();
}
public static KeepMembersPattern none() {
return KeepMembersNonePattern.getInstance();
}
public static KeepMembersPattern all() {
return KeepMembersAllPattern.getInstance();
}
public static class Builder {
private boolean anyMethod = false;
private boolean anyField = false;
private List<KeepMethodPattern> methods = new ArrayList<>();
private List<KeepFieldPattern> fields = new ArrayList<>();
public Builder addMethodPattern(KeepMethodPattern methodPattern) {
if (anyMethod) {
return this;
}
if (methodPattern.isAnyMethod()) {
methods.clear();
anyMethod = true;
}
methods.add(methodPattern);
return this;
}
public Builder addFieldPattern(KeepFieldPattern fieldPattern) {
if (anyField) {
return this;
}
if (fieldPattern.isAnyField()) {
fields.clear();
anyField = true;
}
fields.add(fieldPattern);
return this;
}
public KeepMembersPattern build() {
if (methods.isEmpty() && fields.isEmpty()) {
return KeepMembersPattern.none();
}
if (anyMethod && anyField) {
return KeepMembersPattern.all();
}
return new KeepMembersSomePattern(methods, fields);
}
}
private static class KeepMembersAllPattern extends KeepMembersPattern {
private static KeepMembersAllPattern INSTANCE = null;
public static KeepMembersAllPattern getInstance() {
if (INSTANCE == null) {
INSTANCE = new KeepMembersAllPattern();
}
return INSTANCE;
}
@Override
public boolean isAll() {
return true;
}
@Override
public boolean isNone() {
return true;
}
@Override
public void forEach(Consumer<KeepFieldPattern> onField, Consumer<KeepMethodPattern> onMethod) {
throw new Unimplemented("Should this include all and none?");
}
@Override
public boolean equals(Object obj) {
return this == obj;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public String toString() {
return "*";
}
}
private static class KeepMembersNonePattern extends KeepMembersPattern {
private static KeepMembersNonePattern INSTANCE = null;
public static KeepMembersNonePattern getInstance() {
if (INSTANCE == null) {
INSTANCE = new KeepMembersNonePattern();
}
return INSTANCE;
}
@Override
public boolean isAll() {
return false;
}
@Override
public boolean isNone() {
return true;
}
@Override
public void forEach(Consumer<KeepFieldPattern> onField, Consumer<KeepMethodPattern> onMethod) {
throw new Unimplemented("Should this include all and none?");
}
@Override
public boolean equals(Object obj) {
return this == obj;
}
@Override
public int hashCode() {
return System.identityHashCode(this);
}
@Override
public String toString() {
return "<none>";
}
}
private static class KeepMembersSomePattern extends KeepMembersPattern {
private final List<KeepMethodPattern> methods;
private final List<KeepFieldPattern> fields;
private KeepMembersSomePattern(List<KeepMethodPattern> methods, List<KeepFieldPattern> fields) {
assert !methods.isEmpty() || !fields.isEmpty();
this.methods = methods;
this.fields = fields;
}
@Override
public boolean isAll() {
// Since there is at least one none-all field or method this is not a match all.
return false;
}
@Override
public boolean isNone() {
// Since there is at least one field or method this is not a match none.
return false;
}
@Override
public void forEach(Consumer<KeepFieldPattern> onField, Consumer<KeepMethodPattern> onMethod) {
fields.forEach(onField);
methods.forEach(onMethod);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
KeepMembersSomePattern that = (KeepMembersSomePattern) obj;
return methods.equals(that.methods) && fields.equals(that.fields);
}
@Override
public int hashCode() {
return Objects.hash(methods, fields);
}
@Override
public String toString() {
return "KeepMembersSomePattern{"
+ "methods={"
+ methods.stream().map(Object::toString).collect(Collectors.joining(", "))
+ "}, fields={"
+ fields.stream().map(Object::toString).collect(Collectors.joining(", "))
+ "}}";
}
}
private KeepMembersPattern() {}
public abstract boolean isAll();
public abstract boolean isNone();
public abstract void forEach(
Consumer<KeepFieldPattern> onField, Consumer<KeepMethodPattern> onMethod);
}