cn.wjybxx.dsonapt.SchemaGenerator Maven / Gradle / Ivy
/*
* Copyright 2023-2024 wjybxx([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.wjybxx.dsonapt;
import cn.wjybxx.apt.AbstractGenerator;
import cn.wjybxx.apt.AptUtils;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.*;
import javax.tools.Diagnostic;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 方法对象
*
* @author wjybxx
* date - 2023/12/10
*/
class SchemaGenerator extends AbstractGenerator {
private final Context context;
private final ClassName typeInfoRawTypeName;
public SchemaGenerator(CodecProcessor processor, Context context) {
super(processor, context.typeElement);
this.context = context;
this.typeInfoRawTypeName = processor.typeNameTypeInfo;
}
@Override
public void execute() {
final List allSerialFields = context.dsonSerialFields;
final List allAptTypeInfos = new ArrayList<>(allSerialFields.size());
for (VariableElement variableElement : allSerialFields) {
allAptTypeInfos.add(parseTypeArgMirrors(variableElement));
}
final List typesFields = genTypeFields(allSerialFields, allAptTypeInfos);
final List factoryFields = genFactoryFields(allSerialFields, allAptTypeInfos);
final List namesSpec = genNames();
context.typeBuilder.addFields(typesFields)
.addFields(factoryFields)
.addFields(namesSpec);
}
// region typeArgs
private List genTypeFields(List allSerialFields, List allAptTypeInfos) {
List typeFieldList = new ArrayList<>(allSerialFields.size() * 2);
for (int i = 0; i < allSerialFields.size(); i++) {
VariableElement variableElement = allSerialFields.get(i);
AptTypeInfo aptTypeInfo = allAptTypeInfos.get(i);
typeFieldList.add(genTypeField(variableElement, aptTypeInfo));
}
return typeFieldList;
}
private List genFactoryFields(List allSerialFields, List allAptTypeInfos) {
List typeFieldList = new ArrayList<>(allSerialFields.size() * 2);
for (int i = 0; i < allSerialFields.size(); i++) {
VariableElement variableElement = allSerialFields.get(i);
AptTypeInfo aptTypeInfo = allAptTypeInfos.get(i);
if (aptTypeInfo.impl != null) {
typeFieldList.add(genFactoryField(variableElement, aptTypeInfo));
}
}
return typeFieldList;
}
private FieldSpec genFactoryField(VariableElement variableElement, AptTypeInfo aptTypeInfo) {
// 暂不擦除泛型 -- 我们约定禁止字段出现未定义泛型,如:List
ParameterizedTypeName fieldTypeName = ParameterizedTypeName.get(AptUtils.CLSNAME_SUPPLIER,
TypeName.get(variableElement.asType()));
String filedName = "factories_" + variableElement.getSimpleName().toString();
FieldSpec.Builder builder = FieldSpec.builder(fieldTypeName, filedName, AptUtils.PUBLIC_STATIC_FINAL);
if (aptTypeInfo.type == AptTypeInfo.TYPE_MAP) {
if (processor.isEnumMap(aptTypeInfo.impl)) {
builder.initializer("() -> new EnumMap<>($T.class)",
TypeName.get(typeUtils.erasure(aptTypeInfo.typeArgs.get(0))));
} else {
builder.initializer("$T::new",
TypeName.get(typeUtils.erasure(aptTypeInfo.impl)));
}
} else if (aptTypeInfo.type == AptTypeInfo.TYPE_COLLECTION) {
if (processor.isEnumSet(aptTypeInfo.impl)) {
builder.initializer("() -> EnumSet.noneOf($T.class)",
TypeName.get(typeUtils.erasure(aptTypeInfo.typeArgs.get(0))));
} else {
builder.initializer("$T::new",
TypeName.get(typeUtils.erasure(aptTypeInfo.impl)));
}
} else {
// 其它类型字段
builder.initializer("$T::new",
TypeName.get(typeUtils.erasure(aptTypeInfo.impl)));
}
return builder.build();
}
private FieldSpec genTypeField(VariableElement variableElement, AptTypeInfo aptTypeInfo) {
ParameterizedTypeName fieldTypeName;
if (variableElement.asType().getKind().isPrimitive()) {
// 基础类型不能做泛型参数...
fieldTypeName = ParameterizedTypeName.get(typeInfoRawTypeName,
TypeName.get(variableElement.asType()).box());
} else {
// TypeInfo的泛型T最好不带泛型参数,兼容性很差
fieldTypeName = ParameterizedTypeName.get(typeInfoRawTypeName,
TypeName.get(typeUtils.erasure(variableElement.asType())));
}
String filedName = "types_" + variableElement.getSimpleName().toString();
FieldSpec.Builder builder = FieldSpec.builder(fieldTypeName, filedName, AptUtils.PUBLIC_STATIC_FINAL);
switch (aptTypeInfo.typeArgs.size()) {
case 0: {
builder.initializer("$T.of($T.class)",
typeInfoRawTypeName,
TypeName.get(typeUtils.erasure(aptTypeInfo.declared)));
break;
}
case 1: {
builder.initializer("$T.of($T.class, $T.class)",
typeInfoRawTypeName,
TypeName.get(typeUtils.erasure(aptTypeInfo.declared)),
TypeName.get(typeUtils.erasure(aptTypeInfo.typeArgs.get(0))));
break;
}
case 2: {
builder.initializer("$T.of($T.class, $T.class, $T.class)",
typeInfoRawTypeName,
TypeName.get(typeUtils.erasure(aptTypeInfo.declared)),
TypeName.get(typeUtils.erasure(aptTypeInfo.typeArgs.get(0))),
TypeName.get(typeUtils.erasure(aptTypeInfo.typeArgs.get(1))));
break;
}
default: {
// 超过2个泛型参数时,使用List.of
StringBuilder format = new StringBuilder("$T.of($T.class, List.Of(");
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy