private boolean inherited = false;
private boolean empty = false;
private boolean bodyLoaded = true;
- private boolean accessor = false;
+ private AsmField accessedField = null;
private String signature;
private AsmMethod implementationLinkage = null;
}
public boolean isAccessor() {
- return accessor;
+ return accessedField != null;
+ }
+
+ public AsmField getAccessedField() {
+ return accessedField;
}
- public void setAccessor(boolean accessor) {
- this.accessor = accessor;
+ public void setAccessedField(AsmField accessedField) {
+ this.accessedField = accessedField;
}
@Override
package org.sonar.java.bytecode.visitor;
import org.sonar.java.bytecode.asm.AsmClass;
+import org.sonar.java.bytecode.asm.AsmField;
import org.sonar.java.bytecode.asm.AsmMethod;
public class AccessorVisitor extends BytecodeVisitor {
public void visitMethod(AsmMethod asmMethod) {
String propertyName = extractPropertyNameFromMethodName(asmMethod);
- if (propertyName != null && asmClass.getField(propertyName) != null) {
- asmMethod.setAccessor(true);
+ AsmField accessedField = asmClass.getField(propertyName);
+ if (propertyName != null && accessedField != null) {
+ asmMethod.setAccessedField(accessedField);
}
}
public void visitMethod(AsmMethod asmMethod) {
if (isMethodElligibleForLCOM4Computation(asmMethod)) {
- Set<AsmResource> block = getResourceBlockOrCreateIt(asmMethod);
+ ensureBlockIsCreated(asmMethod);
for (AsmEdge edge : asmMethod.getOutgoingEdges()) {
if (isCallToInternalFieldOrMethod(edge) && isNotCallToExcludedFieldFromLcom4Calculation(edge.getTo())) {
AsmResource toResource = edge.getTo();
- mergeAsmResourceToBlock(block, toResource);
+ linkAsmResources(asmMethod, toResource);
}
}
+ } else if (asmMethod.isAccessor()) {
+ linkAsmResources(asmMethod, asmMethod.getAccessedField());
}
}
getSourceFile(asmClass).addData(Metric.LCOM4_BLOCKS, unrelatedBlocks);
}
}
-
- private void mergeAsmResourceToBlock(Set<AsmResource> block, AsmResource toResource) {
- if (block.contains(toResource)) {
+
+ private void ensureBlockIsCreated(AsmResource resource) {
+ getOrCreateResourceBlock(resource);
+ }
+
+ private void linkAsmResources(AsmResource resourceA, AsmResource resourceB) {
+ Set<AsmResource> blockA = getOrCreateResourceBlock(resourceA);
+ Set<AsmResource> blockB = getOrCreateResourceBlock(resourceB);
+
+ if (blockA == blockB) {
return;
}
- Set<AsmResource> otherBlock = getResourceBlock(toResource);
- if (otherBlock == null) {
- block.add(toResource);
-
- } else {
- block.addAll(otherBlock);
- unrelatedBlocks.remove(otherBlock);
- }
+
+ blockA.addAll(blockB);
+ unrelatedBlocks.remove(blockB);
}
private boolean isCallToInternalFieldOrMethod(AsmEdge edge) {
&& (edge.getUsage() == SourceCodeEdgeUsage.CALLS_FIELD || edge.getUsage() == SourceCodeEdgeUsage.CALLS_METHOD);
}
- private Set<AsmResource> getResourceBlockOrCreateIt(AsmResource fromResource) {
- Set<AsmResource> block = getResourceBlock(fromResource);
- if (block != null) {
- return block;
- }
- block = new HashSet<AsmResource>();
- block.add(fromResource);
- unrelatedBlocks.add(block);
- return block;
- }
-
- private Set<AsmResource> getResourceBlock(AsmResource fromResource) {
+ private Set<AsmResource> getOrCreateResourceBlock(AsmResource fromResource) {
for (Set<AsmResource> block : unrelatedBlocks) {
if (block.contains(fromResource)) {
return block;
}
}
- return null;
+
+ Set<AsmResource> block = new HashSet<AsmResource>();
+ block.add(fromResource);
+ unrelatedBlocks.add(block);
+ return block;
}
}
import org.sonar.java.bytecode.asm.AsmClassProviderImpl;
import org.sonar.java.bytecode.asm.AsmMethod;
+import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class AccessorVisitorTest {
}
@Test
- public void testAccessorMethods() {
+ public void testIsAccessor() {
assertTrue(javaBean.getMethod("getName()Ljava/lang/String;").isAccessor());
assertTrue(javaBean.getMethod("setName(Ljava/lang/String;)V").isAccessor());
assertTrue(javaBean.getMethod("setFrench(Z)V").isAccessor());
assertTrue(javaBean.getMethod("isFrench()Z").isAccessor());
assertFalse(javaBean.getMethod("anotherMethod()V").isAccessor());
}
+
+ @Test
+ public void testAccessedField() {
+ assertThat(javaBean.getMethod("getName()Ljava/lang/String;").getAccessedField().getName(), is("name"));
+ assertThat(javaBean.getMethod("setName(Ljava/lang/String;)V").getAccessedField().getName(), is("name"));
+ assertThat(javaBean.getMethod("setFrench(Z)V").getAccessedField().getName(), is("french"));
+ assertThat(javaBean.getMethod("isFrench()Z").getAccessedField().getName(), is("french"));
+ assertNull(javaBean.getMethod("anotherMethod()V").getAccessedField());
+ }
+
}