Skip to content

Commit

Permalink
Merge pull request micronaut-projects#1884 from altro3/ksp-fixes
Browse files Browse the repository at this point in the history
Fix wrong warnings
  • Loading branch information
altro3 authored Nov 20, 2024
2 parents 08bb2d1 + 6e8b790 commit 996e53f
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 25 deletions.
1 change: 0 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ org.gradle.configuration-cache=false
org.gradle.configuration-cache.parallel=false
org.gradle.caching=true
org.gradle.parallel=true

kotlin.stdlib.default.dependency=false

# No matter which Java toolchain we use, the Kotlin Daemon is always invoked by the current JDK.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,9 @@ private Parameter processMethodParameterAnnotation(VisitorContext context, Opera
}
UriMatchVariable variable = pathVariables.get(paramName);
if (variable == null) {
warn("Path variable name: '" + paramName + "' not found in path, operation: " + swaggerOperation.getOperationId(), context, parameter);
if (!isNullable(parameter)) {
warn("Path variable name: '" + paramName + "' not found in path, operation: " + swaggerOperation.getOperationId(), context, parameter);
}
return null;
}
newParameter = new PathParameter();
Expand Down
46 changes: 33 additions & 13 deletions openapi/src/main/java/io/micronaut/openapi/visitor/ConfigUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,25 @@ public static ClassElement getCustomSchema(String className, Map<String, ClassEl
Environment environment = getEnv(context);
if (environment != null) {
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA, StringConvention.RAW).entrySet()) {

String configuredClassName = entry.getKey();
// Remove this check, after we remove MICRONAUT_OPENAPI_SCHEMA property
String prop = MICRONAUT_OPENAPI_SCHEMA + StringUtil.DOT + configuredClassName;
if (isMicronautProperty(prop)) {
continue;
}

String targetClassName = (String) entry.getValue();
readCustomSchema(configuredClassName, targetClassName, customSchemas, context);
}
for (Map.Entry<String, Object> entry : environment.getProperties(MICRONAUT_OPENAPI_SCHEMA_MAPPING, StringConvention.RAW).entrySet()) {
String configuredClassName = entry.getKey();

// Remove this check, after we remove MICRONAUT_OPENAPI_SCHEMA property
String prop = MICRONAUT_OPENAPI_SCHEMA + StringUtil.DOT + configuredClassName;
if (isMicronautProperty(prop)) {
continue;
}
String targetClassName = (String) entry.getValue();
readCustomSchema(configuredClassName, targetClassName, customSchemas, context);
}
Expand All @@ -238,6 +251,18 @@ public static ClassElement getCustomSchema(String className, Map<String, ClassEl
return customSchema != null ? customSchema.classElement : null;
}

private static boolean isMicronautProperty(String prop) {
return prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_PREFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_POSTFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_PREFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_POSTFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_EMPTY)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_GENERIC)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_INNER_CLASS)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_DUPLICATE_RESOLUTION)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_EXTRA_ENABLED);
}

