| // 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", |
| "constructor"); |
| |
| // 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, |
| this::isConstructor); |
| } |
| |
| 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); |
| } |
| |
| public void setConstructor() { |
| set(Constants.ACC_CONSTRUCTOR); |
| } |
| |
| public boolean isConstructor() { |
| return isSet(Constants.ACC_CONSTRUCTOR); |
| } |
| |
| 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; |
| } |
| } |