Copilot commented on code in PR #6339:
URL: https://github.com/apache/shenyu/pull/6339#discussion_r3252999456
##########
shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/utils/OpenApiUtils.java:
##########
@@ -296,6 +747,226 @@ private static ResponseType parseGenericArrayType(final
ResponseType responseTyp
return responseType;
}
+ private static Schema parseSchema(final Type type, final int depth, final
Map<TypeVariable<?>, Type> typeVariableMap) {
+ if (depth > 5) {
+ return new Schema("object", null);
+ }
+ if (type instanceof Class) {
+ return parseClassSchema((Class<?>) type, depth, typeVariableMap);
+ } else if (type instanceof ParameterizedType) {
+ return parseParameterizedTypeSchema((ParameterizedType) type,
depth, typeVariableMap);
+ } else if (type instanceof GenericArrayType) {
+ Schema elementSchema = parseSchema(((GenericArrayType)
type).getGenericComponentType(), depth + 1, typeVariableMap);
+ Schema schema = new Schema("array", null);
+ schema.setRefs(Collections.singletonList(elementSchema));
+ return schema;
+ } else if (type instanceof TypeVariable) {
+ Type actualType = typeVariableMap.get(type);
+ if (Objects.nonNull(actualType)) {
+ return parseSchema(actualType, depth, typeVariableMap);
+ } else if (((TypeVariable<?>) type).getBounds().length > 0) {
+ return parseSchema(((TypeVariable<?>) type).getBounds()[0],
depth, typeVariableMap);
+ } else {
+ return new Schema("object", null);
+ }
+ } else {
+ return new Schema("object", null);
+ }
+ }
+
+ private static Schema parseClassSchema(final Class<?> clazz, final int
depth, final Map<TypeVariable<?>, Type> typeVariableMap) {
+ if (clazz.isArray()) {
+ Schema elementSchema = parseSchema(clazz.getComponentType(), depth
+ 1, typeVariableMap);
+ Schema schema = new Schema("array", null);
+ schema.setRefs(Collections.singletonList(elementSchema));
+ return schema;
+ } else if (clazz.isEnum()) {
+ return new Schema("string", null);
+ } else if (isBooleanType(clazz)) {
+ return new Schema("boolean", null);
+ } else if (isIntegerType(clazz)) {
+ return new Schema("integer", null);
+ } else if (isNumberType(clazz)) {
+ return new Schema("number", null);
+ } else if (isStringType(clazz)) {
+ return new Schema("string", null);
+ } else if (isDateType(clazz)) {
+ return new Schema("string", "date");
+ } else if (Collection.class.isAssignableFrom(clazz)) {
+ return new Schema("array", null);
+ } else if (Map.class.isAssignableFrom(clazz)) {
+ return new Schema("object", null);
+ } else if (isProtobufMessage(clazz)) {
+ return parseProtobufClassSchema(clazz, depth, typeVariableMap);
+ } else {
+ List<Schema> refs = new ArrayList<>();
+ for (Field field : clazz.getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ continue;
+ }
+ Schema fieldSchema = parseSchema(field.getGenericType(), depth
+ 1, typeVariableMap);
+ fieldSchema.setName(field.getName());
+ refs.add(fieldSchema);
+ }
+ Schema schema = new Schema("object", null);
+ schema.setRefs(refs);
+ return schema;
+ }
+ }
+
+ private static Schema parseParameterizedTypeSchema(final ParameterizedType
type, final int depth, final Map<TypeVariable<?>, Type> typeVariableMap) {
+ Class<?> rawType = (Class<?>) type.getRawType();
+ Type[] actualTypeArguments = type.getActualTypeArguments();
+ TypeVariable<?>[] typeVariables = rawType.getTypeParameters();
+ Map<TypeVariable<?>, Type> newTypeVariableMap = new
HashMap<>(typeVariableMap);
+ for (int i = 0; i < typeVariables.length; i++) {
+ newTypeVariableMap.put(typeVariables[i], actualTypeArguments[i]);
+ }
+ if (Collection.class.isAssignableFrom(rawType)) {
+ Schema elementSchema = parseSchema(actualTypeArguments[0], depth +
1, newTypeVariableMap);
+ elementSchema.setName("items");
+ Schema schema = new Schema("array", null);
+ schema.setRefs(Collections.singletonList(elementSchema));
+ return schema;
+ } else if (Map.class.isAssignableFrom(rawType)) {
+ Schema keySchema = parseSchema(actualTypeArguments[0], depth + 1,
newTypeVariableMap);
+ keySchema.setName("key");
+ Schema valueSchema = parseSchema(actualTypeArguments[1], depth +
1, newTypeVariableMap);
+ valueSchema.setName("value");
+ Schema schema = new Schema("object", null);
+ schema.setRefs(Arrays.asList(keySchema, valueSchema));
+ return schema;
+ } else {
+ List<Schema> refs = new ArrayList<>();
+ for (Field field : rawType.getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ continue;
+ }
+ Schema fieldSchema = parseSchema(field.getGenericType(), depth
+ 1, newTypeVariableMap);
+ fieldSchema.setName(field.getName());
+ refs.add(fieldSchema);
+ }
+ Schema schema = new Schema("object", null);
+ schema.setRefs(refs);
+ return schema;
+ }
+ }
+
+ private static Schema parseProtobufClassSchema(final Class<?> clazz, final
int depth, final Map<TypeVariable<?>, Type> typeVariableMap) {
+ if (isProtobufEmpty(clazz)) {
+ return new Schema("object", null);
+ }
+ try {
+ java.lang.reflect.Method getDescriptorMethod =
clazz.getMethod("getDescriptor");
+ Object descriptor = getDescriptorMethod.invoke(null);
+ java.lang.reflect.Method getFieldsMethod =
descriptor.getClass().getMethod("getFields");
+ @SuppressWarnings("unchecked")
+ List<?> fields = (List<?>) getFieldsMethod.invoke(descriptor);
+ List<Schema> refs = parseProtobufFieldsSchema(fields, clazz,
depth, typeVariableMap);
+ Schema schema = new Schema("object", null);
+ schema.setRefs(refs);
+ return schema;
+ } catch (Exception e) {
+ return new Schema("object", null);
+ }
+ }
+
+ private static List<Schema> parseProtobufFieldsSchema(final List<?>
fields, final Class<?> clazz,
+ final int depth,
final Map<TypeVariable<?>, Type> typeVariableMap) throws Exception {
+ List<Schema> refs = new ArrayList<>();
+ java.lang.reflect.Method getNameMethod = null;
+ java.lang.reflect.Method getTypeMethod = null;
+ java.lang.reflect.Method isRepeatedMethod = null;
+ java.lang.reflect.Method getMessageTypeMethod = null;
+ for (Object field : fields) {
+ if (Objects.isNull(getNameMethod)) {
+ getNameMethod = field.getClass().getMethod("getName");
+ getTypeMethod = field.getClass().getMethod("getType");
+ isRepeatedMethod = field.getClass().getMethod("isRepeated");
+ getMessageTypeMethod =
field.getClass().getMethod("getMessageType");
+ }
+ String fieldName = (String) getNameMethod.invoke(field);
+ Object fieldType = getTypeMethod.invoke(field);
+ boolean isRepeated = (boolean) isRepeatedMethod.invoke(field);
+ refs.add(parseProtobufFieldSchema(fieldName, fieldType, isRepeated,
+ getMessageTypeMethod, field, clazz, depth,
typeVariableMap));
+ }
+ return refs;
+ }
+
+ private static Schema parseProtobufFieldSchema(final String fieldName,
final Object fieldType, final boolean isRepeated,
+ final
java.lang.reflect.Method getMessageTypeMethod, final Object field,
+ final Class<?> clazz, final
int depth,
+ final Map<TypeVariable<?>,
Type> typeVariableMap) throws Exception {
+ if (isRepeated) {
+ return parseRepeatedProtobufFieldSchema(fieldName, fieldType,
getMessageTypeMethod, field);
+ }
+ String fieldTypeName = fieldType.toString();
+ Schema schema;
+ if ("MESSAGE".equals(fieldTypeName)) {
+ schema = resolveProtobufMessageFieldSchema(getMessageTypeMethod,
field, clazz, depth, typeVariableMap);
+ } else if ("ENUM".equals(fieldTypeName)) {
+ schema = new Schema("string", null);
+ } else {
+ schema = new Schema(mapProtobufTypeToOpenApi(fieldTypeName), null);
+ }
+ schema.setName(fieldName);
+ return schema;
+ }
+
+ private static Schema parseRepeatedProtobufFieldSchema(final String
fieldName, final Object fieldType,
+ final
java.lang.reflect.Method getMessageTypeMethod,
+ final Object field)
throws Exception {
+ String fieldTypeName = fieldType.toString();
+ Schema elementSchema;
+ if ("MESSAGE".equals(fieldTypeName)) {
+ Object msgDescriptor = getMessageTypeMethod.invoke(field);
+ java.lang.reflect.Method getFullNameMethod =
msgDescriptor.getClass().getMethod("getFullName");
+ String fullMsgName = (String)
getFullNameMethod.invoke(msgDescriptor);
+ elementSchema = new Schema("object", null);
+ } else {
+ elementSchema = new
Schema(mapProtobufTypeToOpenApi(fieldTypeName), null);
+ }
Review Comment:
In parseRepeatedProtobufFieldSchema(), the computed fullMsgName is unused
and the elementSchema never gets a name. Because convertSchemaToParameter()
uses ref.getName() when converting schema refs, repeated protobuf fields
currently produce an item ref with a null name in the generated
requestParameters. Consider setting a stable item name (e.g., "items") and
either remove fullMsgName or use it (e.g., as a description / to drive nested
schema parsing) to avoid losing message context.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]