use of org.codehaus.groovy.classgen.VerifierCodeVisitor in project groovy by apache.
the class JavaStubGenerator method printClassContents.
private void printClassContents(PrintWriter out, ClassNode classNode) {
if (classNode instanceof InnerClassNode && ((InnerClassNode) classNode).isAnonymous()) {
// if it is an anonymous inner class, don't generate the stub code for it.
return;
}
try {
Verifier verifier = new Verifier() {
@Override
public void visitClass(ClassNode node) {
List<Statement> savedStatements = new ArrayList<>(node.getObjectInitializerStatements());
super.visitClass(node);
node.getObjectInitializerStatements().addAll(savedStatements);
for (ClassNode trait : findTraits(node)) {
// GROOVY-9031: replace property type placeholder with resolved type from trait generics
Map<String, ClassNode> generics = trait.isUsingGenerics() ? createGenericsSpec(trait) : null;
for (PropertyNode traitProperty : trait.getProperties()) {
ClassNode traitPropertyType = traitProperty.getType();
traitProperty.setType(correctToGenericsSpecRecurse(generics, traitPropertyType));
super.visitProperty(traitProperty);
traitProperty.setType(traitPropertyType);
}
}
}
@Override
public void visitConstructor(ConstructorNode node) {
Statement stmt = node.getCode();
if (stmt != null) {
stmt.visit(new VerifierCodeVisitor(getClassNode()));
}
}
@Override
public void visitProperty(PropertyNode node) {
// GROOVY-8233 skip static properties for traits since they don't make the interface
if (!node.isStatic() || !Traits.isTrait(node.getDeclaringClass())) {
super.visitProperty(node);
}
}
@Override
public void addCovariantMethods(ClassNode cn) {
}
@Override
protected void addInitialization(ClassNode node) {
}
@Override
protected void addPropertyMethod(MethodNode method) {
doAddMethod(method);
}
@Override
protected void addReturnIfNeeded(MethodNode node) {
}
@Override
protected MethodNode addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
return doAddMethod(new MethodNode(name, modifiers, returnType, parameters, exceptions, code));
}
@Override
protected void addConstructor(Parameter[] newParams, ConstructorNode ctor, Statement code, ClassNode node) {
if (code instanceof ExpressionStatement) {
// GROOVY-4508
Statement temp = code;
code = new BlockStatement();
((BlockStatement) code).addStatement(temp);
}
ConstructorNode ctrNode = new ConstructorNode(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
ctrNode.setDeclaringClass(node);
constructors.add(ctrNode);
}
@Override
protected void addDefaultParameters(DefaultArgsAction action, MethodNode method) {
final Parameter[] parameters = method.getParameters();
final Expression[] saved = new Expression[parameters.length];
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].hasInitialExpression())
saved[i] = parameters[i].getInitialExpression();
}
super.addDefaultParameters(action, method);
for (int i = 0; i < parameters.length; i++) {
if (saved[i] != null)
parameters[i].setInitialExpression(saved[i]);
}
}
private MethodNode doAddMethod(MethodNode method) {
String sig = method.getTypeDescriptor();
if (propertyMethodsWithSigs.containsKey(sig))
return method;
propertyMethods.add(method);
propertyMethodsWithSigs.put(sig, method);
return method;
}
@Override
protected void addDefaultConstructor(ClassNode node) {
// not required for stub generation
}
@Override
protected FinalVariableAnalyzer.VariableNotFinalCallback getFinalVariablesCallback() {
return null;
}
};
int origNumConstructors = classNode.getDeclaredConstructors().size();
verifier.visitClass(classNode);
// undo unwanted side-effect of verifier
if (origNumConstructors == 0 && classNode.getDeclaredConstructors().size() == 1) {
classNode.getDeclaredConstructors().clear();
}
boolean isInterface = isInterfaceOrTrait(classNode);
boolean isEnum = classNode.isEnum();
boolean isAnnotationDefinition = classNode.isAnnotationDefinition();
printAnnotations(out, classNode);
printModifiers(out, classNode.getModifiers() & ~(isInterface ? Opcodes.ACC_ABSTRACT : 0) & ~(isEnum ? Opcodes.ACC_FINAL | Opcodes.ACC_ABSTRACT : 0));
if (isInterface) {
if (isAnnotationDefinition) {
out.print("@");
}
out.print("interface ");
} else if (isEnum) {
out.print("enum ");
} else {
out.print("class ");
}
String className = classNode.getNameWithoutPackage();
if (classNode instanceof InnerClassNode)
className = className.substring(className.lastIndexOf('$') + 1);
out.println(className);
printGenericsBounds(out, classNode, true);
ClassNode superClass = classNode.getUnresolvedSuperClass(false);
if (!isInterface && !isEnum) {
out.print(" extends ");
printType(out, superClass);
}
ClassNode[] interfaces = classNode.getInterfaces();
if (interfaces != null && interfaces.length > 0 && !isAnnotationDefinition) {
if (isInterface) {
out.println(" extends");
} else {
out.println(" implements");
}
for (int i = 0; i < interfaces.length - 1; ++i) {
out.print(" ");
printType(out, interfaces[i]);
out.print(",");
}
out.print(" ");
printType(out, interfaces[interfaces.length - 1]);
}
out.println(" {");
printFields(out, classNode);
printMethods(out, classNode, isEnum);
for (Iterator<InnerClassNode> inner = classNode.getInnerClasses(); inner.hasNext(); ) {
// GROOVY-4004: Clear the methods from the outer class so that they don't get duplicated in inner ones
propertyMethods.clear();
propertyMethodsWithSigs.clear();
constructors.clear();
printClassContents(out, inner.next());
}
out.println("}");
} finally {
propertyMethods.clear();
propertyMethodsWithSigs.clear();
constructors.clear();
}
}
Aggregations