Java Code Examples for org.codehaus.groovy.ast.ClassNode#isInterface()

The following examples show how to use org.codehaus.groovy.ast.ClassNode#isInterface() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: InnerClassCompletionVisitor.java    From groovy with Apache License 2.0 6 votes vote down vote up
@Override
public void visitClass(ClassNode node) {
    classNode = node;
    thisField = null;
    InnerClassNode innerClass = null;
    if (!node.isEnum() && !node.isInterface() && node instanceof InnerClassNode) {
        innerClass = (InnerClassNode) node;
        thisField = innerClass.getField("this$0");
        if (innerClass.getVariableScope() == null && innerClass.getDeclaredConstructors().isEmpty()) {
            // add empty default constructor
            addGeneratedConstructor(innerClass, ACC_PUBLIC, Parameter.EMPTY_ARRAY, null, null);
        }
    }
    if (node.isEnum() || node.isInterface()) return;
    // use Iterator.hasNext() to check for available inner classes
    if (node.getInnerClasses().hasNext()) addDispatcherMethods(node);
    if (innerClass == null) return;
    super.visitClass(node);
    addMopMethods(innerClass);
}
 
Example 2
Source File: InnerClassCompletionVisitor.java    From groovy with Apache License 2.0 6 votes vote down vote up
private boolean shouldImplicitlyPassThisPara(ConstructorCallExpression cce) {
    boolean pass = false;
    ClassNode superCN = classNode.getSuperClass();
    if (cce.isThisCall()) {
        pass = true;
    } else if (cce.isSuperCall()) {
        // if the super class is another non-static inner class in the same outer class hierarchy, implicit this
        // needs to be passed
        if (!superCN.isEnum() && !superCN.isInterface() && superCN instanceof InnerClassNode) {
            InnerClassNode superInnerCN = (InnerClassNode) superCN;
            if (!isStatic(superInnerCN) && classNode.getOuterClass().isDerivedFrom(superCN.getOuterClass())) {
                pass = true;
            }
        }
    }
    return pass;
}
 
Example 3
Source File: NewifyASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
private void newifyClass(ClassNode cNode, boolean autoFlag, ListExpression list, final Pattern cnPattern) {
    String cName = cNode.getName();
    if (cNode.isInterface()) {
        addError("Error processing interface '" + cName + "'. @"
                + MY_NAME + " not allowed for interfaces.", cNode);
    }

    final ListExpression oldClassesToNewify = classesToNewify;
    final boolean oldAuto = auto;
    final Pattern oldCnPattern = classNamePattern;

    classesToNewify = list;
    auto = autoFlag;
    classNamePattern = cnPattern;

    super.visitClass(cNode);

    classesToNewify = oldClassesToNewify;
    auto = oldAuto;
    classNamePattern = oldCnPattern;
}
 
Example 4
Source File: ClassCompletionVerifier.java    From groovy with Apache License 2.0 6 votes vote down vote up
private void checkClassExtendsAllSelfTypes(ClassNode node) {
    int modifiers = node.getModifiers();
    if (!isInterface(modifiers)) {
        for (ClassNode anInterface : GeneralUtils.getInterfacesAndSuperInterfaces(node)) {
            if (Traits.isTrait(anInterface)) {
                LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<ClassNode>();
                for (ClassNode type : Traits.collectSelfTypes(anInterface, selfTypes, true, false)) {
                    if (type.isInterface() && !node.implementsInterface(type)) {
                        addError(getDescription(node)
                                + " implements " + getDescription(anInterface)
                                + " but does not implement self type " + getDescription(type),
                                anInterface);
                    } else if (!type.isInterface() && !node.isDerivedFrom(type)) {
                        addError(getDescription(node)
                                        + " implements " + getDescription(anInterface)
                                        + " but does not extend self type " + getDescription(type),
                                anInterface);
                    }
                }
            }
        }
    }
}
 
