easy-yapi icon indicating copy to clipboard operation
easy-yapi copied to clipboard

[Bug] 枚举无法转换了

Open zhuangjiaju opened this issue 2 years ago • 7 comments

Describe the bug IntelliJ IDEA 2022.2 (Ultimate Edition) easyyapi: 2.4.3.191.0 最新版 提示枚举无法转换了。 [WARN] can not resolve com.alibaba.study.api.enums.OauthSourceEnum for com.alibaba.study.controller.oauth.request.OauthRequest#oauthSource 以前版本的枚举都是可以的。

在vo层的代码: /** * 授权来源 * * @see OauthSourceEnum */ @NotNull(message = "授权来源不能为空") @IsEnum(enumType = OauthSourceEnum.class, message = "授权来源错误") private String oauthSource;

我们的枚举: @Getter public enum OauthSourceEnum implements BaseEnum<String> { /** * 支付宝 */ ALIPAY("支付宝"),

;
final String description;

OauthSourceEnum(String description) {
    this.description = description;
}

@Override
public String getCode() {
    return this.name();
}

}

public interface BaseEnum<T> {

/**
 * 返回枚举的code。一般建议直接返回枚举的name
 *
 * @return code
 */
T getCode();

/**
 * 返回枚举的描述。返回枚举的中文 方便前端下拉
 *
 * @return description
 */
String getDescription();

}

期望能显示: 枚举: SHOW,HIDE

枚举备注: SHOW :显示 HIDE :隐藏

mock: @pick(["SHOW","HIDE"])

这个是以前的

现在空白了。

To Reproduce

Detailed Steps to reproduce the behavior:

  1. Open '...'
  2. Click on '....'
  3. See error

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

Logs

  1. Add config: #Get the module from the comment,group the apis module=#module #-------------------- #Ignore class/api ignore=#ignore #-------------------- #deprecated info(java) method.doc[#deprecated]=groovy:"\n「已废弃」" + it.doc("deprecated") method.doc[@java.lang.Deprecated]=「已废弃」 method.doc[groovy:it.containingClass().hasDoc("deprecated")]=groovy:"\n「已废弃」" + it.containingClass().doc("deprecated") method.doc[groovy:it.containingClass().hasAnn("java.lang.Deprecated")]=「已废弃」 field.doc[#deprecated]=groovy:"\n「已废弃」" + it.doc("deprecated") field.doc[@java.lang.Deprecated]=「已废弃」 #-------------------- #deprecated info(kotlin) method.doc[@kotlin.Deprecated]=groovy:"\n「已废弃」" + it.ann("kotlin.Deprecated","message") method.doc[groovy:it.containingClass().hasAnn("kotlin.Deprecated")]=groovy:"\n「已废弃」 " + it.containingClass().ann("kotlin.Deprecated","message") field.doc[@kotlin.Deprecated]=groovy:"\n「已废弃」" + it.ann("kotlin.Deprecated","message") #-------------------- #Support for Jackson annotations [email protected]#value [email protected]#value field.mock[@com.fasterxml.jackson.annotation.JsonFormat]=groovy:``` return "@datetime("" + it.ann("com.fasterxml.jackson.annotation.JsonFormat","pattern") + "")"
