Skip to content

Commit

Permalink
General code improvements and cleanup (#513)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjamin-bader authored Oct 10, 2023
1 parent 54bb551 commit 0cf2630
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 98 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ version = VERSION_NAME
description = POM_DESCRIPTION

java {
sourceCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_11
}

sourceSets {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,6 @@ class IntegrationSpec extends Specification {
"7.0.0" | "7.6" || 7355 | 926 | 2592
}

@Unroll
@Ignore
def "completes successfully using AGP #agpVersion and Gradle #gradleVersion"() {
given: "an integration test project"
def project = projectDir(agpVersion, gradleVersion)

when:
def result = GradleRunner.create()
.withGradleVersion(gradleVersion)
.withProjectDir(project)
.withArguments(":app:countDebugDexMethods", "--stacktrace")
.build()

then:
result.task(":app:countDebugDexMethods").outcome == TaskOutcome.SUCCESS

// These version combinations were known to fail at some point.
// This spec serves to guard against regression.
where:
agpVersion | gradleVersion | reportedIn
"4.0.0" | "6.1.1" | "https://github.com/KeepSafe/dexcount-gradle-plugin/issues/410"
}

@Unroll
def "counting AARs using AGP #agpVersion and Gradle #gradleVersion"() {
given: "an integration test project"
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/getkeepsafe/dexcount/CountReporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ private void printSummary() {
logger.warn("Classes remaining in " + inputRepresentation + ": " + classesRemaining);
}

if (options.getTeamCityIntegration() || (options.getTeamCitySlug() != null && options.getTeamCitySlug().length() > 0)) {
if (options.getTeamCityIntegration() || options.hasTeamCitySlug()) {
String slug = "Dexcount";
if (options.getTeamCitySlug() != null) {
slug += "_" + options.getTeamCitySlug().replace(' ', '_');
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/getkeepsafe/dexcount/Deobfuscator.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class Deobfuscator {
* lines that start with an identifier character. We can just pluck them
* out of the file with a regex.
*/
private static final Pattern CLASS_LINE = Pattern.compile("^([a-zA-Z][^\\s]*) -> ([^:]+):$");
private static final Pattern CLASS_LINE = Pattern.compile("^([a-zA-Z]\\S*) -> ([^:]+):$");

public static final Deobfuscator EMPTY = new Deobfuscator(Collections.emptyMap());

Expand Down
142 changes: 96 additions & 46 deletions src/main/java/com/getkeepsafe/dexcount/PackageTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import com.android.dexdeps.MethodRef;
import com.android.dexdeps.Output;
import com.google.gson.stream.JsonWriter;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
Expand All @@ -44,16 +45,46 @@ private enum Type {
REFERENCED,
}

private static class Totals {
Type type;
int classTotal = -1;
int methodTotal = -1;
int fieldTotal = -1;
LinkedHashSet<MethodRef> methods = new LinkedHashSet<>();
LinkedHashSet<FieldRef> fields = new LinkedHashSet<>();

Totals(Type type) {
this.type = type;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Totals totals = (Totals) o;
return classTotal == totals.classTotal && methodTotal == totals.methodTotal
&& fieldTotal == totals.fieldTotal && type == totals.type && Objects.equals(methods,
totals.methods) && Objects.equals(fields, totals.fields);
}

@Override
public int hashCode() {
return Objects.hash(type, classTotal, methodTotal, fieldTotal, methods, fields);
}
}

private final String name;
private final boolean isClass;
private final Deobfuscator deobfuscator;

private final LinkedHashMap<Type, Integer> classTotal = new LinkedHashMap<>();
private final LinkedHashMap<Type, Integer> methodTotal = new LinkedHashMap<>();
private final LinkedHashMap<Type, Integer> fieldTotal = new LinkedHashMap<>();
private final Totals declared = new Totals(Type.DECLARED);
private final Totals referenced = new Totals(Type.REFERENCED);

private final SortedMap<String, PackageTree> children = new TreeMap<>();
private final LinkedHashMap<Type, LinkedHashSet<MethodRef>> methods = new LinkedHashMap<>();
private final LinkedHashMap<Type, LinkedHashSet<FieldRef>> fields = new LinkedHashMap<>();

public PackageTree() {
this("", false, null);
Expand All @@ -79,11 +110,6 @@ public PackageTree(String name, boolean isClass, Deobfuscator deobfuscator) {
this.name = name;
this.isClass = isClass;
this.deobfuscator = deobfuscator;

for (Type type : Type.values()) {
methods.put(type, new LinkedHashSet<>());
fields.put(type, new LinkedHashSet<>());
}
}

public String getName() {
Expand Down Expand Up @@ -118,47 +144,69 @@ public int getFieldCountDeclared() {
return getFieldCount(Type.DECLARED);
}

private int getClassCount(Type type) {
Integer maybeTotal = classTotal.get(type);
if (maybeTotal != null) {
return maybeTotal;
private Totals getTotalsForType(Type type) {
switch (type) {
case DECLARED:
return declared;

case REFERENCED:
return referenced;

default:
throw new IllegalArgumentException("Unexpected Type: " + type);
}
}

private int getClassCount(Totals totals) {
if (totals.classTotal != -1) {
return totals.classTotal;
}

if (isClass) {
classTotal.put(type, 1);
totals.classTotal = 1;
return 1;
}

int result = children.values().parallelStream().mapToInt(child -> child.getClassCount(type)).sum();
classTotal.put(type, result);
int result = children.values().parallelStream().mapToInt(child -> child.getClassCount(totals.type)).sum();
totals.classTotal = result;

return result;
}

private int getMethodCount(Type type) {
Integer maybeTotal = methodTotal.get(type);
if (maybeTotal != null) {
return maybeTotal;
private int getClassCount(Type type) {
return getClassCount(getTotalsForType(type));
}

private int getMethodCount(Totals totals) {
if (totals.methodTotal != -1) {
return totals.methodTotal;
}

int result = methods.get(type).size() + children.values().parallelStream().mapToInt(child -> child.getMethodCount(type)).sum();
methodTotal.put(type, result);
int result = totals.methods.size() + children.values().parallelStream().mapToInt(child -> child.getMethodCount(totals.type)).sum();
totals.methodTotal = result;

return result;
}

private int getFieldCount(Type type) {
Integer maybeTotal = fieldTotal.get(type);
if (maybeTotal != null) {
return maybeTotal;
private int getMethodCount(Type type) {
return getMethodCount(getTotalsForType(type));
}

private int getFieldCount(Totals totals) {
if (totals.fieldTotal != -1) {
return totals.fieldTotal;
}

int result = fields.get(type).size() + children.values().parallelStream().mapToInt(child -> child.getFieldCount(type)).sum();
fieldTotal.put(type, result);
int result = totals.fields.size() + children.values().parallelStream().mapToInt(child -> child.getFieldCount(totals.type)).sum();
totals.fieldTotal = result;

return result;
}

private int getFieldCount(Type type) {
return getFieldCount(getTotalsForType(type));
}

public void addMethodRef(MethodRef ref) {
addInternal(descriptorToDot(ref), 0, true, Type.REFERENCED, ref);
}
Expand Down Expand Up @@ -191,16 +239,18 @@ private void addInternal(String name, int startIndex, boolean isMethod, Type typ
}

if (ix == -1) {
Totals totals = child.getTotalsForType(type);
if (isMethod) {
child.methods.get(type).add((MethodRef) ref);
totals.methods.add((MethodRef) ref);
} else {
child.fields.get(type).add((FieldRef) ref);
totals.fields.add((FieldRef) ref);
}
} else {
Totals totals = getTotalsForType(type);
if (isMethod) {
methodTotal.remove(type);
totals.methodTotal = -1;
} else {
fieldTotal.remove(type);
totals.fieldTotal = -1;
}
child.addInternal(name, ix + 1, isMethod, type, ref);
}
Expand Down Expand Up @@ -397,7 +447,7 @@ private void printTreeRecursively(Appendable out, int depth, PrintOptions opts)
public void printJson(Appendable out, PrintOptions opts) throws IOException {
JsonWriter json = new JsonWriter(new Writer() {
@Override
public void write(@NotNull char[] chars, int offset, int length) throws IOException {
public void write(char @NotNull [] chars, int offset, int length) throws IOException {
out.append(CharBuffer.wrap(chars, offset, length));
}

Expand Down Expand Up @@ -599,17 +649,17 @@ public boolean equals(Object o) {
if (isClass != that.isClass) return false;
if (!name.equals(that.name)) return false;
if (!children.equals(that.children)) return false;
if (!methods.equals(that.methods)) return false;
return fields.equals(that.fields);
if (!declared.equals(that.declared)) return false;
return referenced.equals(that.referenced);
}

@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + (isClass ? 1 : 0);
result = 31 * result + children.hashCode();
result = 31 * result + methods.hashCode();
result = 31 * result + fields.hashCode();
result = 31 * result + declared.hashCode();
result = 31 * result + referenced.hashCode();
return result;
}

Expand Down Expand Up @@ -665,13 +715,13 @@ public static com.getkeepsafe.dexcount.thrift.PackageTree toThrift(PackageTree t
}

Set<com.getkeepsafe.dexcount.thrift.MethodRef> thriftMethodDecls =
tree.methods.get(Type.DECLARED).stream().map(PackageTree::methodRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));
tree.declared.methods.stream().map(PackageTree::methodRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));
Set<com.getkeepsafe.dexcount.thrift.MethodRef> thriftMethodRefs =
tree.methods.get(Type.REFERENCED).stream().map(PackageTree::methodRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));
tree.referenced.methods.stream().map(PackageTree::methodRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));
Set<com.getkeepsafe.dexcount.thrift.FieldRef> thriftFieldDecls =
tree.fields.get(Type.DECLARED).stream().map(PackageTree::fieldRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));
tree.declared.fields.stream().map(PackageTree::fieldRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));
Set<com.getkeepsafe.dexcount.thrift.FieldRef> thriftFieldRefs =
tree.fields.get(Type.REFERENCED).stream().map(PackageTree::fieldRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));
tree.referenced.fields.stream().map(PackageTree::fieldRefToThrift).collect(Collectors.toCollection(LinkedHashSet::new));

return new com.getkeepsafe.dexcount.thrift.PackageTree.Builder()
.name(tree.getName())
Expand All @@ -698,25 +748,25 @@ public static PackageTree fromThrift(com.getkeepsafe.dexcount.thrift.PackageTree

if (tree.declaredMethods != null) {
for (com.getkeepsafe.dexcount.thrift.MethodRef declaredMethod : tree.declaredMethods) {
result.methods.get(Type.DECLARED).add(methodRefFromThrift(declaredMethod));
result.declared.methods.add(methodRefFromThrift(declaredMethod));
}
}

if (tree.referencedMethods != null) {
for (com.getkeepsafe.dexcount.thrift.MethodRef referencedMethod : tree.referencedMethods) {
result.methods.get(Type.REFERENCED).add(methodRefFromThrift(referencedMethod));
result.referenced.methods.add(methodRefFromThrift(referencedMethod));
}
}

if (tree.declaredFields != null) {
for (com.getkeepsafe.dexcount.thrift.FieldRef declaredField : tree.declaredFields) {
result.fields.get(Type.DECLARED).add(fieldRefFromThrift(declaredField));
result.declared.fields.add(fieldRefFromThrift(declaredField));
}
}

if (tree.referencedFields != null) {
for (com.getkeepsafe.dexcount.thrift.FieldRef referencedField : tree.referencedFields) {
result.fields.get(Type.REFERENCED).add(fieldRefFromThrift(referencedField));
result.referenced.fields.add(fieldRefFromThrift(referencedField));
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/getkeepsafe/dexcount/PrintOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public PrintOptions withIsAndroidProject(boolean isAndroidProject) {
.build();
}

public boolean hasTeamCitySlug() {
String slug = getTeamCitySlug();
return slug != null && !slug.isEmpty();
}

@AutoValue.Builder
public abstract static class Builder {
public abstract Builder setIncludeClasses(boolean includeClasses);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/getkeepsafe/dexcount/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ private StringUtils() {
}

public static String capitalize(String text) {
if (text == null || text.length() == 0) {
if (text == null || text.isEmpty()) {
return "";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.attributes.Usage;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.PluginContainer;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.TaskContainer;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.jvm.tasks.Jar;

Expand All @@ -52,6 +55,18 @@ protected Project getProject() {
return project;
}

protected ExtensionContainer getExtensions() {
return getProject().getExtensions();
}

protected PluginContainer getPlugins() {
return getProject().getPlugins();
}

protected TaskContainer getTasks() {
return getProject().getTasks();
}

protected DexCountExtension getExt() {
return ext;
}
Expand Down Expand Up @@ -130,7 +145,7 @@ protected void registerOutputTask(
boolean isAndroid) {
String reportTaskName = String.format("count%sDexMethods", StringUtils.capitalize(variantName));

getProject().getTasks().register(reportTaskName, DexCountOutputTask.class, t -> {
getTasks().register(reportTaskName, DexCountOutputTask.class, t -> {
t.setDescription("Output dex method counts");
t.setGroup("Reporting");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public TaskApplicator create(Project project, DexCountExtension ext) {

@Override
public void apply() {
getProject().getPlugins().withType(JavaPlugin.class).configureEach(plugin -> {
getPlugins().withType(JavaPlugin.class).configureEach(plugin -> {
registerJarTask();
didCreateJarTasks = true;
});
Expand Down
Loading

0 comments on commit 0cf2630

Please sign in to comment.