diff --git a/README.md b/README.md index f595355..67f1349 100644 --- a/README.md +++ b/README.md @@ -3,18 +3,24 @@ [![Build Status](https://travis-ci.org/moyada/medivh.svg?branch=master)](https://travis-ci.org/moyada/medivh) ![version](https://img.shields.io/badge/java-%3E%3D6-red.svg) ![java lifecycle](https://img.shields.io/badge/java%20lifecycle-compile-yellow.svg) -[![Maven Central](https://img.shields.io/badge/maven%20central-0.1.2-brightgreen.svg)](https://search.maven.org/search?q=g:%22io.github.moyada%22%20AND%20a:%22medivh%22) +[![Maven Central](https://img.shields.io/badge/maven%20central-1.0.0-brightgreen.svg)](https://search.maven.org/search?q=g:%22io.github.moyada%22%20AND%20a:%22medivh%22) [![license](https://img.shields.io/hexpm/l/plug.svg)](https://github.com/moyada/medivh/blob/master/LICENSE) -A Java annotation processor, generate verification of method input by configuration rule. +[简体中文](README_CN.md) | English -[中文说明](README_CN.md) +A Java annotation processor, generate verify logic for method input by configuration rule. ## Features -* By modify the syntax tree at `compile time`, to adding verify logic of method input parameter. +* By modify the syntax tree at `compile time`, to adding verify logic for method input parameter. -* Supported types are primitives (such as int and Integer), String, Array, Collection, Map. +* Support null check for Object type. + +* Support range check for byte, short, int, long, float and double. + +* Support length check for String and array. + +* Support capacity check for Collection and Map. ## Requirement @@ -24,61 +30,59 @@ JDK 1.6 or higher. ### Adding dependencies to your project -#### Maven +Using Maven ``` io.github.moyada medivh - 0.1.2 + 1.0.0 provided ``` -#### Gradle +Using Gradle ``` dependencies { - compileOnly 'io.github.moyada:medivh:0.1.2' + compileOnly 'io.github.moyada:medivh:1.0.0' // or previous version - // provided 'io.github.moyada:medivh:0.1.2' + // provided 'io.github.moyada:medivh:1.0.0' } ``` -#### Without build tool - -You can download last jar from -[![release](https://img.shields.io/badge/release-v0.1.2-blue.svg)](https://github.com/moyada/medivh/releases/latest) +Without build tool, you can download last jar from +[![release](https://img.shields.io/badge/release-v1.0.0-blue.svg)](https://github.com/moyada/medivh/releases/latest) or [![Maven Central](https://img.shields.io/maven-central/v/io.github.moyada/medivh.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22io.github.moyada%22%20AND%20a:%22medivh%22) . ### Configure annotation in you program -An example of the use of annotations is [here](#Example). - -#### Annotation description +Annotation usage | Annotation Class | Action Scope | Effect | | :---- | :----- | :---- | | io.moyada.medivh.annotation.Rule | field | provide validate rule for enclose class. | | io.moyada.medivh.annotation.Verify | non-abstract method | enable verification function for this method. | -| io.moyada.medivh.annotation.Check | method parameter | configure check logic for method parameter,except the primitive type. | +| io.moyada.medivh.annotation.Check | method parameter | configure check logic for method parameter, except the primitive type. | -#### Annotation attribute +Attribute description | Attribute | Effect | | :--- | :--- | -| Rule.nullable() | indicates whether or not this field allowed to be null,except primitive type. | +| Rule.nullable() | indicates whether or not this field allowed to be null, except primitive type. | | Rule.min() | set the minimum allowed value of number type. | | Rule.max() | set the maximum allowed value of number type. | -| Rule.maxLength() | set the maximum allowed length or capacity of String, Array, Collection, Map. | +| Rule.maxLength() | set the maximum allowed length or capacity of String, Array, Collection and Map. | | Check.invalid() | set the exception thrown when the argument is invalid, the exception type must have a String constructor. | | Check.message() | message head of thrown exception. | | Check.nullable() | indicates whether or not this parameter allowed to be null. | -| Verify.value() | configure the name of temporary variable, generated by the verify logic. | +| Verify.var() | configure the name of temporary variable, generated by the verify logic. | + +* A use example is [here](#example). ### Compile project @@ -90,8 +94,9 @@ Or use java compile command, like `javac -cp medivh.jar MyApp.java`. | Property | Effect | | :--- | :--- | -| -Dmedivh.method | configure the name of validate method,default is invalid0 . | -| -Dmedivh.var | configure the name of default temporary variable,default is mvar_0 . | +| -Dmedivh.method | configure the name of validate method, default is invalid0 . | +| -Dmedivh.var | configure the name of default temporary variable, default is mvar_0 . | +| -Dmedivh.message | configure the default message head of exception, default is invalid argument . | After compilation phase, the verification logic will be generated. @@ -134,7 +139,7 @@ public class MyApp { } ``` -As the example code,the compiled content will be: +As the example code, the compiled content will be: ``` diff --git a/README_CN.md b/README_CN.md index 95b8bb4..cadaeed 100644 --- a/README_CN.md +++ b/README_CN.md @@ -3,16 +3,24 @@ [![Build Status](https://travis-ci.org/moyada/medivh.svg?branch=master)](https://travis-ci.org/moyada/medivh) ![version](https://img.shields.io/badge/java-%3E%3D6-red.svg) ![java lifecycle](https://img.shields.io/badge/java%20lifecycle-compile-yellow.svg) -[![Maven Central](https://img.shields.io/badge/maven%20central-0.1.2-brightgreen.svg)](https://search.maven.org/search?q=g:%22io.github.moyada%22%20AND%20a:%22medivh%22) +[![Maven Central](https://img.shields.io/badge/maven%20central-1.0.0-brightgreen.svg)](https://search.maven.org/search?q=g:%22io.github.moyada%22%20AND%20a:%22medivh%22) [![license](https://img.shields.io/hexpm/l/plug.svg)](https://github.com/moyada/medivh/blob/master/LICENSE) -Java 语言的注解处理器,根据配置规则生成方法的入参校验。 +简体中文 | [English](README.md) + +Java 的注解处理器,根据配置规则生成方法的入参校验逻辑。 ## 特性 * 通过在 `编译期` 对语法树进行修改,增加方法入参的校验逻辑。 -* 支持校验的属性有 基础类型 (如 int 和 Integer)、String、数组、集合、Map。 +* 支持 对象类型的非空校验。 + +* 支持 byte、short、int、long、float、double 的范围校验。 + +* 支持 String、数组的长度校验。 + +* 支持 集合、Map 的容量校验。 ## 要求 @@ -22,42 +30,38 @@ JDK 1.6 及以上版本。 ### 添加依赖 -#### Maven +使用 Maven ``` io.github.moyada medivh - 0.1.2 + 1.0.0 provided ``` -#### Gradle +使用 Gradle ``` dependencies { - compileOnly 'io.github.moyada:medivh:0.1.2' + compileOnly 'io.github.moyada:medivh:1.0.0' // 或历史版本方式 - // provided 'io.github.moyada:medivh:0.1.2' + // provided 'io.github.moyada:medivh:1.0.0' } ``` -#### 普通工程 - -可以通过 -[![release](https://img.shields.io/badge/release-v0.1.2-blue.svg)](https://github.com/moyada/medivh/releases/latest) +普通工程可以通过 +[![release](https://img.shields.io/badge/release-v1.0.0-blue.svg)](https://github.com/moyada/medivh/releases/latest) 或 [![Maven Central](https://img.shields.io/maven-central/v/io.github.moyada/medivh.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22io.github.moyada%22%20AND%20a:%22medivh%22) 下载最新 jar 包。 ### 在程序中配置注解 -注解的使用示例见[这里](#示例)。 - -#### 注解描述 +注解描述 | 注解类 | 作用域 | 作用 | | :---- | :----- | :---- | @@ -65,7 +69,7 @@ dependencies { | io.moyada.medivh.annotation.Verify | 非静态方法 | 开启方法的校验功能。 | | io.moyada.medivh.annotation.Check | 方法参数 | 配置参数的校验逻辑,基础类型无效。 | -#### 注解属性 +属性说明 | 属性 | 作用 | | :--- | :--- | @@ -76,7 +80,9 @@ dependencies { | Check.invalid() | 设置参数校验失败时抛出异常,异常类需要拥有字符串构造方法。 | | Check.message() | 异常信息头。 | | Check.nullable() | 设置方法参数是否允许为空。 | -| Verify.value() | 配置方法生成逻辑时产生的临时变量名称。 | +| Verify.var() | 配置方法生成逻辑时产生的临时变量名称。 | + +使用示例见[这里](#示例)。 ### 编译项目 @@ -84,12 +90,13 @@ dependencies { 或者使用 Java 命令进行编译,如 `javac -cp medivh.jar MyApp.java`。 -#### 可选系统参数 +#### 系统可选参数 | 参数 | 作用 | | :--- | :--- | | -Dmedivh.method | 配置校验方法名,默认为 invalid0 。 | | -Dmedivh.var | 配置默认临时变量名称,默认为 mvar_0 。 | +| -Dmedivh.message | 配置默认异常信息头,默认为 invalid argument 。 | 经过编译期后,即可生成校验逻辑。 @@ -105,8 +112,8 @@ public class MyApp { @Verify public void run(@Check(invalid = RuntimeException.class) Args args, @Check(message = "something error", nullable = true) Info info, - @Check String name, // can be check null value for normal Object - @Check int num // ineffective type + @Check String name, // 可以对普通对象进行非空检查 + @Check int num // 不支持基本类型 ) { // process ... diff --git a/pom.xml b/pom.xml index c41331b..52f5958 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ io.github.moyada medivh - 0.1.2 + 1.0.0-SNAPSHOT Medivh A Java annotation processor for automatic generate method verify at compile time. @@ -40,7 +40,7 @@ 3.0.1 3.0.1 1.6 - false + true diff --git a/src/main/java/io/moyada/medivh/annotation/Verify.java b/src/main/java/io/moyada/medivh/annotation/Verify.java index 392c3de..828bd53 100644 --- a/src/main/java/io/moyada/medivh/annotation/Verify.java +++ b/src/main/java/io/moyada/medivh/annotation/Verify.java @@ -17,5 +17,5 @@ /** * 临时对象名称 */ - String value() default Element.DEFAULT_VARIABLE_NAME; + String var() default Element.DEFAULT_VARIABLE_NAME; } diff --git a/src/main/java/io/moyada/medivh/translator/VerificationTranslator.java b/src/main/java/io/moyada/medivh/translator/VerificationTranslator.java index be8a92f..6eec629 100644 --- a/src/main/java/io/moyada/medivh/translator/VerificationTranslator.java +++ b/src/main/java/io/moyada/medivh/translator/VerificationTranslator.java @@ -30,9 +30,6 @@ **/ public class VerificationTranslator extends BaseTranslator { - // 默认前置信息 - private final static String DEFAULT_MESSAGE = "invalid argument"; - // 校验规则对象 private Collection ruleClass; @@ -45,17 +42,6 @@ public VerificationTranslator(Context context, Collection statements = CTreeUtil.newStatement(); @@ -101,8 +88,14 @@ public void visitMethodDef(JCTree.JCMethodDecl methodDecl) { } } - checkInfo = new CheckInfo(exception, annotation.message(), annotation.nullable()); - buildLogic(statements, ident, param, prefix, checkInfo); + String message = annotation.message(); + if (message.equals("")) { + message = Element.MESSAGE + actionInfo; + } else { + message += actionInfo; + } + checkInfo = new CheckInfo(exception, message, annotation.nullable()); + buildLogic(statements, ident, param, checkInfo); } List oldStatements = methodDecl.body.stats; @@ -158,14 +151,11 @@ private String getException(List ms) { * @param statements * @param ident * @param param - * @param method * @param checkInfo * @return */ - private void buildLogic(ListBuffer statements, - JCTree.JCIdent ident, - JCTree.JCVariableDecl param, - String method, CheckInfo checkInfo) { + private void buildLogic(ListBuffer statements, JCTree.JCIdent ident, + JCTree.JCVariableDecl param, CheckInfo checkInfo) { // 获取参数引用 JCTree.JCIdent var = treeMaker.Ident(param.name); @@ -175,11 +165,11 @@ private void buildLogic(ListBuffer statements, } if (!checkInfo.nullable) { - addNotNullCheck(statements, var, method, checkInfo); + addNotNullCheck(statements, var, checkInfo); } if (ruleClass.contains(name)) { - addInvalidStatement(statements, ident, var, method, checkInfo); + addInvalidStatement(statements, ident, var, checkInfo); } } @@ -188,19 +178,17 @@ private void buildLogic(ListBuffer statements, * @param statements * @param ident * @param field - * @param method * @param info * @return */ - private void addInvalidStatement(ListBuffer statements, - JCTree.JCIdent ident, - JCTree.JCIdent field, String method, CheckInfo info) { + private void addInvalidStatement(ListBuffer statements, JCTree.JCIdent ident, + JCTree.JCIdent field, CheckInfo info) { // 将校验结果赋值给临时变量 JCTree.JCExpression expression = getMethod(field, Element.METHOD_NAME, CTreeUtil.emptyParam()); JCTree.JCExpressionStatement exec = execMethod(treeMaker.Assign(ident, expression)); // 抛出异常语句 - JCTree.JCMethodInvocation message = concatStatement(ident, method, info.info); + JCTree.JCMethodInvocation message = concatStatement(ident, info.info); JCTree.JCStatement throwStatement = newMsgThrow(message, info.exceptionName); @@ -226,31 +214,27 @@ private void addInvalidStatement(ListBuffer statements, * 添加非空校验 * @param statements * @param field - * @param method * @param info * @return */ - private void addNotNullCheck(ListBuffer statements, JCTree.JCIdent field, - String method, CheckInfo info) { + private void addNotNullCheck(ListBuffer statements, JCTree.JCIdent field, CheckInfo info) { JCTree.JCExpression check = CTreeUtil.newExpression(treeMaker, TypeTag.EQ, field, nullNode); - JCTree.JCLiteral msg = CTreeUtil.newElement(treeMaker, TypeTag.CLASS, field.name + " is null"); - JCTree.JCMethodInvocation message = concatStatement(msg, method, info.info); + JCTree.JCLiteral message = CTreeUtil.newElement(treeMaker, TypeTag.CLASS, info.info + field.name + " is null"); + // JCTree.JCMethodInvocation message = concatStatement(msg, info.info); JCTree.JCStatement throwStatement = newMsgThrow(message, info.exceptionName); statements.append(treeMaker.If(check, throwStatement, null)); } /** - * 并且信息 + * 拼接信息 * @param info - * @param method * @param message * @return */ - private JCTree.JCMethodInvocation concatStatement(JCTree.JCExpression info, String method, String message) { - JCTree.JCExpression args = treeMaker.Literal(message.equals("") ? - DEFAULT_MESSAGE + method : message + method); + private JCTree.JCMethodInvocation concatStatement(JCTree.JCExpression info, String message) { + JCTree.JCExpression args = treeMaker.Literal(message); return getMethod(args, "concat", List.of(info)); } diff --git a/src/main/java/io/moyada/medivh/util/CTreeUtil.java b/src/main/java/io/moyada/medivh/util/CTreeUtil.java index 4c787d5..298fc24 100644 --- a/src/main/java/io/moyada/medivh/util/CTreeUtil.java +++ b/src/main/java/io/moyada/medivh/util/CTreeUtil.java @@ -22,6 +22,20 @@ public static ListBuffer newStatement(){ return new ListBuffer(); } + /** + * 创建方法的报错信息来源 + * @param methodDecl + * @return + */ + public static String getActionInfo(JCTree.JCMethodDecl methodDecl) { + String className = getOriginalTypeName(methodDecl.sym.getEnclosingElement()); + String methodName = methodDecl.name.toString(); + return " while attempting to access " + className + "." + methodName + "(), cause "; + } + public static String getActionInfo() { + return ", cause "; + } + /** * 获取实际类型名 * @param symbol diff --git a/src/main/java/io/moyada/medivh/util/Element.java b/src/main/java/io/moyada/medivh/util/Element.java index a805adc..d3aba24 100644 --- a/src/main/java/io/moyada/medivh/util/Element.java +++ b/src/main/java/io/moyada/medivh/util/Element.java @@ -19,9 +19,18 @@ public class Element { // 默认临时变量名 public static final String DEFAULT_VARIABLE_NAME = "mvar_0"; + // 异常信息头配置 + private static final String MESSAGE_KEY = "medivh.message"; + + // 默认异常信息头 + private static final String DEFAULT_MESSAGE = "Invalid input parameter"; + // 临时变量参数 public final static String LOCAL_VARIABLE = SystemUtil.getProperty(VARIABLE_KEY, DEFAULT_VARIABLE_NAME); // 方法名称 public final static String METHOD_NAME = SystemUtil.getProperty(METHOD_KEY, DEFAULT_METHOD_NAME); + + // 异常信息头 + public final static String MESSAGE = SystemUtil.getProperty(MESSAGE_KEY, DEFAULT_MESSAGE); } diff --git a/src/main/java/io/moyada/medivh/util/SystemUtil.java b/src/main/java/io/moyada/medivh/util/SystemUtil.java index 7ae3534..60569be 100644 --- a/src/main/java/io/moyada/medivh/util/SystemUtil.java +++ b/src/main/java/io/moyada/medivh/util/SystemUtil.java @@ -28,7 +28,7 @@ public static String getProperty(String key, String defaultValue) { * @return */ public static String getTmpVar(Verify verify) { - String var = verify.value(); + String var = verify.var(); if (var.isEmpty()) { return Element.LOCAL_VARIABLE; }