public void visitConstructorCallExpression(ConstructorCallExpression call) { isSpecialConstructorCall = call.isSpecialCall(); super.visitConstructorCallExpression(call); isSpecialConstructorCall = false; if (!call.isUsingAnonymousInnerClass()) return; pushState(); InnerClassNode innerClass = (InnerClassNode) call.getType(); innerClass.setVariableScope(currentScope); for (MethodNode method : innerClass.getMethods()) { Parameter[] parameters = method.getParameters(); if (parameters.length == 0) parameters = null; // null means no implicit "it" ClosureExpression cl = new ClosureExpression(parameters, method.getCode()); visitClosureExpression(cl); } for (FieldNode field : innerClass.getFields()) { final Expression expression = field.getInitialExpression(); if (expression != null) { expression.visit(this); } } for (Statement statement : innerClass.getObjectInitializerStatements()) { statement.visit(this); } markClosureSharedVariables(); popState(); }
private static boolean classNodeUsesReferences(ClassNode classNode) { boolean ret = classNode.getSuperClass() == ClassHelper.CLOSURE_TYPE; if (ret) return ret; if (classNode instanceof InnerClassNode) { InnerClassNode inner = (InnerClassNode) classNode; return inner.isAnonymous(); } return false; }
public void visitClass(ClassNode node) { // AIC are already done, doing them here again will lead // to wrong scopes if (node instanceof InnerClassNode) { InnerClassNode in = (InnerClassNode) node; if (in.isAnonymous()) return; } pushState(); prepareVisit(node); super.visitClass(node); popState(); }
@Override public void visitClass(final ClassNode node) { boolean skip = shouldSkipClassNode(node); if (!skip && !anyMethodSkip(node)) { node.putNodeMetaData(MopWriter.Factory.class, StaticCompilationMopWriter.FACTORY); } ClassNode oldCN = classNode; classNode = node; Iterator<InnerClassNode> innerClasses = classNode.getInnerClasses(); while (innerClasses.hasNext()) { InnerClassNode innerClassNode = innerClasses.next(); boolean innerStaticCompile = !(skip || isSkippedInnerClass(innerClassNode)); innerClassNode.putNodeMetaData(STATIC_COMPILE_NODE, innerStaticCompile); innerClassNode.putNodeMetaData( WriterControllerFactory.class, node.getNodeMetaData(WriterControllerFactory.class)); if (innerStaticCompile && !anyMethodSkip(innerClassNode)) { innerClassNode.putNodeMetaData(MopWriter.Factory.class, StaticCompilationMopWriter.FACTORY); } } super.visitClass(node); addPrivateFieldAndMethodAccessors(node); classNode = oldCN; }
private boolean isAnonymousInnerClass(ClassNode enumClass) { if (!(enumClass instanceof EnumConstantClassNode)) return false; InnerClassNode ic = (InnerClassNode) enumClass; return ic.getVariableScope() == null; }
protected ClassNode createClosureClass(ClosureExpression expression, int mods) { ClassNode classNode = controller.getClassNode(); ClassNode outerClass = controller.getOutermostClass(); MethodNode methodNode = controller.getMethodNode(); String name = classNode.getName() + "$" + controller .getContext() .getNextClosureInnerName( outerClass, classNode, methodNode); // add a more informative name boolean staticMethodOrInStaticClass = controller.isStaticMethod() || classNode.isStaticClass(); Parameter[] parameters = expression.getParameters(); if (parameters == null) { parameters = Parameter.EMPTY_ARRAY; } else if (parameters.length == 0) { // let's create a default 'it' parameter Parameter it = new Parameter(ClassHelper.OBJECT_TYPE, "it", ConstantExpression.NULL); parameters = new Parameter[] {it}; Variable ref = expression.getVariableScope().getDeclaredVariable("it"); if (ref != null) it.setClosureSharedVariable(ref.isClosureSharedVariable()); } Parameter[] localVariableParams = getClosureSharedVariables(expression); removeInitialValues(localVariableParams); InnerClassNode answer = new InnerClassNode(classNode, name, mods, ClassHelper.CLOSURE_TYPE.getPlainNodeReference()); answer.setEnclosingMethod(controller.getMethodNode()); answer.setSynthetic(true); answer.setUsingGenerics(outerClass.isUsingGenerics()); answer.setSourcePosition(expression); if (staticMethodOrInStaticClass) { answer.setStaticClass(true); } if (controller.isInScriptBody()) { answer.setScriptBody(true); } MethodNode method = answer.addMethod( "doCall", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, expression.getCode()); method.setSourcePosition(expression); VariableScope varScope = expression.getVariableScope(); if (varScope == null) { throw new RuntimeException( "Must have a VariableScope by now! for expression: " + expression + " class: " + name); } else { method.setVariableScope(varScope.copy()); } if (parameters.length > 1 || (parameters.length == 1 && parameters[0].getType() != null && parameters[0].getType() != ClassHelper.OBJECT_TYPE && !ClassHelper.OBJECT_TYPE.equals(parameters[0].getType().getComponentType()))) { // let's add a typesafe call method MethodNode call = answer.addMethod( "call", ACC_PUBLIC, ClassHelper.OBJECT_TYPE, parameters, ClassNode.EMPTY_ARRAY, new ReturnStatement( new MethodCallExpression( VariableExpression.THIS_EXPRESSION, "doCall", new ArgumentListExpression(parameters)))); call.setSourcePosition(expression); } // let's make the constructor BlockStatement block = new BlockStatement(); // this block does not get a source position, because we don't // want this synthetic constructor to show up in corbertura reports VariableExpression outer = new VariableExpression("_outerInstance"); outer.setSourcePosition(expression); block.getVariableScope().putReferencedLocalVariable(outer); VariableExpression thisObject = new VariableExpression("_thisObject"); thisObject.setSourcePosition(expression); block.getVariableScope().putReferencedLocalVariable(thisObject); TupleExpression conArgs = new TupleExpression(outer, thisObject); block.addStatement( new ExpressionStatement(new ConstructorCallExpression(ClassNode.SUPER, conArgs))); // let's assign all the parameter fields from the outer context for (Parameter param : localVariableParams) { String paramName = param.getName(); ClassNode type = param.getType(); if (true) { VariableExpression initialValue = new VariableExpression(paramName); initialValue.setAccessedVariable(param); initialValue.setUseReferenceDirectly(true); ClassNode realType = type; type = ClassHelper.makeReference(); param.setType(ClassHelper.makeReference()); FieldNode paramField = answer.addField(paramName, ACC_PRIVATE | ACC_SYNTHETIC, type, initialValue); paramField.setOriginType(ClassHelper.getWrapper(param.getOriginType())); paramField.setHolder(true); String methodName = Verifier.capitalize(paramName); // let's add a getter & setter Expression fieldExp = new FieldExpression(paramField); answer.addMethod( "get" + methodName, ACC_PUBLIC, realType.getPlainNodeReference(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(fieldExp)); } } Parameter[] params = new Parameter[2 + localVariableParams.length]; params[0] = new Parameter(ClassHelper.OBJECT_TYPE, "_outerInstance"); params[1] = new Parameter(ClassHelper.OBJECT_TYPE, "_thisObject"); System.arraycopy(localVariableParams, 0, params, 2, localVariableParams.length); ASTNode sn = answer.addConstructor(ACC_PUBLIC, params, ClassNode.EMPTY_ARRAY, block); sn.setSourcePosition(expression); correctAccessedVariable(answer, expression); return answer; }