Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Refaster matching algorithm compatible with the fork and mainline Error Prone #235

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<modules>
<module>error-prone-contrib</module>
<module>refaster-compiler</module>
<module>refaster-rule-selector</module>
<module>refaster-runner</module>
<module>refaster-support</module>
<module>refaster-test-support</module>
Expand Down Expand Up @@ -144,7 +145,7 @@
<version.auto-service>1.0.1</version.auto-service>
<version.auto-value>1.9</version.auto-value>
<version.error-prone>${version.error-prone-orig}</version.error-prone>
<version.error-prone-fork>v${version.error-prone-orig}-picnic-2</version.error-prone-fork>
<version.error-prone-fork>v${version.error-prone-orig}-picnic-3</version.error-prone-fork>
<version.error-prone-orig>2.14.0</version.error-prone-orig>
<version.error-prone-slf4j>0.1.15</version.error-prone-slf4j>
<version.guava-beta-checker>1.0</version.guava-beta-checker>
Expand Down Expand Up @@ -197,6 +198,11 @@
<artifactId>refaster-compiler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-rule-selector</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-runner</artifactId>
Expand Down Expand Up @@ -224,6 +230,11 @@
<artifactId>auto-common</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>${version.auto-service}</version>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service-annotations</artifactId>
Expand All @@ -244,6 +255,13 @@
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<!-- XXX: TBH, not sure where this one should go.
Discussed this with Stephan. -->
<!-- <dependency>-->
<!-- <groupId>com.google.errorprone</groupId>-->
<!-- <artifactId>error_prone_annotations</artifactId>-->
<!-- <version>${version.error-prone-orig}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.google.googlejavaformat</groupId>
<artifactId>google-java-format</artifactId>
Expand Down Expand Up @@ -417,6 +435,13 @@
</dependencies>
</dependencyManagement>

<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>

<build>
<pluginManagement>
<plugins>
Expand Down Expand Up @@ -793,6 +818,11 @@
<artifactId>error_prone_core</artifactId>
<version>${version.error-prone}</version>
</path>
<path>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value</artifactId>
<version>${version.auto-value}</version>
</path>
<path>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
Expand Down Expand Up @@ -1522,6 +1552,11 @@
Prone bug pattern checkers, so we enable
all and then selectively deactivate some. -->
-XepAllDisabledChecksAsWarnings
<!-- Some generated classes violate Error
Prone bug patterns. We cannot in all cases
avoid that, so we simply tell Error Prone
not to warn about generated code. -->
-XepDisableWarningsInGeneratedCode
<!-- We don't target Android. -->
-Xep:AndroidJdkLibsChecker:OFF
<!-- XXX: Enable this once we open-source
Expand Down
72 changes: 72 additions & 0 deletions refaster-rule-selector/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>tech.picnic.error-prone-support</groupId>
<artifactId>error-prone-support</artifactId>
<version>0.2.1-SNAPSHOT</version>
</parent>

<artifactId>refaster-rule-selector</artifactId>

<name>Picnic :: Error Prone Support :: Refaster Rule Selector</name>
<!-- XXX: Improve text -->
<description>Select rules based on the Error Prone distribution.</description>

<properties>
<groupId.error-prone>com.github.PicnicSupermarket.error-prone</groupId.error-prone>
<version.error-prone>v2.14.0-picnic-3</version.error-prone>
</properties>

