Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve build method API + small improvements #151

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,12 @@ public void returnPrimitiveInitialization() throws IOException {

assertEquals("0", result);
}

@Test
public void returnPrimitiveInitialization2() throws IOException {
ExpressionDef intExpression = TypeDef.Primitive.INT.initialize(0);
String result = writeMethodWithExpression(intExpression);

assertEquals("0", result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,13 @@ private static void createSingularPropertyMethods(ClassDef.ClassDefBuilder class
.addModifiers(Modifier.PUBLIC)
.addParameter(propertyName, TypeDef.parameterized(Collection.class, singularTypeDef))
.build((self, parameterDefs) -> StatementDef.multi(
parameterDefs.get(0).asExpression().isNull().asConditionIf(
parameterDefs.get(0).isNull().asConditionIf(
ClassTypeDef.of(NullPointerException.class).doThrow(ExpressionDef.constant(propertyName + " cannot be null"))
),
self.field(field).isNull().asConditionIf(
self.field(field).assign(ClassTypeDef.of(ArrayList.class).instantiate())
),
self.field(field).invoke("addAll", TypeDef.primitive(boolean.class), parameterDefs.get(0).asExpression()),
self.field(field).invoke("addAll", TypeDef.primitive(boolean.class), parameterDefs.get(0)),
returningExpressionProvider.apply(self)
)));
classBuilder.addMethod(MethodDef.builder(singularName)
Expand All @@ -317,7 +317,7 @@ private static void createSingularPropertyMethods(ClassDef.ClassDefBuilder class
self.field(field).isNull().asConditionIf(
self.field(field).assign(ClassTypeDef.of(ArrayList.class).instantiate())
),
self.field(field).invoke("add", TypeDef.of(boolean.class), parameterDefs.get(0).asExpression()),
self.field(field).invoke("add", TypeDef.of(boolean.class), parameterDefs.get(0)),
returningExpressionProvider.apply(self)
)));
classBuilder.addMethod(MethodDef.builder("clear" + StringUtils.capitalize(propertyName))
Expand All @@ -343,7 +343,7 @@ private static void createSingularPropertyMethods(ClassDef.ClassDefBuilder class
.addModifiers(Modifier.PUBLIC)
.addParameter(propertyName, TypeDef.parameterized(Map.class, keyType, valueType))
.build((self, parameterDefs) -> StatementDef.multi(
parameterDefs.get(0).asExpression().isNull().asConditionIf(
parameterDefs.get(0).isNull().asConditionIf(
ClassTypeDef.of(NullPointerException.class).doThrow(ExpressionDef.constant(propertyName + " cannot be null"))
),
self.field(field).isNull().asConditionIf(
Expand All @@ -352,7 +352,7 @@ private static void createSingularPropertyMethods(ClassDef.ClassDefBuilder class
self.field(field).invoke(
"addAll",
TypeDef.primitive(boolean.class),
parameterDefs.get(0).asExpression().invoke("entrySet", ClassTypeDef.of(Set.class))
parameterDefs.get(0).invoke("entrySet", ClassTypeDef.of(Set.class))
),
returningExpressionProvider.apply(self)
)));
Expand All @@ -370,8 +370,8 @@ private static void createSingularPropertyMethods(ClassDef.ClassDefBuilder class
ClassTypeDef.of(Map.class).invokeStatic(
"entry",
ClassTypeDef.of(Map.Entry.class),
parameterDefs.get(0).asExpression(),
parameterDefs.get(1).asExpression()
parameterDefs.get(0),
parameterDefs.get(1)
)
),
returningExpressionProvider.apply(self)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,7 @@ private static void createToStringMethod(ClassDef.ClassDefBuilder classDefBuilde
if (readMethod.isEmpty()) {
continue;
}
ExpressionDef propertyValue = parameterDef.get(0).asVariable()
.invoke(readMethod.get(), List.of());
ExpressionDef propertyValue = parameterDef.get(0).invoke(readMethod.get());

exp = exp.invoke("append", variableDef.type(),
ExpressionDef.constant(beanProperty.getName() + "="))
Expand Down Expand Up @@ -186,8 +185,8 @@ private static void createEqualsMethod(ClassDef.ClassDefBuilder classDefBuilder,
.addParameter("instance", selfType)
.addParameter("o", TypeDef.OBJECT)
.build((self, parameterDef) -> {
VariableDef instance = parameterDef.get(0).asVariable();
VariableDef o = parameterDef.get(1).asVariable();
VariableDef instance = parameterDef.get(0);
VariableDef o = parameterDef.get(1);

return StatementDef.multi(
instance.asCondition(" == ", o)
Expand All @@ -199,24 +198,23 @@ private static void createEqualsMethod(ClassDef.ClassDefBuilder classDefBuilder,
o.cast(selfType).newLocal("other", variableDef -> {
ExpressionDef exp = null;
for (PropertyElement beanProperty : properties) {
TypeDef propertyTypeDef = TypeDef.of(beanProperty.getType());
if (beanProperty.hasAnnotation(EqualsAndHashCode.Exclude.class)) {
continue;
}
Optional<MethodElement> readMethod = beanProperty.getReadMethod();
if (readMethod.isEmpty()) {
continue;
}
var firstProperty = instance.invoke(readMethod.get(), List.of());
var secondProperty = variableDef.invoke(readMethod.get(), List.of());
var firstProperty = instance.invoke(readMethod.get());
var secondProperty = variableDef.invoke(readMethod.get());

ExpressionDef newEqualsExpression = firstProperty.asCondition(" == ", secondProperty);
if (!propertyTypeDef.isPrimitive()) {
if (!beanProperty.isPrimitive() || beanProperty.isArray()) {
// Object.equals for objects
ExpressionDef equalsMethod = firstProperty.invoke("equals", TypeDef.Primitive.BOOLEAN, secondProperty);
if (propertyTypeDef.isArray()) {
if (beanProperty.isArray()) {
// Arrays.equals or Arrays.deepEquals for Array
String methodName = (((TypeDef.Array) propertyTypeDef).dimensions() > 1) ? "deepEquals" : "equals";
String methodName = beanProperty.getArrayDimensions() > 1 ? "deepEquals" : "equals";
equalsMethod = ClassTypeDef.of(Arrays.class).invokeStatic(methodName, TypeDef.Primitive.BOOLEAN, firstProperty, secondProperty);
}
newEqualsExpression = newEqualsExpression
Expand Down Expand Up @@ -246,13 +244,13 @@ private static void createHashCodeMethod(ClassDef.ClassDefBuilder classDefBuilde
.addParameter("instance", selfType)
.returns(TypeDef.Primitive.INT)
.build((self, parameterDef) -> StatementDef.multi(
parameterDef.get(0).asExpression().isNull().asConditionIf(ExpressionDef.constant(0).returning()),
TypeDef.Primitive.INT.initialize(ExpressionDef.constant(1)).newLocal("hashValue", hashValue -> {
parameterDef.get(0).isNull().asConditionIf(ExpressionDef.constant(0).returning()),
TypeDef.Primitive.INT.initialize(1).newLocal("hashValue", hashValue -> {
List<StatementDef> hashUpdates = new ArrayList<>();
properties.stream().filter(beanProperty -> !beanProperty.hasAnnotation(EqualsAndHashCode.Exclude.class) && beanProperty.getReadMethod().isPresent())
.forEach(property -> {
ExpressionDef propertyGetter = parameterDef.get(0).asVariable()
.invoke(property.getReadMethod().get(), List.of());
ExpressionDef propertyGetter = parameterDef.get(0)
.invoke(property.getReadMethod().get());
hashUpdates.add(hashValue.assign(
hashValue.asCondition(" * ", ExpressionDef.constant(HASH_MULTIPLIER)
.asCondition(" + ", getPropertyHashValue(TypeDef.of(property.getType()), propertyGetter)))));
Expand All @@ -265,7 +263,7 @@ private static void createHashCodeMethod(ClassDef.ClassDefBuilder classDefBuilde
classDefBuilder.addMethod(method);
}

/** Calculate property hash value according to its type
/** Calculate property hash value according to its type.
*
* @param propertyTypeDef TypeDef of the property
* @param propertyGetter the expression that gets the value of the property
Expand Down Expand Up @@ -301,7 +299,7 @@ private static ExpressionDef getPropertyHashValue(TypeDef propertyTypeDef, Expre
} else { // OBJECT
propertyHashCalculation = propertyGetter.isNull().asConditionIfElse(
ExpressionDef.constant(NULL_HASH_VALUE),
propertyGetter.invoke("hashCode", TypeDef.Primitive.INT, List.of())
propertyGetter.invoke("hashCode", TypeDef.Primitive.INT)
);
}
return propertyHashCalculation.cast(TypeDef.Primitive.INT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ private MethodDef createWithConsumerMethod(ClassTypeDef recordType, ClassTypeDef
.addParameter("consumer", consumableType)
.returns(recordType).build((self, parameterDefs) ->
self.invoke(withMethod).newLocal("builder", builderVar ->
parameterDefs.get(0).asExpression().invoke("accept", TypeDef.VOID, builderVar)
parameterDefs.get(0).invoke("accept", TypeDef.VOID, builderVar)
.after(
builderVar.invoke("build", recordType).returning()
))
Expand Down Expand Up @@ -187,7 +187,7 @@ private MethodDef withMethod(ClassElement recordElement, PropertyElement beanPro
for (ParameterElement parameter : recordElement.getPrimaryConstructor().orElseThrow().getParameters()) {
ExpressionDef exp;
if (parameter.getName().equals(beanProperty.getName())) {
exp = parameterDefs.get(0).asExpression();
exp = parameterDefs.get(0);
} else {
exp = self.invoke(propertyAccessMethods.get(parameter.getName()));
}
Expand All @@ -198,7 +198,7 @@ private MethodDef withMethod(ClassElement recordElement, PropertyElement beanPro
ClassTypeDef.of(Objects.class).invokeStatic(
"requireNonNull",
ClassTypeDef.OBJECT,
parameterDefs.get(0).asExpression()
parameterDefs.get(0)
),
recordType.instantiate(values).returning()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,11 @@ public MethodDef build() {
return build((self, parameterDefs) -> null);
}

public MethodDef build(BiFunction<VariableDef.This, List<ParameterDef>, StatementDef> bodyBuilder) {
StatementDef statement = bodyBuilder.apply(new VariableDef.This(TypeDef.THIS), parameters);
public MethodDef build(BiFunction<VariableDef.This, List<VariableDef.MethodParameter>, StatementDef> bodyBuilder) {
List<VariableDef.MethodParameter> variables = parameters.stream()
.map(ParameterDef::asVariable)
.toList();
StatementDef statement = bodyBuilder.apply(new VariableDef.This(TypeDef.THIS), variables);
andriy-dmytruk marked this conversation as resolved.
Show resolved Hide resolved
if (statement != null) {
addStatement(statement);
if (returnType == null && !statements.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public VariableDef asExpression() {
* @return Return the parameter as a variable
* @since 1.2
*/
public VariableDef asVariable() {
public VariableDef.MethodParameter asVariable() {
return new VariableDef.MethodParameter(name, type);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ default ExpressionDef instantiateArray(ExpressionDef... expressions) {
* @param name The primitive type name
* @return a new type definition
*/
static TypeDef primitive(String name) {
static Primitive primitive(String name) {
return new Primitive(name);
}

Expand All @@ -97,7 +97,7 @@ static TypeDef primitive(String name) {
* @param type The primitive type
* @return a new type definition
*/
static TypeDef primitive(Class<?> type) {
static Primitive primitive(Class<?> type) {
if (!type.isPrimitive()) {
throw new IllegalStateException("Expected a primitive type got: " + type);
}
Expand Down Expand Up @@ -280,14 +280,14 @@ default TypeDef makeNullable() {
@Experimental
record Primitive(String name) implements TypeDef {

public static final TypeDef.Primitive INT = (Primitive) of(int.class);
public static final TypeDef.Primitive BOOLEAN = (Primitive) of(boolean.class);
public static final TypeDef.Primitive LONG = (Primitive) of(long.class);
public static final TypeDef.Primitive CHAR = (Primitive) of(char.class);
public static final TypeDef.Primitive BYTE = (Primitive) of(byte.class);
public static final TypeDef.Primitive SHORT = (Primitive) of(short.class);
public static final TypeDef.Primitive DOUBLE = (Primitive) of(double.class);
public static final TypeDef.Primitive FLOAT = (Primitive) of(float.class);
public static final TypeDef.Primitive INT = primitive(int.class);
public static final TypeDef.Primitive BOOLEAN = primitive(boolean.class);
public static final TypeDef.Primitive LONG = primitive(long.class);
public static final TypeDef.Primitive CHAR = primitive(char.class);
public static final TypeDef.Primitive BYTE = primitive(byte.class);
public static final TypeDef.Primitive SHORT = primitive(short.class);
public static final TypeDef.Primitive DOUBLE = primitive(double.class);
public static final TypeDef.Primitive FLOAT = primitive(float.class);

@Override
public boolean isPrimitive() {
Expand All @@ -312,27 +312,27 @@ public ClassTypeDef wrapperType() {
}

/**
* Instantiate this class.
* The new instance expression for primitives.
*
* @param value The expression giving the initial value
* @return The instantiate expression
* @param value The initial value
* @return The new instance
* @since 1.3
*/
public ExpressionDef initialize(ExpressionDef value) {
return initialize(this, value);
@Experimental
public PrimitiveInstance initialize(ExpressionDef value) {
return new PrimitiveInstance(this, value);
}


/**
* The new instance expression for primitives.
*
* @param type The type
* @param value The initial value
* @param constant The constant
* @return The new instance
* @since 1.3
*/
@Experimental
public static PrimitiveInstance initialize(TypeDef type,
ExpressionDef value) {
return new PrimitiveInstance(type, value);
public PrimitiveInstance initialize(Object constant) {
return new PrimitiveInstance(this, new ExpressionDef.Constant(this, constant));
}

/**
Expand All @@ -344,8 +344,8 @@ public static PrimitiveInstance initialize(TypeDef type,
* @since 1.3
*/
@Experimental
public record PrimitiveInstance(TypeDef type,
ExpressionDef value) implements ExpressionDef {
public record PrimitiveInstance(TypeDef.Primitive type,
ExpressionDef value) implements ExpressionDef {
}
}

Expand Down
Loading
Loading