Skip to content

Commit

Permalink
[Feature] add for new
Browse files Browse the repository at this point in the history
  • Loading branch information
binbin.hou committed Jun 4, 2020
1 parent bc4bd1c commit e7daa62
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 11 deletions.
1 change: 0 additions & 1 deletion pom.xml
Expand Up @@ -62,7 +62,6 @@
<artifactId>tools</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<optional>true</optional>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>

Expand Down
@@ -1,15 +1,24 @@
package com.github.houbb.lombok.ex.annotation;

import com.github.houbb.lombok.ex.constant.ToStringType;

import java.lang.annotation.*;

/**
* 注解
* @author binbin.hou
* @since 0.0.4
* @see com.github.houbb.lombok.ex.support.tostring.IToString 字符串构建策略,后续添加这个拓展
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@Documented
public @interface ToString {

/**
* 转换为字符串的实现方式
* @return 实现方式
* @since 0.0.6
*/
ToStringType value() default ToStringType.CONCAT;

}
@@ -0,0 +1,22 @@
package com.github.houbb.lombok.ex.constant;

/**
* @author binbin.hou
* @since 0.0.6
*/
public enum ToStringType {

/**
* 基于 fastJson 实现
* @since 0.0.6
*/
FAST_JSON,

/**
* 字符串拼接
* @since 0.0.6
*/
CONCAT,

;
}
@@ -1,11 +1,15 @@
package com.github.houbb.lombok.ex.processor;

import com.alibaba.fastjson.JSON;
import com.github.houbb.lombok.ex.annotation.Serial;
import com.github.houbb.lombok.ex.annotation.ToString;
import com.github.houbb.lombok.ex.constant.ClassConst;
import com.github.houbb.lombok.ex.constant.LombokExConst;
import com.github.houbb.lombok.ex.constant.ToStringType;
import com.github.houbb.lombok.ex.metadata.LClass;
import com.github.houbb.lombok.ex.support.tostring.IToString;
import com.github.houbb.lombok.ex.support.tostring.impl.ToStringFastJson;
import com.sun.source.tree.Tree;
import com.sun.source.util.SimpleTreeVisitor;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
Expand All @@ -20,6 +24,7 @@
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import java.lang.annotation.Annotation;
import java.util.Arrays;

/**
*
Expand All @@ -38,11 +43,6 @@ protected Class<? extends Annotation> getAnnotationClass() {

@Override
protected void handleClass(LClass lClass) {
//1. 导包
lClass.importPackage(lClass, JSON.class);
lClass.importPackage(lClass, ToStringFastJson.class);

//2. 插入方法
if(!lClass.containsMethod(LombokExConst.TO_STRING)) {
generateToStringMethod(lClass);
}
Expand Down Expand Up @@ -74,9 +74,10 @@ private void generateToStringMethod(LClass lClass) {
// 新增一个方法
final JCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);
Name name = names.fromString(LombokExConst.TO_STRING);

// 表达式
// 这里缺少了 @Override 注解
List<JCTree.JCStatement> statements = List.of(createJSONString());
List<JCTree.JCStatement> statements = createToStringStatements(lClass);

JCTree.JCBlock jcBlock = treeMaker.Block(0, statements);
JCTree.JCExpression restype = treeMaker.Ident(names.fromString("String"));
Expand All @@ -96,6 +97,26 @@ private void generateToStringMethod(LClass lClass) {
lClass.classDecl().defs = defBufferList.toList();
}

/**
* 构建 toString() 语句
* @param lClass 类
* @return 结果
* @since 0.0.1
*/
@SuppressWarnings("unchecked")
private List<JCTree.JCStatement> createToStringStatements(final LClass lClass) {
// 获取注解对应的值
ToString toString = lClass.classSymbol().getAnnotation(ToString.class);
ToStringType type = toString.value();

if(ToStringType.FAST_JSON.equals(type)) {
return createFastJsonStatements(lClass);
}

// 基于字符串拼接的实现
return createStringConcatStatements(lClass);
}

