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]

Reply via email to