blob: 9286d0afe63aff41112c5d1df7fc155d4c89ff4b [file] [log] [blame]
// Copyright (c) 2016, 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;
public abstract class ProguardNameMatcher {
private static final ProguardNameMatcher MATCH_ALL_NAMES = new MatchAllNames();
private ProguardNameMatcher() {
}
public static ProguardNameMatcher create(String pattern) {
if (pattern.equals("*")) {
return MATCH_ALL_NAMES;
} else if (pattern.contains("*") || pattern.contains("?")) {
return new MatchNamePattern(pattern);
} else {
return new MatchSpecificName(pattern);
}
}
/**
* Determines if the proguard name pattern matches the given field or method name.
*
* @param pattern Proguard name pattern potentially with wildcards: ?, *.
* @param name The name to match against.
* @return true iff the pattern matches the name.
*/
public static boolean matchFieldOrMethodName(String pattern, String name) {
return matchFieldOrMethodNameImpl(pattern, 0, name, 0);
}
private static boolean matchFieldOrMethodNameImpl(
String pattern, int patternIndex, String name, int nameIndex) {
for (int i = patternIndex; i < pattern.length(); i++) {
char patternChar = pattern.charAt(i);
switch (patternChar) {
case '*':
// Match the rest of the pattern against the rest of the name.
for (int nextNameIndex = nameIndex; nextNameIndex <= name.length(); nextNameIndex++) {
if (matchFieldOrMethodNameImpl(pattern, i + 1, name, nextNameIndex)) {
return true;
}
}
return false;
case '?':
if (nameIndex == name.length()) {
return false;
}
nameIndex++;
break;
default:
if (nameIndex == name.length() || patternChar != name.charAt(nameIndex++)) {
return false;
}
break;
}
}
return nameIndex == name.length();
}
public abstract boolean matches(String name);
private static class MatchAllNames extends ProguardNameMatcher {
@Override
public boolean matches(String name) {
return true;
}
@Override
public String toString() {
return "*";
}
}
private static class MatchNamePattern extends ProguardNameMatcher {
private final String pattern;
MatchNamePattern(String pattern) {
this.pattern = pattern;
}
@Override
public boolean matches(String name) {
return matchFieldOrMethodName(pattern, name);
}
@Override
public String toString() {
return pattern;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
return o instanceof MatchNamePattern && pattern.equals(((MatchNamePattern) o).pattern);
}
@Override
public int hashCode() {
return pattern.hashCode();
}
}
private static class MatchSpecificName extends ProguardNameMatcher {
private final String name;
MatchSpecificName(String name) {
this.name = name;
}
@Override
public boolean matches(String name) {
return this.name.equals(name);
}
@Override
public String toString() {
return name;
}
@Override
public boolean equals(Object o) {
return o instanceof MatchSpecificName && name.equals(((MatchSpecificName) o).name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
}