blob: 7f9ff8c8f9430115502b56dea49494ab0c5e17fd [file] [log] [blame]
// Copyright (c) 2017, 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.shaking;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.graph.AccessFlags;
import com.android.tools.r8.graph.ClassAccessFlags;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.function.BooleanSupplier;
public class ProguardAccessFlags {
private final static int PPP_MASK =
new ProguardAccessFlags().setPublic().setProtected().setPrivate().flags;
private int flags = 0;
// Ordered list of flag names. Must be consistent with getPredicates.
private static final List<String> NAMES = ImmutableList.of(
"public",
"private",
"protected",
"static",
"final",
"abstract",
"volatile",
"transient",
"synchronized",
"native",
"strictfp",
"synthetic",
"bridge"
);
// Get ordered list of flag predicates. Must be consistent with getNames.
private List<BooleanSupplier> getPredicates() {
return ImmutableList.of(
this::isPublic,
this::isPrivate,
this::isProtected,
this::isStatic,
this::isFinal,
this::isAbstract,
this::isVolatile,
this::isTransient,
this::isSynchronized,
this::isNative,
this::isStrict,
this::isSynthetic,
this::isBridge);
}
private boolean containsAll(int other) {
// ppp flags are the flags public, protected and private.
return
// All non-ppp flags set must match (a 0 in non-ppp flags means don't care).
(((flags & ~PPP_MASK) & (other & ~PPP_MASK)) == (flags & ~PPP_MASK))
// With no ppp flags any flags match, with ppp flags there must be an overlap to match.
&& (((flags & PPP_MASK) == 0) || ((flags & PPP_MASK) & (other & PPP_MASK)) != 0);
}
private boolean containsNone(int other) {
return (flags & other) == 0;
}
public boolean containsAll(AccessFlags other) {
return containsAll(other.getOriginalAccessFlags());
}
public boolean containsNone(AccessFlags other) {
return containsNone(other.getOriginalAccessFlags());
}
public void setFlags(AccessFlags other) {
this.flags = other.getOriginalAccessFlags();
}
public ProguardAccessFlags setPublic() {
set(Constants.ACC_PUBLIC);
return this;
}
public boolean isPublic() {
return isSet(Constants.ACC_PUBLIC);
}
public ProguardAccessFlags setPrivate() {
set(Constants.ACC_PRIVATE);
return this;
}
public boolean isPrivate() {
return isSet(Constants.ACC_PRIVATE);
}
public ProguardAccessFlags setProtected() {
set(Constants.ACC_PROTECTED);
return this;
}
public boolean isProtected() {
return isSet(Constants.ACC_PROTECTED);
}
public void setVisibility(ClassAccessFlags classAccessFlags) {
if (classAccessFlags.isPublic()) {
setPublic();
} else if (classAccessFlags.isProtected()) {
setProtected();
} else if (classAccessFlags.isPrivate()) {
setPrivate();
}
}
public void setStatic() {
set(Constants.ACC_STATIC);
}
public boolean isStatic() {
return isSet(Constants.ACC_STATIC);
}
public void setFinal() {
set(Constants.ACC_FINAL);
}
public boolean isFinal() {
return isSet(Constants.ACC_FINAL);
}
public void setAbstract() {
set(Constants.ACC_ABSTRACT);
}
public boolean isAbstract() {
return isSet(Constants.ACC_ABSTRACT);
}
public void setVolatile() {
set(Constants.ACC_VOLATILE);
}
public boolean isVolatile() {
return isSet(Constants.ACC_VOLATILE);
}
public void setTransient() {
set(Constants.ACC_TRANSIENT);
}
public boolean isTransient() {
return isSet(Constants.ACC_TRANSIENT);
}
public void setSynchronized() {
set(Constants.ACC_SYNCHRONIZED);
}
public boolean isSynchronized() {
return isSet(Constants.ACC_SYNCHRONIZED);
}
public void setNative() {
set(Constants.ACC_NATIVE);
}
public boolean isNative() {
return isSet(Constants.ACC_NATIVE);
}
public void setStrict() {
set(Constants.ACC_STRICT);
}
public boolean isStrict() {
return isSet(Constants.ACC_STRICT);
}
public void setSynthetic() {
set(Constants.ACC_SYNTHETIC);
}
public boolean isSynthetic() {
return isSet(Constants.ACC_SYNTHETIC);
}
public void setBridge() {
set(Constants.ACC_BRIDGE);
}
public boolean isBridge() {
return isSet(Constants.ACC_BRIDGE);
}
private boolean isSet(int flag) {
return (flags & flag) != 0;
}
private void set(int flag) {
flags |= flag;
}
@Override
public String toString() {
List<BooleanSupplier> predicates = getPredicates();
StringBuilder builder = new StringBuilder();
boolean space = false;
for (int i = 0; i < NAMES.size(); i++) {
if (predicates.get(i).getAsBoolean()) {
if (space) {
builder.append(' ');
} else {
space = true;
}
builder.append(NAMES.get(i));
}
}
return builder.toString();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ProguardAccessFlags)) {
return false;
}
return this.flags == ((ProguardAccessFlags) obj).flags;
}
@Override
public int hashCode() {
return flags;
}
}