import com.sun.tools.javac.tree.TreeMaker; //導入方法依賴的package包/類
private JCMethodDecl createToString(JavacNode typeNode, List fields, boolean includeFieldNames, boolean callSuper, FieldAccess fieldAccess, JCTree source) {
TreeMaker maker = typeNode.getTreeMaker();
JCAnnotation overrideAnnotation = maker.Annotation(chainDots(typeNode, "java", "lang", "Override"), List.nil());
JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.of(overrideAnnotation));
JCExpression returnType = chainDots(typeNode, "java", "lang", "String");
boolean first = true;
String typeName = getTypeName(typeNode);
String infix = ", ";
String suffix = ")";
String prefix;
if (callSuper) {
prefix = typeName + "(super=";
} else if (fields.isEmpty()) {
prefix = typeName + "()";
} else if (includeFieldNames) {
prefix = typeName + "(" + ((JCVariableDecl)fields.iterator().next().get()).name.toString() + "=";
} else {
prefix = typeName + "(";
}
JCExpression current = maker.Literal(prefix);
if (callSuper) {
JCMethodInvocation callToSuper = maker.Apply(List.nil(),
maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("toString")),
List.nil());
current = maker.Binary(CTC_PLUS, current, callToSuper);
first = false;
}
for (JavacNode fieldNode : fields) {
JCExpression expr;
JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, fieldAccess);
JCExpression fieldType = getFieldType(fieldNode, fieldAccess);
// The distinction between primitive and object will be useful if we ever add a 'hideNulls' option.
boolean fieldIsPrimitive = fieldType instanceof JCPrimitiveTypeTree;
boolean fieldIsPrimitiveArray = fieldType instanceof JCArrayTypeTree && ((JCArrayTypeTree) fieldType).elemtype instanceof JCPrimitiveTypeTree;
boolean fieldIsObjectArray = !fieldIsPrimitiveArray && fieldType instanceof JCArrayTypeTree;
@SuppressWarnings("unused")
boolean fieldIsObject = !fieldIsPrimitive && !fieldIsPrimitiveArray && !fieldIsObjectArray;
if (fieldIsPrimitiveArray || fieldIsObjectArray) {
JCExpression tsMethod = chainDots(typeNode, "java", "util", "Arrays", fieldIsObjectArray ? "deepToString" : "toString");
expr = maker.Apply(List.nil(), tsMethod, List.of(fieldAccessor));
} else expr = fieldAccessor;
if (first) {
current = maker.Binary(CTC_PLUS, current, expr);
first = false;
continue;
}
if (includeFieldNames) {
current = maker.Binary(CTC_PLUS, current, maker.Literal(infix + fieldNode.getName() + "="));
} else {
current = maker.Binary(CTC_PLUS, current, maker.Literal(infix));
}
current = maker.Binary(CTC_PLUS, current, expr);
}
if (!first) current = maker.Binary(CTC_PLUS, current, maker.Literal(suffix));
JCStatement returnStatement = maker.Return(current);
JCBlock body = maker.Block(0, List.of(returnStatement));
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("toString"), returnType,
List.nil(), List.nil(), List.nil(), body, null), source);
}