#--------------------
#Support for Gson annotations
[email protected]#value
[email protected]#serialize
#--------------------
#ignore transient field
field.ignore=groovy:it.hasModifier("transient")
#--------------------
#The ObjectId and Date will be parsed as strings
json.rule.convert[org.bson.types.ObjectId]=java.lang.String
json.rule.convert[java.util.Date]=java.lang.String
json.rule.convert[java.sql.Date]=java.lang.String
json.rule.convert[java.sql.Time]=java.lang.String
json.rule.convert[java.sql.Timestamp]=java.lang.String
json.rule.convert[java.time.LocalDateTime]=java.lang.String
json.rule.convert[java.time.LocalDate]=java.lang.String
#--------------------
#resolve HttpEntity/RequestEntity/ResponseEntity/DeferredResult
###set resolveProperty = false
json.rule.convert[#regex:org.springframework.http.HttpEntity<(.*?)>]=${1}
json.rule.convert[org.springframework.http.HttpEntity]=java.lang.Object
json.rule.convert[#regex:org.springframework.http.RequestEntity<(.*?)>]=${1}
json.rule.convert[org.springframework.http.RequestEntity]=java.lang.Object
json.rule.convert[#regex:org.springframework.http.ResponseEntity<(.*?)>]=${1}
json.rule.convert[org.springframework.http.ResponseEntity]=java.lang.Object
json.rule.convert[#regex:org.springframework.web.context.request.async.DeferredResult<(.*?)>]=${1}
json.rule.convert[org.springframework.web.context.request.async.DeferredResult]=java.lang.Object
json.rule.convert[#regex:org.reactivestreams.Publisher<(.*?)>]=${1}
json.rule.convert[org.reactivestreams.Publisher]=java.lang.Object
###set resolveProperty = true
#--------------------
#Support spring.validations
[email protected]
param.ignore=groovy:it.type().isExtend("org.springframework.validation.BindingResult")
field.mock[@org.springframework.format.annotation.DateTimeFormat]=groovy:```
    return "@datetime(\"" + it.ann("org.springframework.format.annotation.DateTimeFormat","pattern") + "\")"

#-------------------- #Support spring.ui param.ignore=groovy:it.type().name()=="org.springframework.ui.Model" param.ignore=groovy:it.type().name()=="org.springframework.ui.ModelMap" param.ignore=groovy:it.type().name()=="org.springframework.web.servlet.ModelAndView" #-------------------- #Support for javax.validation annotations [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] #-------------------- #Support spring file type.is_file=groovy:it.isExtend("org.springframework.web.multipart.MultipartFile") #-------------------- #yapi tag api.tag[@java.lang.Deprecated]=deprecated api.tag[#deprecated]=deprecated api.tag[groovy:it.containingClass().hasAnn("java.lang.Deprecated")]=deprecated api.tag[groovy:it.containingClass().hasDoc("deprecated")]=deprecated #-------------------- #yapi tag for kotlin api.tag[@kotlin.Deprecated]=deprecated api.tag[groovy:it.containingClass().hasAnn("kotlin.Deprecated")]=deprecated #-------------------- #yapi status api.status[#undone]=undone api.status[#todo]=undone #-------------------- #yapi mock field.mock=#mock #-------------------- api.tag=#tag api.tag.delimiter=,&\n #-------------------- #ignore serialVersionUID constant.field.ignore=groovy:it.name()=="serialVersionUID" #-------------------- #mock for date ###set resolveMulti = first java_date_types=["java.util.Date","java.sql.Timestamp","java.time.LocalDate","java.time.LocalDateTime"] field.mock[groovy:${java_date_types}.contains(it.type().name())&&it.jsonType().name()=="java.lang.String"] = groovy:"@datetime" field.mock[groovy:${java_date_types}.contains(it.type().name())&&it.jsonType().name()=="java.lang.Long"] = groovy:"@timestamp@string("number", 3)" ###set resolveMulti = error #--------------------

mock for javax.validation

###set resolveMulti = first

define var

number_min=-9999 number_max=9999 float_dmin=2 java_integer_types=["java.lang.Integer","int","java.lang.Long","long","java.lang.Short","short","java.math.BigInteger"] java_float_types=["java.lang.Float","float","java.lang.Double","double","java.math.BigDecimal"]

mock_integer_or_float=${java_integer_types}.contains(it.type().name())?"@integer":"@float"

AssertTrue|AssertFalse|Email

field.mock[@javax.validation.constraints.AssertTrue]=true field.mock[@javax.validation.constraints.AssertFalse]=false field.mock[@javax.validation.constraints.Email]=groovy:"@email"

Positive&PositiveOrZero

field.mock[groovy:it.hasAnn("javax.validation.constraints.Positive")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(1,${number_max})" field.mock[groovy:it.hasAnn("javax.validation.constraints.PositiveOrZero")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(0,${number_max})" field.mock[groovy:it.hasAnn("javax.validation.constraints.Positive")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0.01,${number_max},${float_dmin})" field.mock[groovy:it.hasAnn("javax.validation.constraints.PositiveOrZero")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0,${number_max},${float_dmin})"

Negative&NegativeOrZero

field.mock[groovy:it.hasAnn("javax.validation.constraints.Negative")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(${number_min},-1)" field.mock[groovy:it.hasAnn("javax.validation.constraints.NegativeOrZero")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(${number_min},0)" field.mock[groovy:it.hasAnn("javax.validation.constraints.Negative")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(${number_min},0.01,${float_dmin})" field.mock[groovy:it.hasAnn("javax.validation.constraints.NegativeOrZero")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(${number_min},0,${float_dmin})"

Max+Min

field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&it.hasAnn("javax.validation.constraints.Min")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.Min")+","+it.ann("javax.validation.constraints.Max")+")" field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&it.hasAnn("javax.validation.constraints.Min")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.Min")+","+it.ann("javax.validation.constraints.Max")+",${float_dmin})"

Max|Min

field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(0,"+it.ann("javax.validation.constraints.Max")+")" field.mock[groovy:it.hasAnn("javax.validation.constraints.Min")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.Min")+")" field.mock[groovy:it.hasAnn("javax.validation.constraints.Max")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0,"+it.ann("javax.validation.constraints.Max")+")" field.mock[groovy:it.hasAnn("javax.validation.constraints.Min")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.Min")+")"

DecimalMax+DecimalMin

field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.DecimalMin")+","+it.ann("javax.validation.constraints.DecimalMax")+")" field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.DecimalMin")+","+it.ann("javax.validation.constraints.DecimalMax")+",${float_dmin})"

DecimalMax|DecimalMin

field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer(0,"+it.ann("javax.validation.constraints.DecimalMax")+")" field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_integer_types}.contains(it.jsonType().name())]=groovy:"@integer("+it.ann("javax.validation.constraints.DecimalMin")+")" field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMax")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float(0,"+it.ann("javax.validation.constraints.DecimalMax")+",${float_dmin})" field.mock[groovy:it.hasAnn("javax.validation.constraints.DecimalMin")&&${java_float_types}.contains(it.jsonType().name())]=groovy:"@float("+it.ann("javax.validation.constraints.DecimalMin")+",${float_dmin})" ###set resolveMulti = error #--------------------

@ConfigurationProperties

properties.prefix=@org.springframework.boot.context.properties.ConfigurationProperties#prefix #-------------------- #Support for Fastjson annotations [email protected]#value #-------------------- #enum auto select field by type enum.use.by.type=true

  1. Console output easy_api

    • Please set Preferences(Settings) > Other Settings > EasyApi > Common > log to `LOW```
  2. Logs of IDEA:

[TRACE] find config file:/Users/zhuangjiaju/IdeaProjects/ali-study/.easy.api.config [DEBUG] use recommend config [INFO] Start find apis... [TRACE] find config file:/Users/zhuangjiaju/IdeaProjects/ali-study/.easy.api.config [DEBUG] use recommend config [INFO] search api from: com.alibaba.study.controller.oauth.OauthController [INFO] Export to https://yapi.alibaba.com/project/217/interface/api/cat_1000558 success [WARN] can not resolve com.alibaba.study.api.enums.OauthSourceEnum for com.alibaba.study.controller.oauth.request.UnboundRequest#oauthSource [WARN] can not resolve com.alibaba.study.api.enums.RenderTypeEnum for com.alibaba.study.controller.oauth.request.OauthRequest#renderType [WARN] can not resolve com.alibaba.study.api.enums.OauthSourceEnum for com.alibaba.study.controller.oauth.request.OauthRequest#oauthSource [INFO] Apis exported completed

Add any other context about the problem here.

zhuangjiaju avatar Aug 01 '22 06:08 zhuangjiaju

你可能需要关闭: https://github.com/tangcent/easy-yapi/blob/ecebe4d9de62dfabcc8227e75abf8bfc825eb2db/idea-plugin/src/main/resources/.recommend.easy.api.config#L532

如果没有解决你的问题,可能需要提供一下你这个字段OauthRequest#oauthSource上的注释


这次加的特性是出于这种情况的考虑: http://easyyapi.com/setting/yapi-mock.html image


我不确定使用枚举名称的开发者多一些还是使用枚举中的一个字段的开发者多一些 Anyway, 我都会优化一下这里的提示。

tangcent avatar Aug 01 '22 08:08 tangcent

关闭 enum.use.by.type=true 就可以了。 但是还有一个疑问: /** * 授权来源 * * @see OauthSourceEnum#getCode() */ @NotNull(message = "授权来源不能为空") @IsEnum(enumType = OauthSourceEnum.class, message = "授权来源错误") private String oauthSource;

我的see 都是 后面跟方法的 是不是跟方法比较靠谱? 跟成员变量 显示红色的 比较丑陋。 image

跟方法就很好看 image

zhuangjiaju avatar Aug 01 '22 08:08 zhuangjiaju

我的see 都是 后面跟方法的 是不是跟方法比较靠谱?

是的,跟方法好看一点,我应该是做过兼容了,field/method都可以处理。如果跟方法无法解析的话,可以提一个BUG。

tangcent avatar Aug 01 '22 08:08 tangcent

哈哈 应该是不可以 我测试了下。 但是我关闭 enum.use.by.type=true 就符合我的预期了。

zhuangjiaju avatar Aug 01 '22 08:08 zhuangjiaju

应该是不可以

我试了一下,这里确实有个BUG。 这个BUG在命中单一方法时不会触发, 只存在于命中多个method时, 你这里正好由于继承的原因: getDescription命中了实现类和基类的两个方法。 你这里直接@see OauthSourceEnum#getDescription不加(), 能绕过这段错误的逻辑。


我一般是这样定义:


public class UserInfo {

    /**
     * @default 2
     * @see com.itangcent.common.constant.UserType
     */
    private int type;//用户类型

    /**
     * @default 2
     * @see UserType#getType()
     */
    private int userType;//用户类型

    /**
     * @default 2
     * @see UserType#getDesc
     */
    private String xxxx;//用户类型
}

然后导出结果是这样的:

image

tangcent avatar Aug 01 '22 22:08 tangcent

enum.use.by.type=true 我加没加此配置都不行

版本 image

备注 image

结果 控制台打印 image

liguanqiao avatar Aug 03 '22 09:08 liguanqiao

@liguanqiao 在Preferences(Settings) > Other Settings > EasyApi >Recommend最下面那行,取消选中。

tangcent avatar Aug 03 '22 12:08 tangcent

@tangcent 好的,取消选中后可行

liguanqiao avatar Aug 23 '22 07:08 liguanqiao