Example 5
Source File: WideningCategories.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static ClassNode findGenericsTypeHolderForClass(ClassNode source, ClassNode type) {
    if (isPrimitiveType(source)) source = getWrapper(source);
    if (source.equals(type)) return source;
    if (type.isInterface()) {
        for (ClassNode interfaceNode : source.getAllInterfaces()) {
            if (interfaceNode.equals(type)) {
                ClassNode parameterizedInterface = GenericsUtils.parameterizeType(source, interfaceNode);
                return parameterizedInterface;
            }
        }
    }
    ClassNode superClass = source.getUnresolvedSuperClass();
    // copy generic type information if available
    if (superClass!=null && superClass.isUsingGenerics()) {
        Map<GenericsTypeName, GenericsType> genericsTypeMap = GenericsUtils.extractPlaceholders(source);
        GenericsType[] genericsTypes = superClass.getGenericsTypes();
        if (genericsTypes!=null) {
            GenericsType[] copyTypes = new GenericsType[genericsTypes.length];
            for (int i = 0; i < genericsTypes.length; i++) {
                GenericsType genericsType = genericsTypes[i];
                GenericsTypeName gtn = new GenericsTypeName(genericsType.getName());
                if (genericsType.isPlaceholder() && genericsTypeMap.containsKey(gtn)) {
                    copyTypes[i] = genericsTypeMap.get(gtn);
                } else {
                    copyTypes[i] = genericsType;
                }
            }
            superClass = superClass.getPlainNodeReference();
            superClass.setGenericsTypes(copyTypes);
        }
    }
    if (superClass!=null) return findGenericsTypeHolderForClass(superClass, type);
    return null;
}
 
Example 6
Source File: GroovyNodeToStringUtils.java    From groovy-language-server with Apache License 2.0 5 votes vote down vote up
public static String classToString(ClassNode classNode, ASTNodeVisitor ast) {
	StringBuilder builder = new StringBuilder();
	String packageName = classNode.getPackageName();
	if (packageName != null && packageName.length() > 0) {
		builder.append("package ");
		builder.append(packageName);
		builder.append("\n");
	}
	if (!classNode.isSyntheticPublic()) {
		builder.append("public ");
	}
	if (classNode.isAbstract()) {
		builder.append("abstract ");
	}
	if (classNode.isInterface()) {
		builder.append("interface ");
	} else if (classNode.isEnum()) {
		builder.append("enum ");
	} else {
		builder.append("class ");
	}
	builder.append(classNode.getNameWithoutPackage());

	ClassNode superClass = null;
	try {
		superClass = classNode.getSuperClass();
	} catch (NoClassDefFoundError e) {
		//this is fine, we'll just treat it as null
	}
	if (superClass != null && !superClass.getName().equals(JAVA_OBJECT)) {
		builder.append(" extends ");
		builder.append(superClass.getNameWithoutPackage());
	}
	return builder.toString();
}
 
Example 7
Source File: ClassCompletionVerifier.java    From groovy with Apache License 2.0 5 votes vote down vote up
private void checkClassForAbstractAndFinal(ClassNode node) {
    if (!isAbstract(node.getModifiers())) return;
    if (!isFinal(node.getModifiers())) return;
    if (node.isInterface()) {
        addError("The " + getDescription(node) + " must not be final. It is by definition abstract.", node);
    } else {
        addError("The " + getDescription(node) + " must not be both final and abstract.", node);
    }
}
 
Example 8
Source File: AsmClassGenerator.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static int adjustedClassModifiersForClassWriting(final ClassNode classNode) {
    int modifiers = classNode.getModifiers();
    boolean needsSuper = !classNode.isInterface();
    modifiers = needsSuper ? modifiers | ACC_SUPER : modifiers & ~ACC_SUPER;
    // eliminate static
    modifiers = modifiers & ~ACC_STATIC;
    modifiers = fixInnerClassModifiers(classNode, modifiers);
    modifiers = fixInterfaceModifiers(classNode, modifiers);
    return modifiers;
}
 
Example 9
Source File: Verifier.java    From groovy with Apache License 2.0 5 votes vote down vote up
private boolean isAssignable(ClassNode node, ClassNode testNode) {
    if (node.isArray() && testNode.isArray()) {
        return isArrayAssignable(node.getComponentType(), testNode.getComponentType());
    }
    if (testNode.isInterface()) {
        if (node.equals(testNode) || node.implementsInterface(testNode)) return true;
    }
    return node.isDerivedFrom(testNode);
}
 
