Skip to content

Commit

Permalink
Merge pull request #33110 from matejvasek/funq-dispatch
Browse files Browse the repository at this point in the history
Enable function with same name for Funqy
  • Loading branch information
patriot1burke authored May 18, 2023
2 parents c9041ea + da92ba4 commit a285824
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.quarkus.funqy.test;

import io.quarkus.funqy.Funq;

public class NameConflict {

@Funq
public String function(String s) {
return s.toUpperCase();
}

@Funq
public int function(int i) {
return i * 2;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.funqy.test;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.*;
import java.util.logging.Level;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class NameConflictTest {
@RegisterExtension
static QuarkusUnitTest test = new QuarkusUnitTest()
.withApplicationRoot(jar -> jar.addClass(NameConflict.class))
.setLogRecordPredicate(logRecord -> logRecord.getLevel().intValue() >= Level.WARNING.intValue() &&
logRecord.getLoggerName().startsWith("io.quarkus.funqy"))
.assertLogRecords(logRecords -> {
boolean match = logRecords
.stream()
.anyMatch(logRecord -> logRecord.getMessage().contains("Name conflict"));
if (!match) {
fail("Log does not contain message about name conflict.");
}
});

@Test
void test() {
assertTrue(true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.quarkus.funqy.test;

import io.quarkus.funqy.Funq;

public class Overloading {

@Funq("intfun")
public int function(int i) {
return i * 2;
}

@Funq("strfun")
public String function(String s) {
return s.toUpperCase();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkus.funqy.test;

import static org.hamcrest.Matchers.equalTo;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class OverloadingTest {
@RegisterExtension
static QuarkusUnitTest test = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClasses(Overloading.class));

@Test
public void testMapping() {
RestAssured.given().contentType("application/json")
.body("\"a\"")
.post("/strfun")
.then().statusCode(200)
.body(equalTo("\"A\""));

RestAssured.given().contentType("application/json")
.body("10")
.post("/intfun")
.then().statusCode(200)
.body(equalTo("20"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
public final class FunctionBuildItem extends MultiBuildItem {
protected String className;
protected String methodName;
protected String descriptor;
protected String functionName;

public FunctionBuildItem(String className, String methodName, String functionName) {
public FunctionBuildItem(String className, String methodName, String descriptor, String functionName) {
this.className = className;
this.methodName = methodName;
this.descriptor = descriptor;
this.functionName = functionName;
}

Expand All @@ -21,6 +23,10 @@ public String getMethodName() {
return methodName;
}

public String getDescriptor() {
return descriptor;
}

public String getFunctionName() {
return functionName;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void scanFunctions(BeanArchiveIndexBuildItem beanArchiveIndexBuildItem,
}
if (functionName != null && functionName.isEmpty())
functionName = null;
functions.produce(new FunctionBuildItem(className, methodName, functionName));
functions.produce(new FunctionBuildItem(className, methodName, method.descriptor(), functionName));

String source = FunctionScannerBuildStep.class.getSimpleName() + " > " + method.declaringClass() + "[" + method
+ "]";
Expand Down Expand Up @@ -167,10 +167,11 @@ public FunctionInitializedBuildItem staticInit(FunctionRecorder recorder, List<F
recorder.init();
for (FunctionBuildItem function : functions) {
if (function.getFunctionName() == null) {
recorder.register(context.classProxy(function.getClassName()), function.getMethodName());
recorder.register(context.classProxy(function.getClassName()), function.getMethodName(),
function.getDescriptor());
} else {
recorder.register(context.classProxy(function.getClassName()), function.getMethodName(),
function.getFunctionName());
function.getDescriptor(), function.getFunctionName());
}
}
return FunctionInitializedBuildItem.SINGLETON;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ public void init() {
registry = new FunctionRegistry();
}

public void register(Class functionClass, String methodName) {
registry.register(functionClass, methodName, methodName);
public void register(Class functionClass, String methodName, String descriptor) {
registry.register(functionClass, methodName, descriptor, methodName);
}

public void register(Class functionClass, String methodName, String functionName) {
registry.register(functionClass, methodName, functionName);
public void register(Class functionClass, String methodName, String descriptor, String functionName) {
registry.register(functionClass, methodName, descriptor, functionName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,34 @@
import java.util.HashMap;
import java.util.Map;

import org.jboss.logging.Logger;

public class FunctionRegistry {
protected Map<String, FunctionInvoker> functions = new HashMap<>();

public void register(Class clz, String methodName, String functionName) {
private static final Logger log = Logger.getLogger(FunctionRegistry.class);

public void register(Class clz, String methodName, String descriptor, String functionName) {
String methodDescription = clz.getName() + "/" + methodName + descriptor;

FunctionInvoker fi = functions.get(functionName);
if (fi != null) {
String otherMethodDescription = fi.targetClass.getName() + "/" + fi.method.getName()
+ getMethodDescriptor(fi.method);
String msg = String.format("Name conflict: the name \"%s\" is shared by \"%s\" and \"%s\"." +
" Consider using @Func(\"name-here\") annotation parameter to distinguish them.",
functionName, methodDescription, otherMethodDescription);
log.warn(msg);
}

for (Method m : clz.getMethods()) {
if (m.getName().equals(methodName)) {
if (m.getName().equals(methodName) && descriptor.equals(getMethodDescriptor(m))) {
functions.put(functionName, new FunctionInvoker(functionName, clz, m));
return;
}
}

throw new RuntimeException("Method \"" + methodDescription + "\" not found.");
}

public FunctionInvoker matchInvoker(String name) {
Expand All @@ -23,4 +42,39 @@ public FunctionInvoker matchInvoker(String name) {
public Collection<FunctionInvoker> invokers() {
return functions.values();
}

private static String getDescriptorForClass(final Class c) {
if (c.isPrimitive()) {
if (c == byte.class)
return "B";
if (c == char.class)
return "C";
if (c == double.class)
return "D";
if (c == float.class)
return "F";
if (c == int.class)
return "I";
if (c == long.class)
return "J";
if (c == short.class)
return "S";
if (c == boolean.class)
return "Z";
if (c == void.class)
return "V";
throw new RuntimeException("Unrecognized primitive " + c);
}
if (c.isArray())
return c.getName().replace('.', '/');
return ('L' + c.getName() + ';').replace('.', '/');
}

private static String getMethodDescriptor(Method m) {
String s = "(";
for (final Class c : m.getParameterTypes())
s += getDescriptorForClass(c);
s += ')';
return s + getDescriptorForClass(m.getReturnType());
}
}

0 comments on commit a285824

Please sign in to comment.