/**
* 创建
*
Expand All @@ -104,11 +125,14 @@ private void generateToStringMethod(LClass lClass) {
* </pre>
*
* 待完善的地方:
*
* JSON 可能会有重名,后期可以拓展一下。
* @return 0.0.4
*/
private JCTree.JCStatement createJSONString() {
private List<JCTree.JCStatement> createFastJsonStatements(final LClass lClass) {
//1. 导包
lClass.importPackage(lClass, JSON.class);

//2. 构建 statement
JCTree.JCFieldAccess fieldAccess = treeMaker.Select(treeMaker.Ident(names.fromString("JSON")),
names.fromString("toJSONString"));
// 避免类型擦除
Expand All @@ -117,7 +141,99 @@ private JCTree.JCStatement createJSONString() {
JCTree.JCMethodInvocation methodInvocation = treeMaker.Apply(List.<JCTree.JCExpression>nil(),
fieldAccess, identBuffers.toList());

return treeMaker.Return(methodInvocation);
JCTree.JCStatement statement = treeMaker.Return(methodInvocation);
return List.of(statement);
}

/**
* 创建
*
* 遍历字段,拼接。
*
* <pre>
*
* </pre>
*
* 待完善的地方:
* JSON 可能会有重名,后期可以拓展一下。
* @return 0.0.6
*/
private List<JCTree.JCStatement> createStringConcatStatements(final LClass lClass) {
String fullClassName = lClass.classSymbol().fullname.toString();
String className = fullClassName.substring(fullClassName.lastIndexOf('.') + 1);

//2. 构建 statement
// 所有的字符串都是一个 Literal
JCTree.JCLiteral start = treeMaker.Literal(className+"{");
// 输出字段信息
JCTree.JCBinary lhs = null;

// TODO: 这里不同的 JDK 版本不兼容
final JCTree.Tag tag = JCTree.Tag.PLUS;
for(JCTree jcTree : lClass.classDecl().defs) {
if(jcTree.getKind() == Tree.Kind.VARIABLE) {
JCTree.JCVariableDecl variableDecl = (JCTree.JCVariableDecl) jcTree;
String varName = variableDecl.name.toString();


// 初次加載
if(lhs == null) {
JCTree.JCLiteral fieldName = treeMaker.Literal(varName+"=");
lhs = treeMaker.Binary(tag, start, fieldName);
} else {
JCTree.JCLiteral fieldName = treeMaker.Literal(", "+varName+"=");
lhs = treeMaker.Binary(tag, lhs, fieldName);
}

// 类型为 String 可以考虑加单引号,但是没必要。,判断逻辑比较麻烦
String typeName = variableDecl.vartype.toString();
if(typeName.endsWith("[]")) {
JCTree.JCMethodInvocation methodInvocation = buildArraysToString(lClass, varName);
lhs = treeMaker.Binary(tag, lhs, methodInvocation);
} else {
// 默认直接使用字符串
JCTree.JCIdent fieldValue = treeMaker.Ident(names.fromString(varName));
lhs = treeMaker.Binary(tag, lhs, fieldValue);
}
}
}

JCTree.JCLiteral rhs = treeMaker.Literal("}");
JCTree.JCBinary binary = treeMaker.Binary(tag, lhs, rhs);
JCTree.JCStatement statement = treeMaker.Return(binary);
return List.of(statement);
}

/**
* 构建数组调用
*
* <pre>
* Arrays.toString("xxx");
* </pre>
* @param lClass 类
* @param varName 命名
* @return 结果
* @since 0.0.6
*/
private JCTree.JCMethodInvocation buildArraysToString(final LClass lClass,
final String varName) {
lClass.importPackage(lClass, Arrays.class);

//2. 构建 statement
JCTree.JCFieldAccess fieldAccess = treeMaker.Select(treeMaker.Ident(names.fromString("Arrays")), names.fromString("toString"));
// 避免类型擦除
ListBuffer<JCTree.JCExpression> identBuffers = new ListBuffer<>();
identBuffers.add(treeMaker.Ident(names.fromString(varName)));

return treeMaker.Apply(List.<JCTree.JCExpression>nil(),
fieldAccess, identBuffers.toList());
}
public static void main(String[] args) {
for(JCTree.Tag tag : JCTree.Tag.values()) {
if(71 == tag.ordinal()) {
System.out.println(tag);
}
}
}

}
@@ -0,0 +1,19 @@
package com.github.houbb.lombok.ex.support.tostring.impl;

import com.github.houbb.heaven.annotation.ThreadSafe;
import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.lombok.ex.support.tostring.IToString;

/**
* @author binbin.hou
* @since 0.0.6
*/
@ThreadSafe
public class ToStringDefault implements IToString {

@Override
public String toString(Object instance) {
return StringUtil.EMPTY;
}

}
@@ -1,12 +1,14 @@
package com.github.houbb.lombok.ex.support.tostring.impl;

import com.alibaba.fastjson.JSON;
import com.github.houbb.heaven.annotation.ThreadSafe;
import com.github.houbb.lombok.ex.support.tostring.IToString;

/**
* @author binbin.hou
* @since 0.0.4
*/
@ThreadSafe
public class ToStringFastJson implements IToString {

@Override
Expand Down
@@ -0,0 +1,102 @@
package com.github.houbb.lombok.ex.util;

import com.github.houbb.heaven.annotation.CommonEager;
import com.github.houbb.heaven.constant.PunctuationConst;
import com.github.houbb.heaven.support.tuple.impl.Pair;
import com.github.houbb.heaven.util.common.ArgUtil;
import com.github.houbb.heaven.util.guava.Guavas;
import com.github.houbb.heaven.util.lang.StringUtil;
import com.github.houbb.heaven.util.lang.reflect.ClassTypeUtil;

import java.util.Arrays;
import java.util.List;

/**
* @author binbin.hou
* @since 0.0.6
*/
@Deprecated
public class LombokExStringConcatUtil {

private LombokExStringConcatUtil(){}


/**
* 进行字符串的连接
*
* <pre>
* return "ToStringConcatTest{" +
* "name='" + name + '\'' +
* ", age=" + age +
* ", ints=" + Arrays.toString(ints) +
* '}';
* </pre>
* @param className 类名
* @param fieldPairs 字段列表
* @return 结果
* @since 0.0.6
*/
public static String concat(final String className,
final List<Pair<String, Object>> fieldPairs){

ArgUtil.notEmpty(className, "className");

StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(className).append("{");

// 具体细节可以不断优化,初期可以简单些。
List<String> fieldInfoList = Guavas.newArrayList(fieldPairs.size());
for(Pair<String, Object> pair : fieldPairs) {
String fieldName = pair.getValueOne();
Object fieldValue = pair.getValueTwo();

String fieldValueStr = objectToConcatString(fieldValue);
fieldInfoList.add(fieldName+"="+fieldValueStr);
}
String fieldInfoStr = StringUtil.join(fieldInfoList, PunctuationConst.COMMA);
stringBuilder.append(fieldInfoStr);
stringBuilder.append("}");
return stringBuilder.toString();
}

/**
* 转换为 toString() 的方法
* @param object 对象
* @return 结果
* @since 0.0.5
*/
@CommonEager
private static String objectToConcatString(final Object object) {
if(null == object) {
return "null";
}

final Class type = object.getClass();
if(ClassTypeUtil.isArray(type)) {
// 这里添加各种不同的类型处理
if(int[].class == type) {
return Arrays.toString((boolean[]) object);
} else if(byte[].class == type) {
return Arrays.toString((boolean[]) object);
} else if(char[].class == type) {
return Arrays.toString((char[]) object);
} else if(boolean[].class == type) {
return Arrays.toString((boolean[]) object);
} else if(float[].class == type) {
return Arrays.toString((float[]) object);
} else if(double[].class == type) {
return Arrays.toString((double[]) object);
} else if(short[].class == type) {
return Arrays.toString((short[]) object);
} else if(long[].class == type) {
return Arrays.toString((long[]) object);
}

// 默认是对象数组
return Arrays.toString((Object[]) object);
}

return object.toString();
}

}

0 comments on commit e7daa62

Please sign in to comment.