Example 10
Source File: SortableASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private void createSortable(AnnotationNode anno, ClassNode classNode) {
    List<String> includes = getMemberStringList(anno, "includes");
    List<String> excludes = getMemberStringList(anno, "excludes");
    boolean reversed = memberHasValue(anno, "reversed", true);
    boolean includeSuperProperties = memberHasValue(anno, "includeSuperProperties", true);
    boolean allNames = memberHasValue(anno, "allNames", true);
    boolean allProperties = !memberHasValue(anno, "allProperties", false);
    if (!checkIncludeExcludeUndefinedAware(anno, excludes, includes, MY_TYPE_NAME)) return;
    if (!checkPropertyList(classNode, includes, "includes", anno, MY_TYPE_NAME, false, includeSuperProperties, allProperties)) return;
    if (!checkPropertyList(classNode, excludes, "excludes", anno, MY_TYPE_NAME, false, includeSuperProperties, allProperties)) return;
    if (classNode.isInterface()) {
        addError(MY_TYPE_NAME + " cannot be applied to interface " + classNode.getName(), anno);
    }
    List<PropertyNode> properties = findProperties(anno, classNode, includes, excludes, allProperties, includeSuperProperties, allNames);
    implementComparable(classNode);

    addGeneratedMethod(classNode,
            "compareTo",
            ACC_PUBLIC,
            ClassHelper.int_TYPE,
            params(param(newClass(classNode), OTHER)),
            ClassNode.EMPTY_ARRAY,
            createCompareToMethodBody(properties, reversed)
    );

    for (PropertyNode property : properties) {
        createComparatorFor(classNode, property, reversed);
    }
    new VariableScopeVisitor(sourceUnit, true).visitClass(classNode);
}
 
Example 11
Source File: InnerClassVisitorHelper.java    From groovy with Apache License 2.0 5 votes vote down vote up
protected static boolean shouldHandleImplicitThisForInnerClass(ClassNode cn) {
    if (cn.isEnum() || cn.isInterface()) return false;
    if ((cn.getModifiers() & Opcodes.ACC_STATIC) != 0) return false;

    if (!(cn instanceof InnerClassNode)) return false;
    InnerClassNode innerClass = (InnerClassNode) cn;
    // scope != null means aic, we don't handle that here
    if (innerClass.getVariableScope() != null) return false;
    // static inner classes don't need this$0
    return (innerClass.getModifiers() & Opcodes.ACC_STATIC) == 0;
}
 
Example 12
Source File: ClassCompletionVerifier.java    From groovy with Apache License 2.0 5 votes vote down vote up
private void checkImplementsAndExtends(ClassNode node) {
    ClassNode cn = node.getSuperClass();
    if (cn.isInterface() && !node.isInterface()) {
        addError("You are not allowed to extend the " + getDescription(cn) + ", use implements instead.", node);
    }
    for (ClassNode anInterface : node.getInterfaces()) {
        cn = anInterface;
        if (!cn.isInterface()) {
            addError("You are not allowed to implement the " + getDescription(cn) + ", use extends instead.", node);
        }
    }
}
 
Example 13
Source File: CompilationUnit.java    From groovy with Apache License 2.0 5 votes vote down vote up
private List<ClassNode> getPrimaryClassNodes(final boolean sort) {
    List<ClassNode> unsorted = getAST().getModules().stream()
        .flatMap(module -> module.getClasses().stream()).collect(toList());

    if (!sort) return unsorted;

    int n = unsorted.size();
    int[] indexClass = new int[n];
    int[] indexInterface = new int[n];
    {
        int i = 0;
        for (ClassNode element : unsorted) {
            if (element.isInterface()) {
                indexInterface[i] = getSuperInterfaceCount(element);
                indexClass[i] = -1;
            } else {
                indexClass[i] = getSuperClassCount(element);
                indexInterface[i] = -1;
            }
            i += 1;
        }
    }

    List<ClassNode> sorted = getSorted(indexInterface, unsorted);
    sorted.addAll(getSorted(indexClass, unsorted));
    return sorted;
}
 
