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

Backport updates from main 4 #1931

Merged
merged 10 commits into from
Aug 1, 2024
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>parsson</artifactId>
<version>1.1.6</version>
<version>1.1.7</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface UtilLogging extends BasicLogger {
@Message(id = 1000, value = "Failed to introspect BeanInfo for: %s")
void failedToIntrospectBeanInfo(Class<?> clazz, @Cause Throwable cause);

@LogMessage(level = Logger.Level.INFO)
@LogMessage(level = Logger.Level.DEBUG)
@Message(id = 1001, value = "Schema with zero references removed from #/components/schemas: %s")
void unusedSchemaRemoved(String name);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

Expand Down Expand Up @@ -54,9 +55,10 @@ public enum Visibility {
UNSET
}

public Visibility isIgnore(AnnotationTarget annotationTarget, AnnotationTarget reference) {
public Visibility isIgnore(Map<String, TypeResolver> properties,
AnnotationTarget annotationTarget, AnnotationTarget reference) {
for (IgnoreAnnotationHandler handler : ignoreHandlers) {
Visibility v = handler.shouldIgnore(annotationTarget, reference);
Visibility v = handler.shouldIgnore(properties, annotationTarget, reference);

if (v != Visibility.UNSET) {
return v;
Expand All @@ -82,7 +84,8 @@ public Visibility getDescendantVisibility(String propertyName, List<ClassInfo> d
*/
private final class SchemaHiddenHandler implements IgnoreAnnotationHandler {
@Override
public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference) {
public Visibility shouldIgnore(Map<String, TypeResolver> properties, AnnotationTarget target,
AnnotationTarget reference) {
AnnotationInstance annotationInstance = context.annotations().getAnnotation(target, getNames());
if (annotationInstance != null) {
Boolean hidden = context.annotations().value(annotationInstance, SchemaConstant.PROP_HIDDEN);
Expand All @@ -105,7 +108,8 @@ public List<DotName> getNames() {
*/
private final class JsonbTransientHandler implements IgnoreAnnotationHandler {
@Override
public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference) {
public Visibility shouldIgnore(Map<String, TypeResolver> properties, AnnotationTarget target,
AnnotationTarget reference) {
return context.annotations().hasAnnotation(target, getNames()) ? Visibility.IGNORED : Visibility.UNSET;
}

Expand All @@ -121,14 +125,15 @@ public List<DotName> getNames() {
private final class JsonIgnorePropertiesHandler implements IgnoreAnnotationHandler {

@Override
public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference) {
Visibility visibility = declaringClassIgnore(target);
public Visibility shouldIgnore(Map<String, TypeResolver> properties, AnnotationTarget target,
AnnotationTarget reference) {
Visibility visibility = declaringClassIgnore(properties, target);

if (visibility != Visibility.UNSET) {
return visibility;
}

return nestingPropertyIgnore(reference, propertyName(target));
return nestingPropertyIgnore(reference, propertyName(properties, target));
}

/**
Expand All @@ -146,10 +151,10 @@ public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget referen
* @param target
* @return
*/
private Visibility declaringClassIgnore(AnnotationTarget target) {
private Visibility declaringClassIgnore(Map<String, TypeResolver> properties, AnnotationTarget target) {
AnnotationInstance declaringClassJIP = context.annotations().getAnnotation(TypeUtil.getDeclaringClass(target),
getNames());
return shouldIgnoreTarget(declaringClassJIP, propertyName(target));
return shouldIgnoreTarget(declaringClassJIP, propertyName(properties, target));
}

/**
Expand Down Expand Up @@ -181,12 +186,12 @@ private Visibility nestingPropertyIgnore(AnnotationTarget nesting, String proper
return shouldIgnoreTarget(nestedTypeJIP, propertyName);
}

private String propertyName(AnnotationTarget target) {
private String propertyName(Map<String, TypeResolver> properties, AnnotationTarget target) {
if (target.kind() == Kind.FIELD) {
return target.asField().name();
}
// Assuming this is a getter or setter
return TypeResolver.propertyName(target.asMethod());
return TypeResolver.propertyName(properties, target.asMethod());
}

private Visibility shouldIgnoreTarget(AnnotationInstance jipAnnotation, String targetName) {
Expand Down Expand Up @@ -227,7 +232,8 @@ public Visibility getDescendantVisibility(String propertyName, List<ClassInfo> d
private final class JsonIgnoreHandler implements IgnoreAnnotationHandler {

@Override
public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference) {
public Visibility shouldIgnore(Map<String, TypeResolver> properties, AnnotationTarget target,
AnnotationTarget reference) {
AnnotationInstance annotationInstance = context.annotations().getAnnotation(target, getNames());
if (annotationInstance != null && valueAsBooleanOrTrue(annotationInstance)) {
return Visibility.IGNORED;
Expand All @@ -248,7 +254,8 @@ private final class JsonIgnoreTypeHandler implements IgnoreAnnotationHandler {
private final Set<DotName> ignoredTypes = new LinkedHashSet<>();

@Override
public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference) {
public Visibility shouldIgnore(Map<String, TypeResolver> properties, AnnotationTarget target,
AnnotationTarget reference) {
Type classType;

switch (target.kind()) {
Expand Down Expand Up @@ -277,7 +284,7 @@ public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget referen
// Primitive and non-indexed types will result in a null
if (classType.kind() == Type.Kind.PRIMITIVE ||
classType.kind() == Type.Kind.VOID ||
(classType.kind() == Type.Kind.ARRAY && classType.asArrayType().component().kind() == Type.Kind.PRIMITIVE)
(classType.kind() == Type.Kind.ARRAY && classType.asArrayType().constituent().kind() == Type.Kind.PRIMITIVE)
||
!index.containsClass(classType)) {
return Visibility.UNSET;
Expand Down Expand Up @@ -309,7 +316,8 @@ public List<DotName> getNames() {

private final class TransientIgnoreHandler implements IgnoreAnnotationHandler {
@Override
public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference) {
public Visibility shouldIgnore(Map<String, TypeResolver> properties, AnnotationTarget target,
AnnotationTarget reference) {
if (target.kind() == AnnotationTarget.Kind.FIELD) {
FieldInfo field = target.asField();
// If field has transient modifier, e.g. `transient String foo;`, then hide it.
Expand All @@ -336,7 +344,8 @@ public List<DotName> getNames() {

private final class JaxbAccessibilityHandler implements IgnoreAnnotationHandler {
@Override
public Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference) {
public Visibility shouldIgnore(Map<String, TypeResolver> properties, AnnotationTarget target,
AnnotationTarget reference) {
if (hasXmlTransient(target)) {
return Visibility.IGNORED;
}
Expand Down Expand Up @@ -411,7 +420,9 @@ private boolean valueAsBooleanOrTrue(AnnotationInstance annotation) {
}

private interface IgnoreAnnotationHandler {
Visibility shouldIgnore(AnnotationTarget target, AnnotationTarget reference);
Visibility shouldIgnore(Map<String, TypeResolver> properties,
AnnotationTarget target,
AnnotationTarget reference);

List<DotName> getNames();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ private static List<MethodInfo> methods(AnnotationScannerContext context, ClassI
}

private static boolean acceptMethod(MethodInfo method) {
if (Modifier.isStatic(method.flags())) {
if (Modifier.isStatic(method.flags()) || method.isSynthetic()) {
return false;
}
String name = method.name();
Expand Down Expand Up @@ -603,11 +603,11 @@ private static boolean isViewable(AnnotationScannerContext context, AnnotationTa
* @param target the field or method to be checked for ignoring or exposure in the API
* @param reference an annotated member (field or method) that referenced the type of target's declaring class
* @param descendants list of classes that descend from the class containing target
* @param ignoreResolver resolver to determine if the field is ignored
* @param properties map of other known properties that are peers of the target
*/
private void processVisibility(AnnotationScannerContext context, AnnotationTarget target, AnnotationTarget reference,
List<ClassInfo> descendants,
IgnoreResolver ignoreResolver) {
Map<String, TypeResolver> properties) {
if (this.exposed || this.ignored) {
// @Schema with hidden = false OR ignored somehow by a member lower in the class hierarchy
return;
Expand All @@ -619,7 +619,7 @@ private void processVisibility(AnnotationScannerContext context, AnnotationTarge
return;
}

switch (getVisibility(context, target, reference, descendants, ignoreResolver)) {
switch (getVisibility(context, target, reference, descendants, properties)) {
case EXPOSED:
this.exposed = true;
break;
Expand Down Expand Up @@ -674,22 +674,23 @@ private void processAccess(AnnotationTarget target) {
* @param target the field or method to be checked for ignoring or exposure in the API
* @param reference an annotated member (field or method) that referenced the type of target's declaring class
* @param descendants list of classes that descend from the class containing target
* @param ignoreResolver resolver to determine if the field is ignored
* @param properties map of other known properties that are peers of the target
*/
private IgnoreResolver.Visibility getVisibility(AnnotationScannerContext context, AnnotationTarget target,
AnnotationTarget reference,
List<ClassInfo> descendants,
IgnoreResolver ignoreResolver) {
Map<String, TypeResolver> properties) {

if (!isViewable(context, target)) {
return IgnoreResolver.Visibility.IGNORED;
}

IgnoreResolver ignoreResolver = context.getIgnoreResolver();
// First check if a descendant class has hidden/exposed the property
IgnoreResolver.Visibility visibility = ignoreResolver.getDescendantVisibility(propertyName, descendants);

if (visibility == IgnoreResolver.Visibility.UNSET) {
visibility = ignoreResolver.isIgnore(target, reference);
visibility = ignoreResolver.isIgnore(properties, target, reference);
}

return visibility;
Expand Down Expand Up @@ -773,7 +774,7 @@ private static void scanField(AnnotationScannerContext context, Map<String, Type
// Ignored for getters/setters
resolver.ignored = true;
} else {
resolver.processVisibility(context, field, reference, descendants, context.getIgnoreResolver());
resolver.processVisibility(context, field, reference, descendants, properties);
resolver.processAccess(field);
}
}
Expand Down Expand Up @@ -841,7 +842,7 @@ private static void scanMethod(AnnotationScannerContext context, Map<String, Typ
if (propertyType != null) {
TypeResolver resolver = updateTypeResolvers(context, properties, stack, method, propertyType);
if (resolver != null) {
resolver.processVisibility(context, method, reference, descendants, context.getIgnoreResolver());
resolver.processVisibility(context, method, reference, descendants, properties);
resolver.processAccess(method);
}
}
Expand All @@ -865,7 +866,7 @@ private static TypeResolver updateTypeResolvers(AnnotationScannerContext context
MethodInfo method,
Type propertyType) {

final String propertyName = propertyName(method);
final String propertyName = propertyName(properties, method);

if (propertyName == null) {
return null;
Expand Down Expand Up @@ -913,7 +914,7 @@ private static TypeResolver updateTypeResolvers(AnnotationScannerContext context
* @param method either an accessor (getter) or mutator (setter) for the property
* @return the property name
*/
static String propertyName(MethodInfo method) {
static String propertyName(Map<String, TypeResolver> properties, MethodInfo method) {
final String methodName = method.name();
final ClassInfo declaringClass = method.declaringClass();

Expand All @@ -923,6 +924,11 @@ static String propertyName(MethodInfo method) {
return methodName;
}

if (Optional.ofNullable(properties.get(methodName)).map(p -> p.field).isPresent()) {
// The method name matches the field name. Do not modify further.
return methodName;
}

final int nameStart = methodNamePrefix(method).length();
final String propertyName;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public class TypeUtil {
TYPE_MAP.put(DotName.createSimple(StringBuilder.class.getName()), STRING_FORMAT);
TYPE_MAP.put(DotName.createSimple(CharSequence.class.getName()), STRING_FORMAT);
TYPE_MAP.put(DotName.createSimple(java.net.URI.class.getName()), URI_FORMAT);
TYPE_MAP.put(DotName.createSimple(java.net.URL.class.getName()), STRING_FORMAT);
TYPE_MAP.put(DotName.createSimple(java.util.UUID.class.getName()), UUID_FORMAT);

// B64 String
Expand Down Expand Up @@ -669,7 +670,7 @@ public static Type getOptionalType(Type type) {

public static DotName getName(Type type) {
if (type.kind() == Type.Kind.ARRAY) {
return type.asArrayType().component().name();
return type.asArrayType().constituent().name();
}
if (type.kind() == Type.Kind.WILDCARD_TYPE) {
return getBound(type.asWildcardType()).name();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -789,4 +789,35 @@ class Bean {

assertJsonEquals("components.schemas.exceptional-examples.json", Bean.class);
}

@Test
void testPropertyWithJavaBeanPrefixes() throws IOException, JSONException {
@Schema(name = "Bean")
@SuppressWarnings("unused")
class Bean {
@Schema(name = "getProperty1")
public String getProperty1;

@Schema(name = "propertyTwo")
public java.net.URL getProperty2;

public String getProperty1() {
return getProperty1;
}

public void getProperty1(String getProperty1) {
this.getProperty1 = getProperty1;
}

public java.net.URL getProperty2() {
return getProperty2;
}

public void getProperty2(java.net.URL getProperty2) {
this.getProperty2 = getProperty2;
}
}

assertJsonEquals("components.schemas.javabean-property-prefix.json", Bean.class, java.net.URL.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"openapi" : "3.1.0",
"components" : {
"schemas" : {
"Bean" : {
"type" : "object",
"properties" : {
"getProperty1" : {
"type" : "string"
},
"propertyTwo" : {
"type" : "string"
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion extension-jaxrs/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<name>SmallRye: OpenAPI extension - JAX-RS</name>

<properties>
<version.parsson.json>1.1.6</version.parsson.json>
<version.parsson.json>1.1.7</version.parsson.json>
</properties>

<dependencies>
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
<version.buildhelper.plugin>3.6.0</version.buildhelper.plugin>
<jackson-bom.version>2.17.2</jackson-bom.version>
<version.eclipse.microprofile.config>3.0.3</version.eclipse.microprofile.config>
<version.io.smallrye.jandex>3.2.0</version.io.smallrye.jandex>
<version.io.smallrye.smallrye-config>3.8.3</version.io.smallrye.smallrye-config>
<version.io.smallrye.jandex>3.2.1</version.io.smallrye.jandex>
<version.io.smallrye.smallrye-config>3.9.0</version.io.smallrye.smallrye-config>
<version.eclipse.microprofile.openapi>4.0</version.eclipse.microprofile.openapi>
<version.org.hamcrest>1.3</version.org.hamcrest>
<version.org.hamcrest.java-hamcrest>2.0.0.0</version.org.hamcrest.java-hamcrest>
<version.org.skyscreamer>1.5.3</version.org.skyscreamer>
<version.maven-resources-plugin>3.3.1</version.maven-resources-plugin>
<version.com.github.eirslett.frontend-maven-plugin>1.15.0</version.com.github.eirslett.frontend-maven-plugin>
<version.quarkus>3.12.2</version.quarkus>
<version.quarkus>3.13.0</version.quarkus>
<version.testng>7.10.2</version.testng>
<version.arquillian.jetty>2.0.0.Final</version.arquillian.jetty>
<version.jetty>11.0.22</version.jetty>
Expand Down
2 changes: 1 addition & 1 deletion testsuite/data/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<maven.compiler.release>${java.version}</maven.compiler.release>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
<quarkus.platform.version>3.12.2</quarkus.platform.version>
<quarkus.platform.version>3.13.0</quarkus.platform.version>
<quarkus.package.type>uber-jar</quarkus.package.type>
<quarkus.package.add-runner-suffix>false</quarkus.package.add-runner-suffix>
</properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import org.junit.jupiter.params.provider.ValueSource;
import org.skyscreamer.jsonassert.JSONAssert;

import io.smallrye.config.ConfigValuePropertiesConfigSource;
import io.smallrye.config.PropertiesConfigSource;
import io.smallrye.config.SmallRyeConfigBuilder;
import io.smallrye.openapi.api.OpenApiConfig;
import io.smallrye.openapi.runtime.OpenApiProcessor;
Expand Down Expand Up @@ -62,7 +62,7 @@ static OpenApiConfig dynamicConfig(String key, Object value) {

static OpenApiConfig dynamicConfig(Map<String, String> properties) {
Config config = new SmallRyeConfigBuilder()
.withSources(new ConfigValuePropertiesConfigSource(properties, "unit-test", ConfigSource.DEFAULT_ORDINAL))
.withSources(new PropertiesConfigSource(properties, "unit-test", ConfigSource.DEFAULT_ORDINAL))
.build();
return OpenApiConfig.fromConfig(config);
}
Expand Down
Loading