use of org.codehaus.groovy.ast.InnerClassNode in project groovy by apache.
the class EnumHelper method makeEnumNode.
public static ClassNode makeEnumNode(String name, int modifiers, ClassNode[] interfaces, ClassNode outerClass) {
modifiers = modifiers | Opcodes.ACC_FINAL | Opcodes.ACC_ENUM;
ClassNode enumClass;
if (outerClass == null) {
enumClass = new ClassNode(name, modifiers, null, interfaces, MixinNode.EMPTY_ARRAY);
} else {
name = outerClass.getName() + "$" + name;
modifiers |= Opcodes.ACC_STATIC;
enumClass = new InnerClassNode(outerClass, name, modifiers, null, interfaces, MixinNode.EMPTY_ARRAY);
}
// set super class and generics info
// "enum X" -> class X extends Enum<X>
GenericsType gt = new GenericsType(enumClass);
ClassNode superClass = ClassHelper.makeWithoutCaching("java.lang.Enum");
superClass.setGenericsTypes(new GenericsType[] { gt });
enumClass.setSuperClass(superClass);
superClass.setRedirect(ClassHelper.Enum_Type);
return enumClass;
}
use of org.codehaus.groovy.ast.InnerClassNode 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();
}
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy by apache.
the class MacroGroovyMethods method buildSubstitutions.
public static ListExpression buildSubstitutions(final SourceUnit source, final ASTNode expr) {
final ListExpression listExpression = new ListExpression();
ClassCodeVisitorSupport visitor = new ClassCodeVisitorSupport() {
@Override
protected SourceUnit getSourceUnit() {
return null;
}
@Override
public void visitClass(final ClassNode node) {
super.visitClass(node);
Iterator<InnerClassNode> it = node.getInnerClasses();
while (it.hasNext()) {
InnerClassNode next = it.next();
visitClass(next);
}
}
@Override
public void visitMethodCallExpression(MethodCallExpression call) {
super.visitMethodCallExpression(call);
if (DOLLAR_VALUE.equals(call.getMethodAsString())) {
ClosureExpression substitutionClosureExpression = getClosureArgument(source, call);
if (substitutionClosureExpression == null) {
return;
}
Statement code = substitutionClosureExpression.getCode();
if (code instanceof BlockStatement) {
((BlockStatement) code).setVariableScope(null);
}
listExpression.addExpression(substitutionClosureExpression);
}
}
};
if (expr instanceof ClassNode) {
visitor.visitClass((ClassNode) expr);
} else {
expr.visit(visitor);
}
return listExpression;
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy by apache.
the class ResolveVisitor method checkThisAndSuperAsPropertyAccess.
private void checkThisAndSuperAsPropertyAccess(final PropertyExpression expression) {
if (expression.isImplicitThis())
return;
String prop = expression.getPropertyAsString();
if (prop == null)
return;
if (!prop.equals("this") && !prop.equals("super"))
return;
ClassNode type = expression.getObjectExpression().getType();
if (expression.getObjectExpression() instanceof ClassExpression) {
if (!(currentClass instanceof InnerClassNode) && !Traits.isTrait(type)) {
addError("The usage of 'Class.this' and 'Class.super' is only allowed in nested/inner classes.", expression);
return;
}
if (currentScope != null && !currentScope.isInStaticContext() && Traits.isTrait(type) && "super".equals(prop) && directlyImplementsTrait(type)) {
return;
}
ClassNode iterType = currentClass;
while (iterType != null) {
if (iterType.equals(type))
break;
iterType = iterType.getOuterClass();
}
if (iterType == null) {
addError("The class '" + type.getName() + "' needs to be an outer class of '" + currentClass.getName() + "' when using '.this' or '.super'.", expression);
}
if (!Modifier.isStatic(currentClass.getModifiers()))
return;
if (currentScope != null && !currentScope.isInStaticContext())
return;
addError("The usage of 'Class.this' and 'Class.super' within static nested class '" + currentClass.getName() + "' is not allowed in a static context.", expression);
}
}
use of org.codehaus.groovy.ast.InnerClassNode in project groovy by apache.
the class AsmClassGenerator method makeInnerClassEntry.
private void makeInnerClassEntry(final ClassNode cn) {
if (!(cn instanceof InnerClassNode))
return;
InnerClassNode innerClass = (InnerClassNode) cn;
String innerClassName = innerClass.getName();
String innerClassInternalName = BytecodeHelper.getClassInternalName(innerClassName);
{
int index = innerClassName.lastIndexOf('$');
if (index >= 0)
innerClassName = innerClassName.substring(index + 1);
}
String outerClassName = BytecodeHelper.getClassInternalName(innerClass.getOuterClass().getName());
MethodNode enclosingMethod = innerClass.getEnclosingMethod();
if (enclosingMethod != null) {
// local inner classes do not specify the outer class name
outerClassName = null;
if (innerClass.isAnonymous())
innerClassName = null;
}
int modifiers = adjustedClassModifiersForInnerClassTable(cn);
classVisitor.visitInnerClass(innerClassInternalName, outerClassName, innerClassName, modifiers);
}
Aggregations