Example 14
Source File: CompilationUnit.java    From groovy with Apache License 2.0 5 votes vote down vote up
protected ClassVisitor createClassVisitor() {
    CompilerConfiguration config = getConfiguration();
    int computeMaxStackAndFrames = ClassWriter.COMPUTE_MAXS;
    if (CompilerConfiguration.isPostJDK7(config.getTargetBytecode()) || config.isIndyEnabled()) {
        computeMaxStackAndFrames += ClassWriter.COMPUTE_FRAMES;
    }
    return new ClassWriter(computeMaxStackAndFrames) {
        private ClassNode getClassNode(String name) {
            // try classes under compilation
            CompileUnit cu = getAST();
            ClassNode cn = cu.getClass(name);
            if (cn != null) return cn;
            // try inner classes
            cn = cu.getGeneratedInnerClass(name);
            if (cn != null) return cn;
            ClassNodeResolver.LookupResult lookupResult = getClassNodeResolver().resolveName(name, CompilationUnit.this);
            return lookupResult == null ? null : lookupResult.getClassNode();
        }
        private ClassNode getCommonSuperClassNode(ClassNode c, ClassNode d) {
            // adapted from ClassWriter code
            if (c.isDerivedFrom(d)) return d;
            if (d.isDerivedFrom(c)) return c;
            if (c.isInterface() || d.isInterface()) return ClassHelper.OBJECT_TYPE;
            do {
                c = c.getSuperClass();
            } while (c != null && !d.isDerivedFrom(c));
            if (c == null) return ClassHelper.OBJECT_TYPE;
            return c;
        }
        @Override
        protected String getCommonSuperClass(String arg1, String arg2) {
            ClassNode a = getClassNode(arg1.replace('/', '.'));
            ClassNode b = getClassNode(arg2.replace('/', '.'));
            return getCommonSuperClassNode(a,b).getName().replace('.','/');
        }
    };
}
 
Example 15
Source File: StaticInvocationWriter.java    From groovy with Apache License 2.0 5 votes vote down vote up
private boolean compatibleArgumentType(final ClassNode argumentType, final ClassNode paramType) {
    if (argumentType == null) return false;
    if (ClassHelper.getWrapper(argumentType).equals(ClassHelper.getWrapper(paramType))) return true;
    if (paramType.isInterface()) return argumentType.implementsInterface(paramType);
    if (paramType.isArray() && argumentType.isArray())
        return compatibleArgumentType(argumentType.getComponentType(), paramType.getComponentType());
    return ClassHelper.getWrapper(argumentType).isDerivedFrom(ClassHelper.getWrapper(paramType));
}
 
Example 16
Source File: GroovyVirtualSourceProvider.java    From netbeans with Apache License 2.0 5 votes vote down vote up
private void genMethod(ClassNode clazz, MethodNode methodNode, PrintWriter out, boolean ignoreSynthetic) {
    String name = methodNode.getName();
    if ((ignoreSynthetic && methodNode.isSynthetic()) || name.startsWith("super$")) { // NOI18N
        return;
    }
// </netbeans>
    if (methodNode.getName().equals("<clinit>")) {
        return;
    }
    if (!clazz.isInterface()) {
        printModifiers(out, methodNode.getModifiers());
    }
    printType(methodNode.getReturnType(), out);
    out.print(" ");
    out.print(methodNode.getName());

    printParams(methodNode, out);

    ClassNode[] exceptions = methodNode.getExceptions();
    if (exceptions != null && exceptions.length > 0) {
        out.print(" throws ");
        for (int i = 0; i < exceptions.length; i++) {
            if (i > 0) {
                out.print(", ");
            }
            printType(exceptions[i], out);
        }
    }

    if ((methodNode.getModifiers() & Opcodes.ACC_ABSTRACT) != 0) {
        out.println(";");
    } else {
        out.print(" { ");
        ClassNode retType = methodNode.getReturnType();
        printReturn(out, retType);
        out.println("}");
    }
}
 
