Skip to content

Commit

Permalink
Fix method parameters rendering (#54)
Browse files Browse the repository at this point in the history
* Fix method parameters rendering
  The current code causes a stack overflow exception as it tries rendering the original expression instead of each parameter.
* Add test for expression writing
  • Loading branch information
andriy-dmytruk authored Feb 8, 2024
1 parent 9a858ac commit 11b220e
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ private CodeBlock renderExpression(@Nullable ObjectDef objectDef, MethodDef meth
+ "("),
callInstanceMethod.parameters()
.stream()
.map(exp -> renderExpression(objectDef, methodDef, expressionDef))
.map(exp -> renderExpression(objectDef, methodDef, exp))
.collect(CodeBlock.joining(", ")),
CodeBlock.of(")")
);
Expand All @@ -447,7 +447,7 @@ private CodeBlock renderExpression(@Nullable ObjectDef objectDef, MethodDef meth
+ "(", asType(staticMethod.classDef())),
staticMethod.parameters()
.stream()
.map(exp -> renderExpression(objectDef, methodDef, expressionDef))
.map(exp -> renderExpression(objectDef, methodDef, exp))
.collect(CodeBlock.joining(", ")),
CodeBlock.of(")")
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package io.micronaut.sourcegen.javapoet.write;

import io.micronaut.inject.ast.ClassElement;
import io.micronaut.sourcegen.JavaPoetSourceGenerator;
import io.micronaut.sourcegen.model.ClassDef;
import io.micronaut.sourcegen.model.ClassTypeDef;
import io.micronaut.sourcegen.model.ExpressionDef;
import io.micronaut.sourcegen.model.MethodDef;
import io.micronaut.sourcegen.model.StatementDef;
import io.micronaut.sourcegen.model.TypeDef;
import io.micronaut.sourcegen.model.VariableDef;
import org.junit.Test;

import javax.lang.model.element.Modifier;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

public class ExpressionWriteTest {

private static final ClassTypeDef STRING = ClassTypeDef.of(String.class);

@Test
public void returnConstantExpression() throws IOException {
ExpressionDef helloString = ExpressionDef.constant(
ClassElement.of(String.class), STRING, "hello"
);
String result = writeMethodWithExpression(helloString);

assertEquals("\"hello\"", result);
}

@Test
public void returnStaticInvoke() throws IOException {
ExpressionDef two = ExpressionDef.constant(
ClassElement.of(int.class), new TypeDef.Primitive("int"), "2"
);
ExpressionDef valueOfTwo = ExpressionDef.invokeStatic(
STRING, "valueOf", List.of(two), STRING
);
String result = writeMethodWithExpression(valueOfTwo);

assertEquals("String.valueOf(2)", result);
}

@Test
public void returnInvoke() throws IOException {
ExpressionDef helloString = ExpressionDef.constant(
ClassElement.of(String.class), STRING, "hello"
);
ExpressionDef equals = ExpressionDef.invoke(
new VariableDef.This(ClassTypeDef.of("test.Test")),
"equals", List.of(helloString), new TypeDef.Primitive("boolean"));
String result = writeMethodWithExpression(equals);

assertEquals("this.equals(\"hello\")", result);
}

private String writeMethodWithExpression(ExpressionDef expression) throws IOException {
StatementDef.Return returnStatement = new StatementDef.Return(expression);
ClassDef classDef = ClassDef.builder("test.Test")
.addMethod(MethodDef.builder("test")
.returns(expression.type())
.addStatement(returnStatement)
.build()
)
.addModifiers(Modifier.PUBLIC)
.build();

JavaPoetSourceGenerator generator = new JavaPoetSourceGenerator();
String result;
try (StringWriter writer = new StringWriter()) {
generator.write(classDef, writer);
result = writer.toString();
}

final Pattern CLASS_REGEX = Pattern.compile("package test;[\\s\\S]+" +
"public class Test \\{\\s+" +
"([\\s\\S]+)\\s+}\\s+");
Matcher matcher = CLASS_REGEX.matcher(result);
if (!matcher.matches()) {
fail("Expected class to match regex: \n" + CLASS_REGEX + "\nbut is: \n" + result);
}
String classBody = matcher.group(1);

final Pattern METHOD_REGEX = Pattern.compile(
"\\S+ test\\(\\) \\{\\s+return ([^;]+);\\s+}");
Matcher methodMatcher = METHOD_REGEX.matcher(classBody);
if (!methodMatcher.matches()) {
fail("Expected method to match regex: \n" + METHOD_REGEX + "\nbut is: \n" + classBody);
}
return methodMatcher.group(1);
}

}

0 comments on commit 11b220e

Please sign in to comment.