Skip to content

Commit

Permalink
Fix: clone() should not catch exception when super.clone() is not thr…
Browse files Browse the repository at this point in the history
…owing it

Fixes issue #98
  • Loading branch information
mkarneim committed Apr 30, 2017
1 parent 0163279 commit 6d0eb19
Show file tree
Hide file tree
Showing 13 changed files with 317 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import javax.lang.model.util.Types;

import net.karneim.pojobuilder.model.BuildMethodM;
import net.karneim.pojobuilder.model.CloneMethodM;
import net.karneim.pojobuilder.model.CopyMethodM;
import net.karneim.pojobuilder.model.ManualBuilderM;
import net.karneim.pojobuilder.model.PropertyM;
Expand Down Expand Up @@ -238,6 +239,11 @@ private void processBaseClass(Output output) {
if (hasBuildMethod) {
output.getBuilderModel().getBuildMethod().setOverrides(true);
}
boolean cloneShouldCatchException =
!javaModelAnalyzerUtil.hasCloneMethodThatDoesNotThrowACloneNotSupportedException(baseTypeElement);
output.getBuilderModel().setCloneMethod(
new CloneMethodM().setShouldCatchCloneNotSupportedException(cloneShouldCatchException));

output.getBuilderModel().setBaseType(baseType);
output.getInput().getOrginatingElements()
.add(javaModelAnalyzerUtil.getCompilationUnit(baseTypeElement));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
public class JavaModelAnalyzerUtil {

private static final String BUILD_METHOD_NAME = "build";
private static final String CLONE_METHOD_NAME = "clone";
private static final String GET_METHOD_NAME = "get";
private static final String IS = "is";
private static final String GET = "get";
Expand Down Expand Up @@ -252,10 +253,29 @@ public TypeMirror getType(DeclaredType ownerType, Element element) {
public boolean hasBuildMethod(TypeElement typeElement, TypeMirror requiredReturnType) {
return hasMethod(typeElement, BUILD_METHOD_NAME, requiredReturnType, null);
}

/**
* Returns true, if the given type element has a method called "get" with no parameters and
* which has an actual return type that is compatible with the given return type.
* Returns true, if the given type element has a method called "clone" with no parameters and
* which does not throw a {@link CloneNotSupportedException}.
*
* @param typeElement the type element
* @return true, if the method is found
*/
public boolean hasCloneMethodThatDoesNotThrowACloneNotSupportedException(TypeElement typeElement) {
ExecutableElement ex = findMethod(typeElement, CLONE_METHOD_NAME, null, null);
if (ex != null) {
TypeElement execptionType =
elements.getTypeElement(CloneNotSupportedException.class.getName());
List<? extends TypeMirror> thrownTypes = ex.getThrownTypes();
TypeMirror exType = execptionType.asType();
return (!thrownTypes.contains(exType));
}
return false;
}

/**
* Returns true, if the given type element has a method called "get" with no parameters and which
* has an actual return type that is compatible with the given return type.
*
* @param interfaceTypeElement
* @param asType
Expand All @@ -279,6 +299,24 @@ public boolean hasGetMethod(TypeElement typeElement, TypeMirror requiredReturnTy
*/
public boolean hasMethod(TypeElement typeElement, String name, TypeMirror requiredReturnType,
TypeMirror requiredParamType) {
return findMethod(typeElement, name, requiredReturnType, requiredParamType) != null;
}

/**
* Searches the given type element for a method with the given name and an actual return type that
* is compatible with the given return type, and has an actual parameter that is compatible with
* the given parameter type.
*
* @param typeElement the type element
* @param name the required name of the method
* @param requiredReturnType the required return type (maybe {@link NoType}).
* @param requiredParamType the type of the required (first) parameter, or <code>null</code> if no
* parameter is required
* @return the ExecutableElement repesenting the found method, or <code>null</code> if none if
* found
*/
public ExecutableElement findMethod(TypeElement typeElement, String name,
TypeMirror requiredReturnType, TypeMirror requiredParamType) {
List<? extends Element> memberEls = elements.getAllMembers(typeElement);
List<ExecutableElement> methodEls = ElementFilter.methodsIn(memberEls);
for (ExecutableElement methodEl : methodEls) {
Expand Down Expand Up @@ -310,9 +348,9 @@ public boolean hasMethod(TypeElement typeElement, String name, TypeMirror requir
continue;
}
}
return true;
return methodEl;
}
return false;
return null;
}

/**
Expand Down
21 changes: 15 additions & 6 deletions src/main/java/net/karneim/pojobuilder/model/BuilderM.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.karneim.pojobuilder.model;


public class BuilderM {
private TypeM type;
private boolean isAbstract;
Expand All @@ -16,6 +15,7 @@ public class BuilderM {
private boolean hasBuilderProperties;
private TypeM optionalType;
private StaticFactoryMethodM staticFactoryMethod;
private CloneMethodM cloneMethod;

public TypeM getType() {
return type;
Expand Down Expand Up @@ -129,13 +129,22 @@ public void setStaticFactoryMethod(StaticFactoryMethodM staticFactoryMethod) {
this.staticFactoryMethod = staticFactoryMethod;
}

public CloneMethodM getCloneMethod() {
return cloneMethod;
}

public void setCloneMethod(CloneMethodM cloneMethod) {
this.cloneMethod = cloneMethod;
}

@Override
public String toString() {
return "BuilderM [type=" + type + ", isAbstract=" + isAbstract + ", selfType=" + selfType + ", baseType="
+ baseType + ", pojoType=" + pojoType + ", properties=" + properties + ", factoryMethod=" + factoryMethod
+ ", copyMethod=" + copyMethod + ", buildMethod=" + buildMethod + ", validator=" + validator
+ ", interfaceType=" + interfaceType + ", hasBuilderProperties=" + hasBuilderProperties + ", optionalType="
+ optionalType + ", staticFactoryMethod=" + staticFactoryMethod + "]";
return "BuilderM [type=" + type + ", isAbstract=" + isAbstract + ", selfType=" + selfType
+ ", baseType=" + baseType + ", pojoType=" + pojoType + ", properties=" + properties
+ ", factoryMethod=" + factoryMethod + ", copyMethod=" + copyMethod + ", buildMethod="
+ buildMethod + ", validator=" + validator + ", interfaceType=" + interfaceType
+ ", hasBuilderProperties=" + hasBuilderProperties + ", optionalType=" + optionalType
+ ", staticFactoryMethod=" + staticFactoryMethod + ", cloneMethod=" + cloneMethod + "]";
}

}
23 changes: 23 additions & 0 deletions src/main/java/net/karneim/pojobuilder/model/CloneMethodM.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package net.karneim.pojobuilder.model;

public class CloneMethodM {
private boolean shouldCatchCloneNotSupportedException;

public CloneMethodM() {}

public boolean shouldCatchCloneNotSupportedException() {
return shouldCatchCloneNotSupportedException;
}

public CloneMethodM setShouldCatchCloneNotSupportedException(boolean value) {
this.shouldCatchCloneNotSupportedException = value;
return this;
}

@Override
public String toString() {
return "BuildMethodM [shouldCatchCloneNotSupportedException="
+ shouldCatchCloneNotSupportedException + "]";
}

}
Loading

0 comments on commit 6d0eb19

Please sign in to comment.