Skip to content

Commit

Permalink
Ignore synthetic methods during parameter scan (#1390)
Browse files Browse the repository at this point in the history
Fixes #1256

Signed-off-by: Michael Edgar <[email protected]>
  • Loading branch information
MikeEdgar authored Mar 1, 2023
1 parent 22b883b commit ee4723f
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1533,30 +1533,40 @@ boolean isBeanPropertyParam(AnnotationInstance annotation) {
boolean relevant = false;

switch (target.kind()) {
case FIELD:
case FIELD: {
FieldInfo field = target.asField();
relevant = hasParameters(field.annotations());
break;
case METHOD_PARAMETER:
}

case METHOD_PARAMETER: {
MethodParameterInfo param = target.asMethodParameter();
relevant = !isResourceMethod(param.method()) &&
hasParameters(TypeUtil.getAnnotations(param)) &&
!isSubResourceLocator(param.method());
MethodInfo method = param.method();
relevant = nonSyntheticParameterMethod(method, TypeUtil.getAnnotations(param));
break;
case METHOD:
}

case METHOD: {
MethodInfo method = target.asMethod();
relevant = !isResourceMethod(method) &&
hasParameters(method.annotations()) &&
getType(target) != null &&
!isSubResourceLocator(method);
relevant = nonSyntheticParameterMethod(method, method.annotations()) &&
getType(target) != null;
break;
}

default:
break;
}

return relevant;
}

boolean nonSyntheticParameterMethod(MethodInfo method, Collection<AnnotationInstance> annotations) {
return !method.isSynthetic() &&
!isResourceMethod(method) &&
hasParameters(annotations) &&
!isSubResourceLocator(method);
}

/**
* Determines if the given method is a sub-resource locator method
* annotated by {@code @Path} but NOT annotated with one of the HTTP method
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalLong;

import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import org.jboss.jandex.Index;
import org.jboss.jandex.IndexReader;
Expand Down Expand Up @@ -468,4 +476,77 @@ void testPreferredParameterOrderWithAnnotation() throws IOException, JSONExcepti
test("params.annotation-preferred-order.json",
test.io.smallrye.openapi.runtime.scanner.jakarta.ParameterOrderResource.CLASSES);
}

static class Issue1256 {
static final Class<?>[] CLASSES = {
BeanParamBean.class,
Filter.class,
FilterBean.class,
JsonBase.class,
DataJson.class,
GenericBaseInterface.class,
RestInterface.class,
RestImpl.class
};

static class BeanParamBean {
@jakarta.ws.rs.QueryParam("param")
@Parameter(description = "A parameter")
private String param;
}

interface Filter {
}

static class FilterBean implements Filter {
}

static class JsonBase {
}

static class DataJson extends JsonBase {
}

interface GenericBaseInterface<T extends JsonBase, F extends Filter> {

@Operation(summary = "list")
@APIResponse(responseCode = "200", description = "OK")
@APIResponse(responseCode = "500", description = "internal server error", content = @Content(schema = @Schema(type = SchemaType.OBJECT)))
List<T> list(BeanParamBean params, F filter);
}

@jakarta.ws.rs.Path("reproducer/reproducers")
@jakarta.ws.rs.Consumes(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
@jakarta.ws.rs.Produces(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)
@Tag(name = "reproducers", description = "This resource is there for reproducing bug 1256.")
interface RestInterface extends GenericBaseInterface<DataJson, FilterBean> {

@jakarta.ws.rs.POST
@Operation(summary = "create")
@APIResponse(responseCode = "200", description = "OK")
@APIResponse(responseCode = "500", description = "internal server error", content = @Content(schema = @Schema(type = SchemaType.OBJECT)))
DataJson create(DataJson json);

@jakarta.ws.rs.GET
@Override
List<DataJson> list(@jakarta.ws.rs.BeanParam BeanParamBean params, @jakarta.ws.rs.BeanParam FilterBean filter);
}

static class RestImpl implements RestInterface {
@Override
public DataJson create(DataJson json) {
return null;
}

@Override
public List<DataJson> list(BeanParamBean params, FilterBean filter) {
return null;
}
}
}

@Test
void testParamsNotDuplicated() throws IOException, JSONException {
test("params.synthetic-methods-not-included.json", Issue1256.CLASSES);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
{
"openapi": "3.0.3",
"tags": [
{
"name": "reproducers",
"description": "This resource is there for reproducing bug 1256."
}
],
"paths": {
"/reproducer/reproducers": {
"get": {
"tags": [
"reproducers"
],
"parameters": [
{
"name": "param",
"in": "query",
"description": "A parameter",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DataJson"
}
}
}
}
}
}
},
"post": {
"tags": [
"reproducers"
],
"summary": "create",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataJson"
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DataJson"
}
}
}
},
"500": {
"description": "internal server error",
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"DataJson": {
"type": "object"
}
}
}
}

0 comments on commit ee4723f

Please sign in to comment.