Skip to content

Commit

Permalink
Improve Refaster matching algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephan202 authored and rickie committed May 21, 2022
1 parent 3edc483 commit 87dfe9c
Show file tree
Hide file tree
Showing 7 changed files with 428 additions and 14 deletions.
5 changes: 5 additions & 0 deletions error-prone-contrib/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@
<artifactId>auto-service-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.auto.value</groupId>
<artifactId>auto-value-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package tech.picnic.errorprone.bugpatterns;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
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.HashSet;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

@AutoValue
abstract class BuildNode<T> {
static <T> BuildNode<T> create() {
return new AutoValue_BuildNode<>(new TreeMap<>(), new HashSet<>());
}

static <T> BuildNode<T> create(SortedMap<String, BuildNode<T>> children, Set<T> candidateRules) {
return new AutoValue_BuildNode<>(children, candidateRules);
}

@SuppressWarnings("AutoValueImmutableFields" /* The BuildNode is used to construct the tree. */)
public abstract SortedMap<String, BuildNode<T>> children();

@SuppressWarnings("AutoValueImmutableFields" /* The BuildNode is used to construct the tree. */)
public abstract Set<T> candidateRules();

public void register(ImmutableSet<ImmutableSortedSet<String>> identifierCombinations, T rule) {
for (ImmutableSet<String> path : identifierCombinations) {
registerPath(path.asList(), rule);
}
}

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

Node<T> immutable() {
return Node.create(
Maps.transformValues(ImmutableSortedMap.copyOfSorted(children()), BuildNode::immutable),
ImmutableSet.copyOf(candidateRules()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package tech.picnic.errorprone.bugpatterns;

import static com.google.common.collect.ImmutableList.toImmutableList;

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.ImmutableSortedSet;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

@AutoValue
abstract class Node<T> {
static <T> Node<T> create(Map<String, Node<T>> children, ImmutableSet<T> candidateRules) {
return new AutoValue_Node<>(ImmutableMap.copyOf(children), candidateRules);
}

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

public abstract ImmutableSet<T> candidateRules();

static <C> Node<C> createRefasterTemplateTree(
List<C> refasterRules, Function<C, ImmutableSet<ImmutableSortedSet<String>>> edgeExtractor) {
// XXX: Improve this method...
List<ImmutableSet<ImmutableSortedSet<String>>> beforeTemplateIdentifiers =
refasterRules.stream().map(edgeExtractor).collect(toImmutableList());

BuildNode<C> tree = BuildNode.create();
for (int i = 0; i < refasterRules.size(); i++) {
tree.register(beforeTemplateIdentifiers.get(i), refasterRules.get(i));
}
return tree.immutable();
}

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

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

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

0 comments on commit 87dfe9c

Please sign in to comment.