All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.fastjson2.internal.processor.Analysis Maven / Gradle / Ivy
package com.alibaba.fastjson2.internal.processor;
import com.alibaba.fastjson2.annotation.JSONCompiled;
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.annotation.JSONType;
import com.alibaba.fastjson2.codec.FieldInfo;
import com.alibaba.fastjson2.util.BeanUtils;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.*;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.*;
public class Analysis {
final ProcessingEnvironment processingEnv;
final Elements elements;
private final Types types;
final TypeElement jsonCompiledElement;
final TypeElement jsonTypeElement;
public final DeclaredType jsonCompiledDeclaredType;
public final DeclaredType jsonTypeDeclaredType;
final Map structs = new LinkedHashMap<>();
public Analysis(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
this.elements = processingEnv.getElementUtils();
this.types = processingEnv.getTypeUtils();
this.jsonCompiledElement = elements.getTypeElement(JSONCompiled.class.getName());
this.jsonCompiledDeclaredType = types.getDeclaredType(jsonCompiledElement);
this.jsonTypeElement = elements.getTypeElement(JSONType.class.getName());
this.jsonTypeDeclaredType = types.getDeclaredType(jsonTypeElement);
}
public void processAnnotation(DeclaredType currentAnnotationType, Set extends Element> targets) {
Stack path = new Stack<>();
for (Element el : targets) {
Element classElement;
ExecutableElement factory = null;
ExecutableElement builder = null;
if (el instanceof TypeElement) {
classElement = el;
} else if (el instanceof ExecutableElement && el.getKind() == ElementKind.METHOD) {
ExecutableElement ee = (ExecutableElement) el;
Element returnClass = types.asElement(ee.getReturnType());
Element enclosing = ee.getEnclosingElement();
if (!el.getModifiers().contains(Modifier.STATIC)
&& !types.isSameType(ee.getReturnType(), enclosing.asType())
&& returnClass.toString().equals(enclosing.getEnclosingElement().toString())) {
builder = ee;
}
factory = ee;
classElement = returnClass;
} else {
classElement = el.getEnclosingElement();
}
findStructs(classElement, currentAnnotationType, currentAnnotationType + " requires accessible public constructor", path, factory, builder);
}
}
private void findStructs(
Element el,
DeclaredType discoveredBy,
String errorMessage,
Stack path,
ExecutableElement factory,
ExecutableElement builder
) {
if (!(el instanceof TypeElement)) {
return;
}
String typeName = el.toString();
final TypeElement element = (TypeElement) el;
String name = "struct" + structs.size();
String binaryName = elements.getBinaryName(element).toString();
StructInfo info = new StructInfo(types, element, jsonCompiledDeclaredType, jsonTypeDeclaredType, name, binaryName);
structs.put(typeName, info);
}
static int getModifiers(Set modifiers) {
int modifierValue = 0;
for (Modifier modifier : modifiers) {
switch (modifier) {
case PUBLIC:
modifierValue |= java.lang.reflect.Modifier.PUBLIC;
break;
case PRIVATE:
modifierValue |= java.lang.reflect.Modifier.PRIVATE;
break;
case FINAL:
modifierValue |= java.lang.reflect.Modifier.FINAL;
break;
default:
break;
}
}
return modifierValue;
}
public Map analyze() {
findRelatedReferences();
return structs;
}
private void findRelatedReferences() {
for (Map.Entry entry : structs.entrySet()) {
StructInfo info = entry.getValue();
for (TypeElement inheritance : getTypeHierarchy(info.element)) {
for (VariableElement field : ElementFilter.fieldsIn(inheritance.getEnclosedElements())) {
Set modifiers = field.getModifiers();
if (modifiers.contains(Modifier.TRANSIENT)) {
continue;
}
if (modifiers.contains(Modifier.STATIC)) {
// TODO enum
continue;
}
FieldInfo fieldInfo = new FieldInfo();
String name = field.getSimpleName().toString();
JSONField[] annotations = field.getAnnotationsByType(JSONField.class);
for (JSONField annotation : annotations) {
CodeGenUtils.getFieldInfo(fieldInfo, annotation, false);
}
if (fieldInfo.fieldName != null) {
name = fieldInfo.fieldName;
}
info.getAttributeByField(name, field);
}
for (ExecutableElement method : ElementFilter.methodsIn(inheritance.getEnclosedElements())) {
List extends VariableElement> parameters = method.getParameters();
int parameterCount = parameters.size();
String methodName = method.getSimpleName().toString();
if (parameterCount > 2) {
continue;
}
boolean ignored = false;
if (parameterCount == 0) {
switch (methodName) {
case "hashCode":
ignored = true;
break;
default:
break;
}
} else if (parameterCount == 1) {
ignored = "equals".equals(methodName);
}
if (ignored) {
continue;
}
ExecutableElement getter = null, setter = null;
TypeMirror type = null;
String name = null;
if (parameters.size() == 0 && (methodName.startsWith("get") || methodName.startsWith("is"))) {
name = BeanUtils.getterName(methodName, null);
getter = method;
type = method.getReturnType();
} else if (methodName.startsWith("set") && method.getParameters().size() == 1) {
name = BeanUtils.setterName(methodName, null);
setter = method;
type = method.getParameters().get(0).asType();
} else {
continue;
}
AttributeInfo attr = info.getAttributeByMethod(name, type, getter, setter);
}
}
}
}
private List getTypeHierarchy(TypeElement element) {
List result = new ArrayList();
getAllTypes(element, result, new HashSet());
return result;
}
private void getAllTypes(TypeElement element, List result, Set processed) {
if (!processed.add(element) || element.getQualifiedName().contentEquals("java.lang.Object")) {
return;
}
result.add(element);
for (TypeMirror type : types.directSupertypes(element.asType())) {
Element current = types.asElement(type);
if (current instanceof TypeElement) {
getAllTypes((TypeElement) current, result, processed);
}
}
}
}