private static String getClassNameWithGenerics(String className, Map<String, ClassElement> typeArgs) {
var key = new StringBuilder(className);
if (!typeArgs.isEmpty()) {
Expand Down Expand Up @@ -734,24 +759,19 @@ private static void readSchemaDecorators(Properties props, Map<String, SchemaDec
private static void readCustomSchemas(Properties props, Map<String, CustomSchema> customSchemas, VisitorContext context) {

for (String prop : props.stringPropertyNames()) {
if (!prop.startsWith(MICRONAUT_OPENAPI_SCHEMA)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_PREFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_POSTFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_PREFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_DECORATOR_POSTFIX)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_EMPTY)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_GENERIC)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_INNER_CLASS)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_DUPLICATE_RESOLUTION)
|| prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_EXTRA_ENABLED)
) {

// Remove this check, after we remove MICRONAUT_OPENAPI_SCHEMA property
if (isMicronautProperty(prop)) {
continue;
}

String className;
if (prop.startsWith(MICRONAUT_OPENAPI_SCHEMA_MAPPING)) {
className = prop.substring(MICRONAUT_OPENAPI_SCHEMA_MAPPING.length() + 1);
} else {
} else if (prop.startsWith(MICRONAUT_OPENAPI_SCHEMA)) {
className = prop.substring(MICRONAUT_OPENAPI_SCHEMA.length() + 1);
} else {
continue;
}
String targetClassName = props.getProperty(prop);
readCustomSchema(className, targetClassName, customSchemas, context);
Expand All @@ -764,7 +784,7 @@ private static void readCustomSchema(String className, String targetClassName, M
}
ClassElement targetClassElement = ContextUtils.getClassElement(targetClassName, context);
if (targetClassElement == null) {
warn("Can't find class " + targetClassName + " in classpath. Skip it.", context);
warn("Can't find class " + targetClassName + " for className " + className + " in classpath. Custom schemas: " + customSchemas + ". Skip it.", context);
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,14 @@ public static void addEnumExtensions(EnumElement enumEl, Schema<?> schema, Visit
}
}

// check if upper case values equals with enum var names
var generatedEnumVarNames = new ArrayList<String>(schema.getEnum().size());
for (var enumVal : schema.getEnum()) {
generatedEnumVarNames.add(enumVal.toString().toUpperCase());
}

if (!enumVarNameList.isEmpty() && !extensions.containsKey(ENUM_VAR_NAMES)
&& !schema.getEnum().equals(enumVarNameList)) {
&& !generatedEnumVarNames.equals(enumVarNameList)) {
extensions.put(ENUM_VAR_NAMES, enumVarNameList);
}
if (!enumVarDocList.isEmpty() && !extensions.containsKey(ENUM_DESCRIPTIONS)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,109 @@ class MyBean {}
schema.properties.class
schema.properties.class.maxLength == 50
}

void "test kotlin optional path vars"() {

when:
buildBeanDefinition('test.MyBean', '''
package test
import com.fasterxml.jackson.annotation.*
import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.annotation.JsonValue
import io.micronaut.core.annotation.Nullable
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Header
import io.micronaut.http.annotation.PathVariable
import io.micronaut.http.annotation.Post
import io.micronaut.serde.annotation.Serdeable
import jakarta.validation.constraints.*
@Controller
open class MyEntity2Controller {
@Post("/test2{/apiVersion}")
open fun test(
@Header("X-Favor-Token") @Nullable xFavorToken: String? = null,
@PathVariable("apiVersion") @Nullable apiVersion: MyEnum? = MyEnum.V5,
@Header("Content-Type") @Nullable contentType: String? = "application/json"
): String? {
return null
}
@Serdeable
enum class MyEnum(
@get:JsonValue val value: String
) {
@JsonProperty("v1")
V1("v1"),
@JsonProperty("v2")
V2("v2"),
@JsonProperty("v3")
V3("v3"),
@JsonProperty("v4")
V4("v4"),
@JsonProperty("v5")
V5("v5"),
@JsonProperty("v6")
V6("v6"),
@JsonProperty("v7")
V7("v7");
override fun toString(): String {
return value
}
companion object {
@JvmField
val VALUE_MAPPING = entries.associateBy { it.value }
/**
* Create this enum from a value.
*
* @param value value for enum
*
* @return The enum
*/
@JsonCreator
@JvmStatic
fun fromValue(value: String): MyEnum {
require(VALUE_MAPPING.containsKey(value)) { "Unexpected value '$value'" }
return VALUE_MAPPING[value]!!
}
}
}
}
@jakarta.inject.Singleton
class MyBean {}
''')
then: "the state is correct"
Utils.testReference != null

when: "The OpenAPI is retrieved"
def openAPI = Utils.testReference
Schema schema = openAPI.components.schemas."MyEntity2Controller.MyEnum"

then: "the components are valid"
openAPI.paths."/test2"
openAPI.paths."/test2".post.parameters.size() == 1
openAPI.paths."/test2".post.parameters[0].name == "X-Favor-Token"

openAPI.paths."/test2/{apiVersion}"
openAPI.paths."/test2/{apiVersion}".post.parameters.size() == 2
openAPI.paths."/test2/{apiVersion}".post.parameters[0].name == "X-Favor-Token"
openAPI.paths."/test2/{apiVersion}".post.parameters[1].name == "apiVersion"

!schema.extensions
}
}
9 changes: 0 additions & 9 deletions src/main/docs/guide/gettingStarted.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,6 @@ dependency:micronaut-openapi[scope="annotationProcessor", groupId="io.micronaut.
For Kotlin the `openapi` dependency should be in the `kapt` or `ksp` scope and for Groovy in the `compileOnly` scope.
====

[IMPORTANT]
====
If you use KSP need to disable incremental processing:
[properties]
----
ksp.incremental=false
----
====

To use the https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations[Swagger Annotations] or Micronaut OpenAPI annotations add them to compile classpath

dependency:micronaut-openapi-annotations[scope="compileOnly", groupId="io.micronaut.openapi"]
Expand Down

0 comments on commit 996e53f

Please sign in to comment.