Example 17
Source File: ClosureWriter.java    From groovy with Apache License 2.0 4 votes vote down vote up
public void writeClosure(final ClosureExpression expression) {
    CompileStack compileStack = controller.getCompileStack();
    MethodVisitor mv = controller.getMethodVisitor();
    ClassNode classNode = controller.getClassNode();
    AsmClassGenerator acg = controller.getAcg();

    // generate closure as public class to make sure it can be properly invoked by classes of the
    // Groovy runtime without circumventing JVM access checks (see CachedMethod for example).
    int mods = ACC_PUBLIC | ACC_FINAL;
    if (classNode.isInterface()) {
        mods |= ACC_STATIC;
    }
    ClassNode closureClass = getOrAddClosureClass(expression, mods);
    String closureClassinternalName = BytecodeHelper.getClassInternalName(closureClass);
    List<ConstructorNode> constructors = closureClass.getDeclaredConstructors();
    ConstructorNode node = constructors.get(0);

    Parameter[] localVariableParams = node.getParameters();

    mv.visitTypeInsn(NEW, closureClassinternalName);
    mv.visitInsn(DUP);
    if (controller.isStaticMethod() || compileStack.isInSpecialConstructorCall()) {
        (new ClassExpression(classNode)).visit(acg);
        (new ClassExpression(controller.getOutermostClass())).visit(acg);
    } else {
        mv.visitVarInsn(ALOAD, 0);
        controller.getOperandStack().push(ClassHelper.OBJECT_TYPE);
        loadThis();
    }

    // now let's load the various parameters we're passing
    // we start at index 2 because the first variable we pass
    // is the owner instance and at this point it is already
    // on the stack
    for (int i = 2; i < localVariableParams.length; i++) {
        Parameter param = localVariableParams[i];
        String name = param.getName();
        loadReference(name, controller);
        if (param.getNodeMetaData(ClosureWriter.UseExistingReference.class)==null) {
            param.setNodeMetaData(ClosureWriter.UseExistingReference.class,Boolean.TRUE);
        }
    }

    // we may need to pass in some other constructors
    //cv.visitMethodInsn(INVOKESPECIAL, innerClassinternalName, "<init>", prototype + ")V");
    mv.visitMethodInsn(INVOKESPECIAL, closureClassinternalName, "<init>", BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, localVariableParams), false);
    controller.getOperandStack().replace(ClassHelper.CLOSURE_TYPE, localVariableParams.length);
}
 
Example 18
Source File: StaticTypeCheckingSupport.java    From groovy with Apache License 2.0 4 votes vote down vote up
public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final ClassNode right, final Expression rightExpression, final boolean allowConstructorCoercion) {
    ClassNode leftRedirect = left.redirect();
    ClassNode rightRedirect = right.redirect();
    if (leftRedirect == rightRedirect) return true;

    if (leftRedirect.isArray() && rightRedirect.isArray()) {
        return checkCompatibleAssignmentTypes(leftRedirect.getComponentType(), rightRedirect.getComponentType(), rightExpression, false);
    }

    if (right == VOID_TYPE || right == void_WRAPPER_TYPE) {
        return left == VOID_TYPE || left == void_WRAPPER_TYPE;
    }

    if ((isNumberType(rightRedirect) || WideningCategories.isNumberCategory(rightRedirect))) {
        if (BigDecimal_TYPE == leftRedirect) {
            // any number can be assigned to a big decimal
            return true;
        }
        if (BigInteger_TYPE == leftRedirect) {
            return WideningCategories.isBigIntCategory(getUnwrapper(rightRedirect)) || rightRedirect.isDerivedFrom(BigInteger_TYPE);
        }
    }

    // if rightExpression is null and leftExpression is not a primitive type, it's ok
    boolean rightExpressionIsNull = (rightExpression instanceof ConstantExpression && ((ConstantExpression) rightExpression).isNullExpression());
    if (rightExpressionIsNull && !isPrimitiveType(left)) {
        return true;
    }

    // on an assignment everything that can be done by a GroovyCast is allowed

    // anything can be assigned to an Object, String, Boolean or Class typed variable
    if (isWildcardLeftHandSide(leftRedirect) && !(boolean_TYPE.equals(left) && rightExpressionIsNull)) return true;

    // char as left expression
    if (leftRedirect == char_TYPE && rightRedirect == STRING_TYPE) {
        if (rightExpression instanceof ConstantExpression) {
            String value = rightExpression.getText();
            return value.length() == 1;
        }
    }
    if (leftRedirect == Character_TYPE && (rightRedirect == STRING_TYPE || rightExpressionIsNull)) {
        return rightExpressionIsNull || (rightExpression instanceof ConstantExpression && rightExpression.getText().length() == 1);
    }

    // if left is Enum and right is String or GString we do valueOf
    if (leftRedirect.isDerivedFrom(Enum_Type) && (rightRedirect == GSTRING_TYPE || rightRedirect == STRING_TYPE)) {
        return true;
    }

    // if right is array, map or collection we try invoking the constructor
    if (allowConstructorCoercion && isGroovyConstructorCompatible(rightExpression)) {
        // TODO: in case of the array we could maybe make a partial check
        if (leftRedirect.isArray() && rightRedirect.isArray()) {
            return checkCompatibleAssignmentTypes(leftRedirect.getComponentType(), rightRedirect.getComponentType());
        } else if (rightRedirect.isArray() && !leftRedirect.isArray()) {
            return false;
        }
        return true;
    }

    // simple check on being subclass
    if (right.isDerivedFrom(left) || (left.isInterface() && right.implementsInterface(left))) return true;

    // if left and right are primitives or numbers allow
    if (isPrimitiveType(leftRedirect) && isPrimitiveType(rightRedirect)) return true;
    if (isNumberType(leftRedirect) && isNumberType(rightRedirect)) return true;

    // left is a float/double and right is a BigDecimal
    if (WideningCategories.isFloatingCategory(leftRedirect) && BigDecimal_TYPE.equals(rightRedirect)) {
        return true;
    }

    if (GROOVY_OBJECT_TYPE.equals(leftRedirect) && isBeingCompiled(right)) {
        return true;
    }

    if (left.isGenericsPlaceHolder()) {
        // GROOVY-7307
        GenericsType[] genericsTypes = left.getGenericsTypes();
        if (genericsTypes != null && genericsTypes.length == 1) {
            // should always be the case, but safe guard is better
            return genericsTypes[0].isCompatibleWith(right);
        }
    }

    // GROOVY-7316: It is an apparently legal thing to allow this. It's not type safe, but it is allowed...
    return right.isGenericsPlaceHolder();
}
 
