Skip to content

Commit

Permalink
Issue #15. Almost done. Need more testing and check if package is tak…
Browse files Browse the repository at this point in the history
…en into account
  • Loading branch information
stephanenicolas committed Oct 13, 2013
1 parent 36fa9b1 commit 32fdfef
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.boundbox.sample;

@edu.umd.cs.findbugs.annotations.SuppressWarnings(
value={"URF_UNREAD_FIELD"},
justification="Only used for tests")
public class MultipleInnerClassTestClass {
public class InnerClass {
public int a = 0;
};
public static class StaticInnerClass2 {
public int a = 3;
};
public static class StaticInnerClass {
public int a = 2;
};
public class InnerClass2 {
public int a = 1;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.boundbox.sample;

@SuppressWarnings("unused")
@edu.umd.cs.findbugs.annotations.SuppressWarnings(
value={"URF_UNREAD_FIELD"},
justification="Only used for tests")
public class VisibilityTestClass {
private class Inner {
public class InnerInner{
private C foo = new C();
}
}
private static class C {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.boundbox.sample;

import static org.junit.Assert.*;

import org.boundbox.BoundBox;
import org.junit.Before;
import org.junit.Test;

public class MultipleInnerClassTest {

private MultipleInnerClassTestClass multipleInnerClassTestClassInstance;
@BoundBox(boundClass = MultipleInnerClassTestClass.class)
private BoundBoxOfMultipleInnerClassTestClass boundBoxOfA;

@Before
public void setup() {
multipleInnerClassTestClassInstance = new MultipleInnerClassTestClass();
boundBoxOfA = new BoundBoxOfMultipleInnerClassTestClass(multipleInnerClassTestClassInstance);
}

@Test
public void test_read_access_to_field() {
//given
Object innerInstance = boundBoxOfA.boundBox_new_InnerClass();
Object innerInstance2 = boundBoxOfA.boundBox_new_InnerClass2();
Object staticInnerInstance = BoundBoxOfMultipleInnerClassTestClass.boundBox_new_StaticInnerClass();
Object staticInnerInstance2 = BoundBoxOfMultipleInnerClassTestClass.boundBox_new_StaticInnerClass2();

//when
BoundBoxOfMultipleInnerClassTestClass.BoundBoxOfInnerClass boundBoxOfInner = boundBoxOfA.new BoundBoxOfInnerClass(innerInstance);
BoundBoxOfMultipleInnerClassTestClass.BoundBoxOfInnerClass2 boundBoxOfInner2 = boundBoxOfA.new BoundBoxOfInnerClass2(innerInstance2);
BoundBoxOfMultipleInnerClassTestClass.BoundBoxOfStaticInnerClass boundBoxOfStaticInner = new BoundBoxOfMultipleInnerClassTestClass.BoundBoxOfStaticInnerClass(staticInnerInstance);
BoundBoxOfMultipleInnerClassTestClass.BoundBoxOfStaticInnerClass2 boundBoxOfStaticInner2 = new BoundBoxOfMultipleInnerClassTestClass.BoundBoxOfStaticInnerClass2(staticInnerInstance2);

//then
assertEquals("org.boundbox.sample.MultipleInnerClassTestClass$InnerClass", innerInstance.getClass().getName());
assertEquals("org.boundbox.sample.MultipleInnerClassTestClass$InnerClass2", innerInstance2.getClass().getName());
assertEquals("org.boundbox.sample.MultipleInnerClassTestClass$StaticInnerClass", staticInnerInstance.getClass().getName());
assertEquals("org.boundbox.sample.MultipleInnerClassTestClass$StaticInnerClass2", staticInnerInstance2.getClass().getName());

assertEquals(0,boundBoxOfInner.boundBox_getA());
assertEquals(1,boundBoxOfInner2.boundBox_getA());
assertEquals(2,boundBoxOfStaticInner.boundBox_getA());
assertEquals(3,boundBoxOfStaticInner2.boundBox_getA());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.boundbox.sample;

import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotSame;

import org.boundbox.BoundBox;
import org.junit.Before;
import org.junit.Test;

public class VisibilityTest {

private VisibilityTestClass visibilityTestClassA;
@BoundBox(boundClass = VisibilityTestClass.class)
private BoundBoxOfVisibilityTestClass boundBoxOfA;

@Before
public void setup() {
visibilityTestClassA = new VisibilityTestClass();
boundBoxOfA = new BoundBoxOfVisibilityTestClass(visibilityTestClassA);
}

@Test
public void test_read_access_to_field() {
System.out.println("Inner classes of VisibilityTestClass");
for(Class<?> c : VisibilityTestClass.class.getDeclaredClasses()) {
System.out.println(c.getName());
}
//given
Object innerInstance = boundBoxOfA.boundBox_new_Inner();
Object cInstance = BoundBoxOfVisibilityTestClass.boundBox_new_C();

//when
BoundBoxOfVisibilityTestClass.BoundBoxOfInner boundBoxOfInner = boundBoxOfA.new BoundBoxOfInner(innerInstance);
Object innerInnerInstance = boundBoxOfInner.boundBox_new_InnerInner();
BoundBoxOfVisibilityTestClass.BoundBoxOfInner.BoundBoxOfInnerInner boundBoxOfInnerInner = boundBoxOfInner.new BoundBoxOfInnerInner(innerInnerInstance);

//then
assertNotEquals(innerInstance, cInstance);
assertNotEquals(innerInstance.getClass(), cInstance.getClass());
assertNotSame(null, boundBoxOfInnerInner.boundBox_getFoo());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class ClassInfo {

@NonNull
@Getter
private String className;
protected String className;
@Setter
@Getter
private List<FieldInfo> listFieldInfos = new ArrayList<FieldInfo>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.boundbox.model;

import org.apache.commons.lang3.builder.CompareToBuilder;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -8,18 +10,14 @@

//CHECKSTYLE:OFF HideUtilityClassConstructorCheck
@SuppressWarnings("PMD.UnusedPrivateField")
@EqualsAndHashCode(callSuper=true,exclude={"effectiveInheritanceLevel","innerClassIndex"})
@ToString
public class InnerClassInfo extends ClassInfo implements Inheritable {
@EqualsAndHashCode(callSuper=true,exclude={"effectiveInheritanceLevel"})
@ToString(callSuper=true)
public class InnerClassInfo extends ClassInfo implements Inheritable, Comparable<InnerClassInfo> {

@Setter
@Getter
private ClassInfo superClassInfo;

@Setter
@Getter
private int innerClassIndex;

@Getter
private int inheritanceLevel;

Expand All @@ -39,6 +37,14 @@ public void setInheritanceLevel(int inheritanceLevel) {
this.inheritanceLevel = inheritanceLevel;
this.effectiveInheritanceLevel = inheritanceLevel;
}

@Override
public int compareTo(InnerClassInfo other) {
return new CompareToBuilder()
.append(isStaticInnerClass(), other.isStaticInnerClass())
.append(className, other.className)
.toComparison();
}

}
//CHECKSTYLE:ON
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public boolean process(final Set<? extends TypeElement> annotations, final Round
Set<? extends Element> classElements = roundEnvironment.getElementsAnnotatedWith(BoundBox.class);
// For each class that has the annotation
for (final Element classElement : classElements) {

// Get the annotation information
TypeElement boundClass = null;
String maxSuperClass = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public Void visitTypeAsClass(TypeElement e, ScanningContext scanningContext) {
}

visitiedTypes.add(e.toString());
if( !computeVisibility(e)) {
if (!computeVisibility(e)) {
listOfInvisibleTypes.add(e.getQualifiedName().toString());
}

Expand All @@ -94,7 +94,6 @@ public Void visitTypeAsClass(TypeElement e, ScanningContext scanningContext) {
ClassInfo classInfo = scanningContext.getCurrentClassInfo();
int inheritanceLevel = scanningContext.getInheritanceLevel();
InnerClassInfo innerClassInfo = new InnerClassInfo(e.getSimpleName().toString());
innerClassInfo.setInnerClassIndex(classInfo.getListInnerClassInfo().size());
innerClassInfo.setStaticInnerClass(e.getModifiers().contains(Modifier.STATIC));
innerClassInfo.getListSuperClassNames().add(e.toString());
innerClassInfo.setInheritanceLevel(inheritanceLevel);
Expand Down Expand Up @@ -154,37 +153,38 @@ public Void visitTypeAsClass(TypeElement e, ScanningContext scanningContext) {
return super.visitTypeAsClass(e, scanningContext);
}


@Override
public Void visitExecutable(ExecutableElement e, ScanningContext scanningContext) {
log.info("executable ->" + e.getSimpleName());
MethodInfo methodInfo = new MethodInfo(e);
//visibility of types in signature
//TODO should go inside a computer
if( ! computeVisibility(e.getReturnType()) ) {

// visibility of types in signature
// TODO should go inside a computer
if (!computeVisibility(e.getReturnType())) {
TypeElement visibleType = findSuperType(e.getReturnType());
methodInfo.setReturnTypeName(visibleType.getQualifiedName().toString());
}
for( int indexParam =0; indexParam<e.getParameters().size();indexParam++ ) {

for (int indexParam = 0; indexParam < e.getParameters().size(); indexParam++) {
VariableElement param = e.getParameters().get(indexParam);
if( !computeVisibility(param.asType())) {
if (!computeVisibility(param.asType())) {
TypeElement visibleType = findSuperType(param.asType());
FieldInfo fieldInfo = methodInfo.getParameterTypes().get(indexParam);
fieldInfo.setFieldTypeName(visibleType.getQualifiedName().toString());
}
}
for( int indexThrownTypes =0; indexThrownTypes<e.getThrownTypes().size();indexThrownTypes++ ) {

for (int indexThrownTypes = 0; indexThrownTypes < e.getThrownTypes().size(); indexThrownTypes++) {
TypeMirror typeMirrorOfException = e.getThrownTypes().get(indexThrownTypes);
if( !computeVisibility(typeMirrorOfException)) {
if (!computeVisibility(typeMirrorOfException)) {
TypeElement visibleType = findSuperType(typeMirrorOfException);
String visibleTypeName = visibleType.getQualifiedName().toString();
methodInfo.getThrownTypeNames().set(indexThrownTypes, visibleTypeName);
}
}
//other properties

// other properties
if (methodInfo.isConstructor()) {
if (scanningContext.getInheritanceLevel() == 0) {
scanningContext.getCurrentClassInfo().getListConstructorInfos().add(methodInfo);
Expand All @@ -209,10 +209,10 @@ public Void visitExecutable(ExecutableElement e, ScanningContext scanningContext
@Override
public Void visitVariableAsField(VariableElement e, ScanningContext scanningContext) {
FieldInfo fieldInfo = new FieldInfo(e);
//TODO should go inside a computer

// TODO should go inside a computer
TypeMirror typeOfField = e.asType();
if( ! computeVisibility(typeOfField) ) {
if (!computeVisibility(typeOfField)) {
TypeElement visibleType = findSuperType(typeOfField);
fieldInfo.setFieldTypeName(visibleType.getQualifiedName().toString());
}
Expand Down Expand Up @@ -241,26 +241,26 @@ private void addTypeToImport(ClassInfo classInfo, TypeMirror typeMirror) {
addTypeToImport(classInfo, ((DeclaredType) typeMirror));
}
}
//TODO should go inside a computer

// TODO should go inside a computer
private TypeElement findSuperType(TypeMirror typeMirror) {
if( typeMirror.getKind() == TypeKind.DECLARED ) {
if (typeMirror.getKind() == TypeKind.DECLARED) {
DeclaredType declaredTypeOfField = (DeclaredType) typeMirror;
TypeElement typeElementOfTypeOfField = (TypeElement) declaredTypeOfField.asElement();
return findSuperType(typeElementOfTypeOfField);
} else {
throw new RuntimeException("Type mirror " + typeMirror + " is not a class.");
}
}
//TODO should go inside a computer

// TODO should go inside a computer
private TypeElement findSuperType(TypeElement e) {
TypeElement typeElement = e;
while( !computeVisibility(typeElement)) {
if( typeElement.asType().getKind() == TypeKind.DECLARED ) {
while (!computeVisibility(typeElement)) {
if (typeElement.asType().getKind() == TypeKind.DECLARED) {
TypeMirror typeMirrorOfSuperClass = typeElement.getSuperclass();
if(typeMirrorOfSuperClass.getKind() == TypeKind.DECLARED ) {
typeElement = (TypeElement) ((DeclaredType)typeMirrorOfSuperClass).asElement();
if (typeMirrorOfSuperClass.getKind() == TypeKind.DECLARED) {
typeElement = (TypeElement) ((DeclaredType) typeMirrorOfSuperClass).asElement();
} else {
throw new RuntimeException();
}
Expand All @@ -270,30 +270,30 @@ private TypeElement findSuperType(TypeElement e) {
}
return typeElement;
}
//TODO should go inside a computer

// TODO should go inside a computer
private boolean computeVisibility(TypeMirror typeMirror) {
if( typeMirror.getKind() == TypeKind.DECLARED ) {
if (typeMirror.getKind() == TypeKind.DECLARED) {
DeclaredType declaredTypeOfField = (DeclaredType) typeMirror;
TypeElement typeElementOfTypeOfField = (TypeElement) declaredTypeOfField.asElement();
return computeVisibility(typeElementOfTypeOfField);
} else {
return true;
}
}
//TODO should go inside a computer

// TODO should go inside a computer
private boolean computeVisibility(TypeElement e) {

//for nested classes, all outer classes must be visible too
// for nested classes, all outer classes must be visible too
TypeMirror outerType = e.asType();
TypeElement outerTypeElement = e;
while (outerTypeElement.getNestingKind().isNested()) {
if(outerTypeElement.getEnclosingElement().getKind() == ElementKind.CLASS || outerTypeElement.getEnclosingElement().getKind() == ElementKind.INTERFACE) {
outerType = outerTypeElement.getEnclosingElement().asType();
if( outerType.getKind() == TypeKind.DECLARED ) {
outerTypeElement = (TypeElement) ((DeclaredType)outerType).asElement();
if( !computeVisibility(outerTypeElement)) {
if (outerTypeElement.getEnclosingElement().getKind() == ElementKind.CLASS || outerTypeElement.getEnclosingElement().getKind() == ElementKind.INTERFACE) {
outerType = outerTypeElement.getEnclosingElement().asType();
if (outerType.getKind() == TypeKind.DECLARED) {
outerTypeElement = (TypeElement) ((DeclaredType) outerType).asElement();
if (!computeVisibility(outerTypeElement)) {
return false;
}
} else {
Expand All @@ -303,7 +303,7 @@ private boolean computeVisibility(TypeElement e) {
return false;
}
}

boolean isPublic = e.getModifiers().contains(Modifier.PUBLIC);
if (isPublic) {
return true;
Expand All @@ -325,5 +325,6 @@ private boolean isInBoundBoxPackage(String elementFQN) {
}
return packageOfElement.equals(boundBoxPackageName);
}


}
Loading

0 comments on commit 32fdfef

Please # to comment.