Improve symboltable codebase
- Move shared code to pmd-core - Allow search methods to stop searching when they want to - If we are looking for a variable declaration, just search among those and not all name declarations - This is roughtly another 10% improvement on symbol table performance
This commit is contained in:

committed by
Andreas Dangel

parent
b6bc06d3d2
commit
b950929b7c
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.symboltable;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.sourceforge.pmd.util.SearchFunction;
|
||||
|
||||
public final class Applier {
|
||||
|
||||
private Applier() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
public static <E> void apply(SearchFunction<E> f, Iterator<? extends E> i) {
|
||||
while (i.hasNext() && f.applyTo(i.next())) {
|
||||
// Nothing to do
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +1,16 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.plsql.symboltable;
|
||||
|
||||
package net.sourceforge.pmd.lang.symboltable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.util.UnaryFunction;
|
||||
import net.sourceforge.pmd.util.SearchFunction;
|
||||
|
||||
public class ImageFinderFunction implements UnaryFunction<NameDeclaration> {
|
||||
public class ImageFinderFunction implements SearchFunction<NameDeclaration> {
|
||||
|
||||
private Set<String> images = new HashSet<>();
|
||||
private NameDeclaration decl;
|
||||
@ -23,10 +23,13 @@ public class ImageFinderFunction implements UnaryFunction<NameDeclaration> {
|
||||
images.addAll(imageList);
|
||||
}
|
||||
|
||||
public void applyTo(NameDeclaration nameDeclaration) {
|
||||
@Override
|
||||
public boolean applyTo(NameDeclaration nameDeclaration) {
|
||||
if (images.contains(nameDeclaration.getImage())) {
|
||||
decl = nameDeclaration;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public NameDeclaration getDecl() {
|
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.util;
|
||||
|
||||
public interface SearchFunction<E> {
|
||||
/**
|
||||
* Applies the search function over a single element.
|
||||
* @param o The element to analyze.
|
||||
* @return True if the search should continue, false otherwhise.
|
||||
*/
|
||||
boolean applyTo(E o);
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.util;
|
||||
|
||||
public interface UnaryFunction<E> {
|
||||
void applyTo(E o);
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
package net.sourceforge.pmd.lang.symboltable;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import net.sourceforge.pmd.util.SearchFunction;
|
||||
|
||||
public class ApplierTest {
|
||||
|
||||
private static class MyFunction implements SearchFunction<Object> {
|
||||
private int numCallbacks = 0;
|
||||
private final int maxCallbacks;
|
||||
|
||||
MyFunction(int maxCallbacks) {
|
||||
this.maxCallbacks = maxCallbacks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyTo(Object o) {
|
||||
this.numCallbacks++;
|
||||
return numCallbacks < maxCallbacks;
|
||||
}
|
||||
|
||||
public int getNumCallbacks() {
|
||||
return this.numCallbacks;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimple() {
|
||||
MyFunction f = new MyFunction(Integer.MAX_VALUE);
|
||||
List<Object> l = new ArrayList<>();
|
||||
l.add(new Object());
|
||||
l.add(new Object());
|
||||
l.add(new Object());
|
||||
Applier.apply(f, l.iterator());
|
||||
assertEquals(l.size(), f.getNumCallbacks());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLimit() {
|
||||
MyFunction f = new MyFunction(2);
|
||||
List<Object> l = new ArrayList<>();
|
||||
l.add(new Object());
|
||||
l.add(new Object());
|
||||
l.add(new Object());
|
||||
Applier.apply(f, l.iterator());
|
||||
assertEquals(2, f.getNumCallbacks());
|
||||
}
|
||||
|
||||
public static junit.framework.Test suite() {
|
||||
return new junit.framework.JUnit4TestAdapter(ApplierTest.class);
|
||||
}
|
||||
}
|
@ -42,7 +42,7 @@ public class ASTVariableDeclaratorId extends AbstractJavaTypeNode {
|
||||
}
|
||||
|
||||
public List<NameOccurrence> getUsages() {
|
||||
return getScope().getDeclarations().get(nameDeclaration);
|
||||
return getScope().getDeclarations(VariableNameDeclaration.class).get(nameDeclaration);
|
||||
}
|
||||
|
||||
public void bumpArrayDepth() {
|
||||
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.symboltable;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.sourceforge.pmd.util.UnaryFunction;
|
||||
|
||||
public final class Applier {
|
||||
|
||||
private Applier() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
public static <E> void apply(UnaryFunction<E> f, Iterator<? extends E> i) {
|
||||
while (i.hasNext()) {
|
||||
f.applyTo(i.next());
|
||||
}
|
||||
}
|
||||
}
|
@ -36,6 +36,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTTypeParameter;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTTypeParameters;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
import net.sourceforge.pmd.lang.java.ast.JavaParserTreeConstants;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
import net.sourceforge.pmd.lang.symboltable.Scope;
|
||||
|
@ -5,9 +5,9 @@ package net.sourceforge.pmd.lang.java.symboltable;
|
||||
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
import net.sourceforge.pmd.util.UnaryFunction;
|
||||
import net.sourceforge.pmd.util.SearchFunction;
|
||||
|
||||
public class DeclarationFinderFunction implements UnaryFunction<NameDeclaration> {
|
||||
public class DeclarationFinderFunction implements SearchFunction<NameDeclaration> {
|
||||
|
||||
private NameOccurrence occurrence;
|
||||
private NameDeclaration decl;
|
||||
@ -16,10 +16,13 @@ public class DeclarationFinderFunction implements UnaryFunction<NameDeclaration>
|
||||
this.occurrence = occurrence;
|
||||
}
|
||||
|
||||
public void applyTo(NameDeclaration nameDeclaration) {
|
||||
@Override
|
||||
public boolean applyTo(NameDeclaration nameDeclaration) {
|
||||
if (isDeclaredBefore(nameDeclaration) && isSameName(nameDeclaration)) {
|
||||
decl = nameDeclaration;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isDeclaredBefore(NameDeclaration nameDeclaration) {
|
||||
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.symboltable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.util.UnaryFunction;
|
||||
|
||||
public class ImageFinderFunction implements UnaryFunction<NameDeclaration> {
|
||||
|
||||
private Set<String> images = new HashSet<>();
|
||||
private NameDeclaration decl;
|
||||
|
||||
public ImageFinderFunction(String img) {
|
||||
images.add(img);
|
||||
}
|
||||
|
||||
public ImageFinderFunction(List<String> imageList) {
|
||||
images.addAll(imageList);
|
||||
}
|
||||
|
||||
public void applyTo(NameDeclaration nameDeclaration) {
|
||||
if (images.contains(nameDeclaration.getImage())) {
|
||||
decl = nameDeclaration;
|
||||
}
|
||||
}
|
||||
|
||||
public NameDeclaration getDecl() {
|
||||
return this.decl;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.symboltable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -10,6 +11,7 @@ import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
|
||||
@ -48,10 +50,10 @@ public class LocalScope extends AbstractJavaScope {
|
||||
}
|
||||
|
||||
public Set<NameDeclaration> findVariableHere(JavaNameOccurrence occurrence) {
|
||||
Set<NameDeclaration> result = new HashSet<>();
|
||||
if (occurrence.isThisOrSuper() || occurrence.isMethodOrConstructorInvocation()) {
|
||||
return result;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Set<NameDeclaration> result = new HashSet<>();
|
||||
DeclarationFinderFunction finder = new DeclarationFinderFunction(occurrence);
|
||||
Applier.apply(finder, getVariableDeclarations().keySet().iterator());
|
||||
if (finder.getDecl() != null) {
|
||||
|
@ -11,6 +11,8 @@ import java.util.Set;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
|
||||
|
@ -13,6 +13,8 @@ import java.util.Set;
|
||||
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTImportDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
import net.sourceforge.pmd.lang.symboltable.Scope;
|
||||
|
@ -1,31 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.symboltable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
import net.sourceforge.pmd.util.UnaryFunction;
|
||||
|
||||
public class VariableUsageFinderFunction implements UnaryFunction<NameDeclaration> {
|
||||
|
||||
private Map<NameDeclaration, List<NameOccurrence>> results = new HashMap<>();
|
||||
|
||||
private Map<NameDeclaration, List<NameOccurrence>> decls;
|
||||
|
||||
public VariableUsageFinderFunction(Map<NameDeclaration, List<NameOccurrence>> decls) {
|
||||
this.decls = decls;
|
||||
}
|
||||
|
||||
public void applyTo(NameDeclaration o) {
|
||||
results.put(o, decls.get(o));
|
||||
}
|
||||
|
||||
public Map<NameDeclaration, List<NameOccurrence>> getUsed() {
|
||||
return results;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.java.symboltable;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.symboltable.Applier;
|
||||
import net.sourceforge.pmd.util.UnaryFunction;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ApplierTest {
|
||||
|
||||
private static class MyFunction implements UnaryFunction<Object> {
|
||||
private boolean gotCallback;
|
||||
|
||||
public void applyTo(Object o) {
|
||||
this.gotCallback = true;
|
||||
}
|
||||
|
||||
public boolean gotCallback() {
|
||||
return this.gotCallback;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimple() {
|
||||
MyFunction f = new MyFunction();
|
||||
List<Object> l = new ArrayList<>();
|
||||
l.add(new Object());
|
||||
Applier.apply(f, l.iterator());
|
||||
assertTrue(f.gotCallback());
|
||||
}
|
||||
|
||||
public static junit.framework.Test suite() {
|
||||
return new junit.framework.JUnit4TestAdapter(ApplierTest.class);
|
||||
}
|
||||
}
|
@ -9,8 +9,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
|
||||
import org.junit.Test;
|
||||
|
@ -1,45 +0,0 @@
|
||||
package net.sourceforge.pmd.lang.java.symboltable;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
|
||||
import net.sourceforge.pmd.lang.java.ast.DummyJavaNode;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.JavaNameOccurrence;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.VariableNameDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.symboltable.VariableUsageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
|
||||
import org.junit.Test;
|
||||
public class VariableUsageFinderFunctionTest {
|
||||
|
||||
@Test
|
||||
public void testLookingForUsed() {
|
||||
ASTVariableDeclaratorId variableDeclarationIdNode = new ASTVariableDeclaratorId(1);
|
||||
variableDeclarationIdNode.setImage("x");
|
||||
VariableNameDeclaration nameDeclaration = new VariableNameDeclaration(variableDeclarationIdNode);
|
||||
List<NameOccurrence> nameOccurrences = new ArrayList<>();
|
||||
nameOccurrences.add(new JavaNameOccurrence(new DummyJavaNode(2), "x"));
|
||||
|
||||
Map<NameDeclaration, List<NameOccurrence>> declarations = new HashMap<>();
|
||||
declarations.put(nameDeclaration, nameOccurrences);
|
||||
|
||||
List<NameDeclaration> vars = new ArrayList<>();
|
||||
vars.add(nameDeclaration);
|
||||
|
||||
VariableUsageFinderFunction f = new VariableUsageFinderFunction(declarations);
|
||||
Applier.apply(f, vars.iterator());
|
||||
Map<NameDeclaration, List<NameOccurrence>> p = f.getUsed();
|
||||
assertEquals(1, p.size());
|
||||
}
|
||||
|
||||
public static junit.framework.Test suite() {
|
||||
return new junit.framework.JUnit4TestAdapter(VariableUsageFinderFunctionTest.class);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
package net.sourceforge.pmd.lang.plsql.symboltable;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import net.sourceforge.pmd.util.UnaryFunction;
|
||||
|
||||
public final class Applier {
|
||||
|
||||
private Applier() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
public static <E> void apply(UnaryFunction<E> f, Iterator<? extends E> i) {
|
||||
while (i.hasNext()) {
|
||||
f.applyTo(i.next());
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,8 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.plsql.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.plsql.ast.AbstractPLSQLNode;
|
||||
import net.sourceforge.pmd.lang.symboltable.AbstractScope;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
|
||||
|
@ -11,6 +11,8 @@ import java.util.Set;
|
||||
import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.plsql.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.symboltable.AbstractScope;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
|
||||
|
@ -12,6 +12,8 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
import net.sourceforge.pmd.lang.plsql.ast.ASTName;
|
||||
import net.sourceforge.pmd.lang.plsql.ast.AbstractPLSQLNode;
|
||||
import net.sourceforge.pmd.lang.symboltable.AbstractScope;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
package net.sourceforge.pmd.lang.plsql.symboltable;
|
||||
|
||||
import net.sourceforge.pmd.lang.symboltable.AbstractScope;
|
||||
import net.sourceforge.pmd.lang.symboltable.Applier;
|
||||
import net.sourceforge.pmd.lang.symboltable.ImageFinderFunction;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameDeclaration;
|
||||
import net.sourceforge.pmd.lang.symboltable.NameOccurrence;
|
||||
|
||||
|
Reference in New Issue
Block a user