Object pooling for Signatures
This commit is contained in:
@ -9,6 +9,6 @@ import net.sourceforge.pmd.lang.ast.Node;
|
||||
/**
|
||||
* @author Clément Fournier
|
||||
*/
|
||||
public interface ASTMethodOrConstructorDeclaration extends QualifiableNode, Node {
|
||||
public interface ASTMethodOrConstructorDeclaration extends QualifiableNode, Node, AccessNode {
|
||||
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class QualifiedName {
|
||||
|
||||
|
||||
// Might be useful with type resolution
|
||||
public static QualifiedName parseJavaCanonicalName(String canon) {
|
||||
public static QualifiedName makeClassOf(Class<?> clazz) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.oom.visitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
|
||||
/**
|
||||
@ -13,6 +16,8 @@ import net.sourceforge.pmd.lang.java.ast.ASTFieldDeclaration;
|
||||
*/
|
||||
public class FieldSignature extends Signature {
|
||||
|
||||
private static final Map<Integer, FieldSignature> POOL = new HashMap<>();
|
||||
|
||||
public final boolean isStatic;
|
||||
public final boolean isFinal;
|
||||
|
||||
@ -30,7 +35,16 @@ public class FieldSignature extends Signature {
|
||||
* @return The signature of the field.
|
||||
*/
|
||||
public static FieldSignature buildFor(ASTFieldDeclaration node) {
|
||||
return new FieldSignature(Visibility.get(node), node.isStatic(), node.isFinal());
|
||||
int code = code(Visibility.get(node), node.isStatic(), node.isAbstract());
|
||||
if (!POOL.containsKey(code)) {
|
||||
POOL.put(code, new FieldSignature(Visibility.get(node), node.isStatic(), node.isAbstract()));
|
||||
}
|
||||
return POOL.get(code);
|
||||
}
|
||||
|
||||
/** Used internally by the pooler. */
|
||||
private static int code(Visibility visibility, boolean isStatic, boolean isAbstract) {
|
||||
return visibility.hashCode() * 31 + (isStatic ? 1 : 0) * 2 + (isAbstract ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.oom.visitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTConstructorDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
|
||||
import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
|
||||
@ -15,44 +18,18 @@ import net.sourceforge.pmd.lang.java.ast.ASTMethodOrConstructorDeclaration;
|
||||
*/
|
||||
public class OperationSignature extends Signature {
|
||||
|
||||
public final Role role;
|
||||
private static final Map<Integer, OperationSignature> POOL = new HashMap<>();
|
||||
|
||||
public final Role role;
|
||||
public final boolean isAbstract;
|
||||
|
||||
public OperationSignature(Visibility visibility, Role role, boolean isAbstract) {
|
||||
|
||||
private OperationSignature(Visibility visibility, Role role, boolean isAbstract) {
|
||||
super(visibility);
|
||||
this.role = role;
|
||||
this.isAbstract = isAbstract;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an operation signature from a method declaration.
|
||||
*
|
||||
* @param node The method declaration
|
||||
*
|
||||
* @return The signature of the parameter
|
||||
*/
|
||||
public static OperationSignature buildFor(ASTMethodDeclaration node) {
|
||||
// TODO better getter or setter detection
|
||||
boolean isGetterOrSetter = node.getName().startsWith("get")
|
||||
|| node.getName().startsWith("set");
|
||||
Role role = isGetterOrSetter ? Role.GETTER_OR_SETTER
|
||||
: node.isStatic() ? Role.STATIC : Role.METHOD;
|
||||
|
||||
return new OperationSignature(Visibility.get(node), role, node.isAbstract());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an operation signature from a constructor declaration.
|
||||
*
|
||||
* @param node The constructor declaration
|
||||
*
|
||||
* @return The signature of the parameter
|
||||
*/
|
||||
public static OperationSignature buildFor(ASTConstructorDeclaration node) {
|
||||
return new OperationSignature(Visibility.get(node), Role.CONSTRUCTOR, node.isAbstract());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an operation signature from a method or constructor declaration.
|
||||
*
|
||||
@ -61,14 +38,21 @@ public class OperationSignature extends Signature {
|
||||
* @return The signature of the parameter
|
||||
*/
|
||||
public static OperationSignature buildFor(ASTMethodOrConstructorDeclaration node) {
|
||||
return node instanceof ASTMethodDeclaration ? buildFor((ASTMethodDeclaration) node)
|
||||
: buildFor((ASTConstructorDeclaration) node);
|
||||
int code = code(Visibility.get(node), Role.get(node), node.isAbstract());
|
||||
if (!POOL.containsKey(code)) {
|
||||
POOL.put(code, new OperationSignature(Visibility.get(node), Role.get(node), node.isAbstract()));
|
||||
}
|
||||
return POOL.get(code);
|
||||
}
|
||||
|
||||
/** Used internally by the pooler. */
|
||||
private static int code(Visibility visibility, Role role, boolean isAbstract) {
|
||||
return visibility.hashCode() * 31 + role.hashCode() * 2 + (isAbstract ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof OperationSignature && super.equals(o) && role == (
|
||||
(OperationSignature) o).role
|
||||
return o instanceof OperationSignature && super.equals(o) && role == ((OperationSignature) o).role
|
||||
&& isAbstract == ((OperationSignature) o).isAbstract;
|
||||
}
|
||||
|
||||
@ -81,6 +65,18 @@ public class OperationSignature extends Signature {
|
||||
* Role of an operation.
|
||||
*/
|
||||
public enum Role {
|
||||
GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC
|
||||
GETTER_OR_SETTER, CONSTRUCTOR, METHOD, STATIC;
|
||||
|
||||
public static Role get(ASTMethodOrConstructorDeclaration node) {
|
||||
return node instanceof ASTConstructorDeclaration ? CONSTRUCTOR : get((ASTMethodDeclaration) node);
|
||||
}
|
||||
|
||||
private static Role get(ASTMethodDeclaration node) {
|
||||
// TODO better getter or setter detection
|
||||
boolean isGetterOrSetter = node.getName().startsWith("get")
|
||||
|| node.getName().startsWith("set");
|
||||
|
||||
return node.isStatic() ? Role.STATIC : isGetterOrSetter ? Role.GETTER_OR_SETTER : Role.METHOD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
package net.sourceforge.pmd.lang.java.oom.visitor;
|
||||
|
||||
import net.sourceforge.pmd.lang.java.ast.AbstractJavaAccessNode;
|
||||
import net.sourceforge.pmd.lang.java.ast.AccessNode;
|
||||
|
||||
/**
|
||||
* Generic signature. This class is extended by classes specific to operations and fields.
|
||||
@ -35,7 +35,6 @@ public abstract class Signature {
|
||||
public enum Visibility {
|
||||
PUBLIC, PACKAGE, PROTECTED, PRIVATE, UNDEF;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Visibility enum key for a node.
|
||||
*
|
||||
@ -43,13 +42,12 @@ public abstract class Signature {
|
||||
*
|
||||
* @return The visibility enum key for a node.
|
||||
*/
|
||||
public static Visibility get(AbstractJavaAccessNode node) {
|
||||
public static Visibility get(AccessNode node) {
|
||||
return node.isPublic() ? PUBLIC
|
||||
: node.isPackagePrivate() ? PACKAGE
|
||||
: node.isProtected() ? PROTECTED
|
||||
: node.isPrivate()
|
||||
? PRIVATE
|
||||
: UNDEF;
|
||||
: node.isPackagePrivate() ? PACKAGE
|
||||
: node.isProtected() ? PROTECTED
|
||||
: node.isPrivate() ? PRIVATE
|
||||
: UNDEF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -81,8 +81,7 @@ public class SignatureTest extends ParserTst {
|
||||
" public void doSomething(){}}";
|
||||
|
||||
|
||||
List<ASTMethodOrConstructorDeclaration> nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration
|
||||
.class, TEST);
|
||||
List<ASTMethodOrConstructorDeclaration> nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST);
|
||||
List<OperationSignature> sigs = new ArrayList<>();
|
||||
|
||||
for (ASTMethodOrConstructorDeclaration node : nodes) {
|
||||
@ -106,8 +105,7 @@ public class SignatureTest extends ParserTst {
|
||||
"public void doSomething(){}}";
|
||||
|
||||
|
||||
List<ASTMethodOrConstructorDeclaration> nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration
|
||||
.class, TEST);
|
||||
List<ASTMethodOrConstructorDeclaration> nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST);
|
||||
List<OperationSignature> sigs = new ArrayList<>();
|
||||
|
||||
for (ASTMethodOrConstructorDeclaration node : nodes) {
|
||||
@ -121,4 +119,69 @@ public class SignatureTest extends ParserTst {
|
||||
assertFalse(sigs.get(3).isAbstract);
|
||||
assertFalse(sigs.get(4).isAbstract);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void operationPoolTest() {
|
||||
final String TEST = "class Bzaz{ " +
|
||||
"public static void foo(){} " +
|
||||
"public static void az(){} " +
|
||||
"public static int getX(){return x;}}";
|
||||
|
||||
final String TEST2 = "class Bzaz{ " +
|
||||
"void foo(){} " +
|
||||
"void az(){} " +
|
||||
"int rand(){return x;}}";
|
||||
|
||||
|
||||
List<ASTMethodOrConstructorDeclaration> nodes = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST);
|
||||
List<ASTMethodOrConstructorDeclaration> nodes2 = getOrderedNodes(ASTMethodOrConstructorDeclaration.class, TEST2);
|
||||
|
||||
List<OperationSignature> sigs = new ArrayList<>();
|
||||
List<OperationSignature> sigs2 = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < sigs.size(); i++) {
|
||||
sigs.add(OperationSignature.buildFor(nodes.get(i)));
|
||||
sigs2.add(OperationSignature.buildFor(nodes2.get(i)));
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < sigs.size() - 1; i++) {
|
||||
assertTrue(sigs.get(i) == sigs.get(i + 1));
|
||||
assertTrue(sigs2.get(i) == sigs2.get(i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fieldPoolTest() {
|
||||
final String TEST = "class Bzaz {" +
|
||||
"public int bar;" +
|
||||
"public String k;" +
|
||||
"public double d;" +
|
||||
"}";
|
||||
|
||||
final String TEST2 = "class Foo {" +
|
||||
"private final int i;" +
|
||||
"private final int x;" +
|
||||
"private final String k;" +
|
||||
"}";
|
||||
|
||||
|
||||
List<ASTFieldDeclaration> nodes = getOrderedNodes(ASTFieldDeclaration.class, TEST);
|
||||
List<ASTFieldDeclaration> nodes2 = getOrderedNodes(ASTFieldDeclaration.class, TEST2);
|
||||
|
||||
List<FieldSignature> sigs = new ArrayList<>();
|
||||
List<FieldSignature> sigs2 = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < sigs.size(); i++) {
|
||||
sigs.add(FieldSignature.buildFor(nodes.get(i)));
|
||||
sigs2.add(FieldSignature.buildFor(nodes2.get(i)));
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < sigs.size() - 1; i++) {
|
||||
assertTrue(sigs.get(i) == sigs.get(i + 1));
|
||||
assertTrue(sigs2.get(i) == sigs2.get(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user