blob: afbb13f22cbe8e0f23c7aeab01beb3a8443f4596 [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.graph;
import com.android.tools.r8.dex.Constants;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.function.BooleanSupplier;
/** Access flags common to classes, methods and fields. */
public abstract class AccessFlags {
protected static final int BASE_FLAGS
= Constants.ACC_PUBLIC
| Constants.ACC_PRIVATE
| Constants.ACC_PROTECTED
| Constants.ACC_STATIC
| Constants.ACC_FINAL
| Constants.ACC_SYNTHETIC;
// Ordered list of flag names. Must be consistent with getPredicates.
private static final List<String> NAMES = ImmutableList.of(
"public",
"private",
"protected",
"static",
"final",
"synthetic"
);
// Get ordered list of flag predicates. Must be consistent with getNames.
protected List<BooleanSupplier> getPredicates() {
return ImmutableList.of(
this::isPublic,
this::isPrivate,
this::isProtected,
this::isStatic,
this::isFinal,
this::isSynthetic);
}
// Get ordered list of flag names. Must be consistent with getPredicates.
protected List<String> getNames() {
return NAMES;
}
protected int flags;
protected AccessFlags(int flags) {
this.flags = flags;
}
public abstract int getAsCfAccessFlags();
public abstract int getAsDexAccessFlags();
@Override
public boolean equals(Object other) {
if (other instanceof AccessFlags) {
return flags == ((AccessFlags) other).flags;
}
return false;
}
@Override
public int hashCode() {
return flags;
}
public boolean isMoreVisibleThan(AccessFlags other) {
return visibilityOrdinal() > other.visibilityOrdinal();
}
public boolean isAtLeastAsVisibleAs(AccessFlags other) {
return visibilityOrdinal() >= other.visibilityOrdinal();
}
private int visibilityOrdinal() {
// public > protected > package > private
if (isPublic()) {
return 3;
}
if (isProtected()) {
return 2;
}
if (isPrivate()) {
return 0;
}
// Package-private
return 1;
}
public boolean isPublic() {
return isSet(Constants.ACC_PUBLIC);
}
public void setPublic() {
assert !isPrivate() && !isProtected();
set(Constants.ACC_PUBLIC);
}
public void unsetPublic() {
unset(Constants.ACC_PUBLIC);
}
public boolean isPrivate() {
return isSet(Constants.ACC_PRIVATE);
}
public void setPrivate() {
assert !isPublic() && !isProtected();
set(Constants.ACC_PRIVATE);
}
public void unsetPrivate() {
unset(Constants.ACC_PRIVATE);
}
public boolean isProtected() {
return isSet(Constants.ACC_PROTECTED);
}
public void setProtected() {
assert !isPublic() && !isPrivate();
set(Constants.ACC_PROTECTED);
}
public void unsetProtected() {
unset(Constants.ACC_PROTECTED);
}
public boolean isStatic() {
return isSet(Constants.ACC_STATIC);
}
public void setStatic() {
set(Constants.ACC_STATIC);
}
public boolean isFinal() {
return isSet(Constants.ACC_FINAL);
}
public void setFinal() {
set(Constants.ACC_FINAL);
}
public void unsetFinal() {
unset(Constants.ACC_FINAL);
}
public boolean isSynthetic() {
return isSet(Constants.ACC_SYNTHETIC);
}
public void setSynthetic() {
set(Constants.ACC_SYNTHETIC);
}
public void unsetSynthetic() {
unset(Constants.ACC_SYNTHETIC);
}
public void promoteToPublic() {
unsetProtected();
unsetPrivate();
setPublic();
}
protected boolean isSet(int flag) {
return (flags & flag) != 0;
}
protected void set(int flag) {
flags |= flag;
}
protected void unset(int flag) {
flags &= ~flag;
}
public String toSmaliString() {
return toStringInternal(true);
}
@Override
public String toString() {
return toStringInternal(false);
}
private String toStringInternal(boolean ignoreSuper) {
List<String> names = getNames();
List<BooleanSupplier> predicates = getPredicates();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < names.size(); i++) {
if (predicates.get(i).getAsBoolean()) {
if (!ignoreSuper || !names.get(i).equals("super")) {
if (builder.length() > 0) {
builder.append(' ');
}
builder.append(names.get(i));
}
}
}
return builder.toString();
}
}