Example 19
Source File: StaticTypesLambdaWriter.java    From groovy with Apache License 2.0 4 votes vote down vote up
@Override
public void writeLambda(final LambdaExpression expression) {
    ClassNode functionalInterface = getFunctionalInterfaceType(expression);
    if (functionalInterface == null || !functionalInterface.isInterface()) {
        super.writeLambda(expression);
        return;
    }

    MethodNode abstractMethod = findSAM(functionalInterface.redirect());
    if (abstractMethod == null) {
        super.writeLambda(expression);
        return;
    }

    if (!expression.isSerializable() && functionalInterface.implementsInterface(SERIALIZABLE_TYPE)) {
        expression.setSerializable(true);
    }

    ClassNode enclosingClass = controller.getClassNode();
    int modifiers = ACC_FINAL | ACC_PUBLIC | ACC_SYNTHETIC;
    if (enclosingClass.isInterface()) modifiers |= ACC_STATIC;
    ClassNode lambdaClass = getOrAddLambdaClass(expression, modifiers, abstractMethod);
    MethodNode lambdaMethod = lambdaClass.getMethods("doCall").get(0);

    boolean canDeserialize = enclosingClass.hasMethod(createDeserializeLambdaMethodName(lambdaClass), createDeserializeLambdaMethodParams());
    if (!canDeserialize) {
        if (expression.isSerializable()) {
            addDeserializeLambdaMethodForEachLambdaExpression(expression, lambdaClass);
            addDeserializeLambdaMethod();
        }
        newGroovyLambdaWrapperAndLoad(lambdaClass, expression, isAccessingInstanceMembersOfEnclosingClass(lambdaMethod));
    }

    MethodVisitor mv = controller.getMethodVisitor();
    mv.visitInvokeDynamicInsn(
            abstractMethod.getName(),
            createAbstractMethodDesc(functionalInterface.redirect(), lambdaClass),
            createBootstrapMethod(enclosingClass.isInterface(), expression.isSerializable()),
            createBootstrapMethodArguments(createMethodDescriptor(abstractMethod), H_INVOKEVIRTUAL, lambdaClass, lambdaMethod, expression.isSerializable())
    );
    if (expression.isSerializable()) {
        mv.visitTypeInsn(CHECKCAST, "java/io/Serializable");
    }

    OperandStack operandStack = controller.getOperandStack();
    operandStack.replace(functionalInterface.redirect(), 1);
}
 