<dependencies>
<dependency>
<groupId>${groupId.error-prone}</groupId>
<artifactId>error_prone_core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value-annotations</artifactId>
<version>${version.auto-value}</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths combine.children="append">
<path>
<groupId>${project.groupId}</groupId>
<artifactId>refaster-compiler</artifactId>
<version>${project.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs combine.children="append">
<arg>-Xplugin:RefasterRuleCompiler</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package tech.picnic.errorprone.rule.selector;

import com.google.auto.service.AutoService;
import com.google.errorprone.refaster.RefasterRule;
import com.sun.source.tree.CompilationUnitTree;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/** XXX: Write this */
@AutoService(RefasterRuleSelector.class)
public final class DefaultRefasterRuleSelector implements RefasterRuleSelector {
private final List<RefasterRule<?, ?>> refasterRules;

/**
* XXX: Write this.
*
* @param refasterRules XXX: Write this
*/
public DefaultRefasterRuleSelector(List<RefasterRule<?, ?>> refasterRules) {
this.refasterRules = refasterRules;
}

@Override
public Set<RefasterRule<?, ?>> selectCandidateRules(CompilationUnitTree tree) {
return new HashSet<>(refasterRules);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package tech.picnic.errorprone.rule.selector;

import com.google.errorprone.refaster.RefasterRule;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;

/** XXX: Write */
public final class DefaultRuleSelectorFactory implements RefasterRuleSelectorFactory {
/**
* XXX: Write this.
*
* @param classLoader Test
* @param refasterRules Test
* @return Test
*/
@Override
public RefasterRuleSelector createRefasterRuleSelector(
ClassLoader classLoader, List<RefasterRule<?, ?>> refasterRules) {
return isClassPathCompatible(classLoader)
? new SmartRefasterRuleSelector(refasterRules)
: new DefaultRefasterRuleSelector(refasterRules);
}

/**
* XXX: Write this
*
* @param classLoader Test
* @return Test
*/
@Override
public boolean isClassPathCompatible(ClassLoader classLoader) {
Class<?> clazz;
try {
clazz =
Class.forName(
"com.google.errorprone.ErrorProneOptions", /* initialize= */ false, classLoader);
} catch (ClassNotFoundException e) {
return false;
// throw new IllegalStateException("Cannot load
// `com.google.errorprone.ErrorProneOptions`", e);
}

return Arrays.stream(clazz.getDeclaredMethods())
.filter(m -> Modifier.isPublic(m.getModifiers()))
.anyMatch(m -> m.getName().equals("isSuggestionsAsWarnings"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package tech.picnic.errorprone.rule.selector;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Maps;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

/**
* A node in an immutable tree.
*
* <p>The tree's edges are string-labeled, while its leaves store values of type {@code T}.
*/
@AutoValue
abstract class Node<T> {
static <T> Node<T> create(Map<String, Node<T>> children, ImmutableList<T> values) {
return new AutoValue_Node<>(ImmutableSortedMap.copyOf(children), values);
}

static <T> Node<T> create(
List<T> values, Function<T, ImmutableSet<ImmutableSortedSet<String>>> pathExtractor) {
BuildNode<T> tree = BuildNode.create();
tree.register(values, pathExtractor);
return tree.immutable();
}

abstract ImmutableMap<String, Node<T>> children();

abstract ImmutableList<T> values();

void collectCandidateTemplates(ImmutableList<String> candidateEdges, Consumer<T> sink) {
values().forEach(sink);

if (candidateEdges.isEmpty() || children().isEmpty()) {
return;
}

if (children().size() < candidateEdges.size()) {
for (Map.Entry<String, Node<T>> e : children().entrySet()) {
if (candidateEdges.contains(e.getKey())) {
e.getValue().collectCandidateTemplates(candidateEdges, sink);
}
}
} else {
ImmutableList<String> remainingCandidateEdges =
candidateEdges.subList(1, candidateEdges.size());
Node<T> child = children().get(candidateEdges.get(0));
if (child != null) {
child.collectCandidateTemplates(remainingCandidateEdges, sink);
}
collectCandidateTemplates(remainingCandidateEdges, sink);
}
}

@AutoValue
@SuppressWarnings("AutoValueImmutableFields" /* Type is used only during `Node` construction. */)
abstract static class BuildNode<T> {
static <T> BuildNode<T> create() {
return new AutoValue_Node_BuildNode<>(new HashMap<>(), new ArrayList<>());
}

abstract Map<String, BuildNode<T>> children();

abstract List<T> values();

private void register(
List<T> values, Function<T, ImmutableSet<ImmutableSortedSet<String>>> pathsExtractor) {
for (T value : values) {
for (ImmutableSet<String> path : pathsExtractor.apply(value)) {
registerPath(value, path.asList());
}
}
}

private void registerPath(T value, ImmutableList<String> path) {
path.stream()
.findFirst()
.ifPresentOrElse(
edge ->
children()
.computeIfAbsent(edge, k -> BuildNode.create())
.registerPath(value, path.subList(1, path.size())),
() -> values().add(value));
}

private Node<T> immutable() {
return Node.create(
Maps.transformValues(children(), BuildNode::immutable), ImmutableList.copyOf(values()));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package tech.picnic.errorprone.rule.selector;

import com.google.errorprone.refaster.RefasterRule;
import com.sun.source.tree.CompilationUnitTree;
import java.util.Set;

/** XXX: Write this. */
public interface RefasterRuleSelector {
/**
* XXX: Write this
*
* @param tree XXX: Write this
* @return XXX: Write this
*/
Set<RefasterRule<?, ?>> selectCandidateRules(CompilationUnitTree tree);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package tech.picnic.errorprone.rule.selector;

import com.google.errorprone.refaster.RefasterRule;
import java.util.List;

/** XXX: Write this */
public interface RefasterRuleSelectorFactory {
/**
* XXX: Write this
*
* @param classLoader XXX: Write this
* @param refasterRules XXX: Write this
* @return XXX: Write this
*/
RefasterRuleSelector createRefasterRuleSelector(
ClassLoader classLoader, List<RefasterRule<?, ?>> refasterRules);

/**
* XXX: Write this
*
* @param classLoader XXX: Write this
* @return XXX: Write this
*/
boolean isClassPathCompatible(ClassLoader classLoader);
}
Loading