blob: dbe52b0c5be333c0ce5a6140415d0208579e4fc7 [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 java.util.Objects;
/**
* An edge in the keep graph.
*
* <p>An edge describes a set of preconditions and a set of consequences. If the preconditions are
* met, then the consequences are put into effect.
*
* <p>Below is a BNF of the keep edge AST for reference. The non-terminals are written in ALL_CAPS,
* possibly-empty repeatable subexpressions denoted with SUB* and non-empty with SUB+
*
* <p>In the Java AST, the non-terminals are prefixed with 'Keep' and in CamelCase.
*
* <p>TODO(b/248408342): Update the BNF and AST to be complete.
*
* <pre>
* EDGE ::= METAINFO PRECONDITIONS -> CONSEQUENCES
* METAINFO = [CONTEXT] [DESCRIPTION]
* CONTEXT = class-descriptor | method-descriptor | field-descriptor
* DESCRIPTION = string-content
*
* PRECONDITIONS ::= always | CONDITION+
* CONDITION ::= ITEM_PATTERN
*
* CONSEQUENCES ::= TARGET+
* TARGET ::= OPTIONS ITEM_PATTERN
* OPTIONS ::= keep-all | OPTION+
* OPTION ::= shrinking | optimizing | obfuscating | access-modification | annotation-removal
*
* ITEM_PATTERN
* ::= any
* | class QUALIFIED_CLASS_NAME_PATTERN extends EXTENDS_PATTERN { MEMBER_PATTERN }
*
* TYPE_PATTERN ::= any | exact type-descriptor
* PACKAGE_PATTERN ::= any | exact package-name
* QUALIFIED_CLASS_NAME_PATTERN ::= any | PACKAGE_PATTERN | UNQUALIFIED_CLASS_NAME_PATTERN
* UNQUALIFIED_CLASS_NAME_PATTERN ::= any | exact simple-class-name
* EXTENDS_PATTERN ::= any | QUALIFIED_CLASS_NAME_PATTERN
*
* MEMBER_PATTERN ::= none | all | FIELD_PATTERN | METHOD_PATTERN
*
* FIELD_PATTERN
* ::= FIELD_ACCESS_PATTERN
* FIELD_TYPE_PATTERN
* FIELD_NAME_PATTERN;
*
* METHOD_PATTERN
* ::= METHOD_ACCESS_PATTERN
* METHOD_RETURN_TYPE_PATTERN
* METHOD_NAME_PATTERN
* METHOD_PARAMETERS_PATTERN
*
* METHOD_ACCESS_PATTERN ::= any
* METHOD_NAME_PATTERN ::= any | exact method-name
* METHOD_RETURN_TYPE_PATTERN ::= void | TYPE_PATTERN
* METHOD_PARAMETERS_PATTERN ::= any | none | (TYPE_PATTERN+)
* </pre>
*/
public final class KeepEdge {
public static class Builder {
private KeepEdgeMetaInfo metaInfo = KeepEdgeMetaInfo.none();
private KeepPreconditions preconditions = KeepPreconditions.always();
private KeepConsequences consequences;
private Builder() {}
public Builder setPreconditions(KeepPreconditions preconditions) {
this.preconditions = preconditions;
return this;
}
public Builder setConsequences(KeepConsequences consequences) {
this.consequences = consequences;
return this;
}
public Builder setMetaInfo(KeepEdgeMetaInfo metaInfo) {
this.metaInfo = metaInfo;
return this;
}
public KeepEdge build() {
if (consequences.isEmpty()) {
throw new KeepEdgeException("KeepEdge must have non-empty set of consequences.");
}
return new KeepEdge(preconditions, consequences, metaInfo);
}
}
public static Builder builder() {
return new Builder();
}
private final KeepEdgeMetaInfo metaInfo;
private final KeepPreconditions preconditions;
private final KeepConsequences consequences;
private KeepEdge(
KeepPreconditions preconditions, KeepConsequences consequences, KeepEdgeMetaInfo metaInfo) {
assert preconditions != null;
assert consequences != null;
assert metaInfo != null;
this.preconditions = preconditions;
this.consequences = consequences;
this.metaInfo = metaInfo;
}
public KeepEdgeMetaInfo getMetaInfo() {
return metaInfo;
}
public KeepPreconditions getPreconditions() {
return preconditions;
}
public KeepConsequences getConsequences() {
return consequences;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
KeepEdge keepEdge = (KeepEdge) o;
return preconditions.equals(keepEdge.preconditions)
&& consequences.equals(keepEdge.consequences);
}
@Override
public int hashCode() {
return Objects.hash(preconditions, consequences);
}
@Override
public String toString() {
return "KeepEdge{" + "preconditions=" + preconditions + ", consequences=" + consequences + '}';
}
}