Example 20
Source File: InnerClassVisitor.java    From groovy with Apache License 2.0 4 votes vote down vote up
@Override
public void visitConstructorCallExpression(ConstructorCallExpression call) {
    super.visitConstructorCallExpression(call);
    if (!call.isUsingAnonymousInnerClass()) {
        passThisReference(call);
        return;
    }

    InnerClassNode innerClass = (InnerClassNode) call.getType();
    ClassNode outerClass = innerClass.getOuterClass();
    ClassNode superClass = innerClass.getSuperClass();
    if (!superClass.isInterface() && superClass.getOuterClass() != null
            && !(superClass.isStaticClass() || (superClass.getModifiers() & ACC_STATIC) != 0)) {
        insertThis0ToSuperCall(call, innerClass);
    }
    if (!innerClass.getDeclaredConstructors().isEmpty()) return;
    if ((innerClass.getModifiers() & ACC_STATIC) != 0) return;

    VariableScope scope = innerClass.getVariableScope();
    if (scope == null) return;
    boolean isStatic = !inClosure && isStatic(innerClass, scope, call);

    // expressions = constructor call arguments
    List<Expression> expressions = ((TupleExpression) call.getArguments()).getExpressions();
    // block = init code for the constructor we produce
    BlockStatement block = new BlockStatement();
    // parameters = parameters of the constructor
    int additionalParamCount = (isStatic ? 0 : 1) + scope.getReferencedLocalVariablesCount();
    List<Parameter> parameters = new ArrayList<>(expressions.size() + additionalParamCount);
    // superCallArguments = arguments for the super call == the constructor call arguments
    List<Expression> superCallArguments = new ArrayList<>(expressions.size());

    // first we add a super() call for all expressions given in the constructor call expression
    for (int i = 0, n = expressions.size(); i < n; i += 1) {
        // add one parameter for each expression in the constructor call
        Parameter param = new Parameter(ClassHelper.OBJECT_TYPE, "p" + additionalParamCount + i);
        parameters.add(param);
        // add the corresponding argument to the super constructor call
        superCallArguments.add(new VariableExpression(param));
    }

    // add the super call
    ConstructorCallExpression cce = new ConstructorCallExpression(
            ClassNode.SUPER,
            new TupleExpression(superCallArguments)
    );

    block.addStatement(new ExpressionStatement(cce));

    int pCount = 0;
    if (!isStatic) {
        // need to pass "this" to access unknown methods/properties
        expressions.add(pCount, VariableExpression.THIS_EXPRESSION);

        ClassNode enclosingType = (inClosure ? ClassHelper.CLOSURE_TYPE : outerClass).getPlainNodeReference();
        Parameter thisParameter = new Parameter(enclosingType, "p" + pCount);
        parameters.add(pCount++, thisParameter);

        // "this" reference is saved in a field named "this$0"
        FieldNode thisField = innerClass.addField("this$0", ACC_FINAL | ACC_SYNTHETIC, enclosingType, null);
        addFieldInit(thisParameter, thisField, block);
    }

    // for each shared variable, add a Reference field
    for (Iterator<Variable> it = scope.getReferencedLocalVariablesIterator(); it.hasNext();) {
        Variable var = it.next();

        VariableExpression ve = new VariableExpression(var);
        ve.setClosureSharedVariable(true);
        ve.setUseReferenceDirectly(true);
        expressions.add(pCount, ve);

        ClassNode referenceType = ClassHelper.REFERENCE_TYPE.getPlainNodeReference();
        Parameter p = new Parameter(referenceType, "p" + pCount);
        p.setOriginType(var.getOriginType());
        parameters.add(pCount++, p);

        VariableExpression initial = new VariableExpression(p);
        initial.setSynthetic(true);
        initial.setUseReferenceDirectly(true);
        FieldNode pField = innerClass.addFieldFirst(ve.getName(), ACC_PUBLIC | ACC_SYNTHETIC, referenceType, initial);
        pField.setHolder(true);
        pField.setOriginType(ClassHelper.getWrapper(var.getOriginType()));
    }

    innerClass.addConstructor(ACC_SYNTHETIC, parameters.toArray(Parameter.EMPTY_ARRAY), ClassNode.EMPTY_ARRAY, block);
}