@Override public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { InnerClassVisitor iv = new InnerClassVisitor(CompilationUnit.this, source); iv.visitClass(classNode); } }, Phases.SEMANTIC_ANALYSIS);
private void passThisReference(ConstructorCallExpression call) { ClassNode cn = call.getType().redirect(); if (!shouldHandleImplicitThisForInnerClass(cn)) return; boolean isInStaticContext = true; if (currentMethod != null) isInStaticContext = currentMethod.getVariableScope().isInStaticContext(); else if (currentField != null) isInStaticContext = currentField.isStatic(); else if (processingObjInitStatements) isInStaticContext = false; // if constructor call is not in static context, return if (isInStaticContext) { // constructor call is in static context and the inner class is non-static - 1st arg is supposed to be // passed as enclosing "this" instance // Expression args = call.getArguments(); if (args instanceof TupleExpression && ((TupleExpression) args).getExpressions().isEmpty()) { addError("No enclosing instance passed in constructor call of a non-static inner class", call); } return; } insertThis0ToSuperCall(call, cn); }
@Override protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) { this.currentMethod = node; visitAnnotations(node); visitClassCodeContainer(node.getCode()); // GROOVY-5681: initial expressions should be visited too! for (Parameter param : node.getParameters()) { if (param.hasInitialExpression()) { param.getInitialExpression().visit(this); } visitAnnotations(param); } this.currentMethod = null; }
super.visitConstructorCallExpression(call); if (!call.isUsingAnonymousInnerClass()) { passThisReference(call); return; && !superClass.isInterface() && !(superClass.isStaticClass()||((superClass.getModifiers()&ACC_STATIC)==ACC_STATIC))) { insertThis0ToSuperCall(call, innerClass); boolean isStatic = isStaticThis(innerClass,scope); ClassNode outerClassType = getClassNode(outerClass, isStatic); if (!isStatic && inClosure) outerClassType = ClassHelper.CLOSURE_TYPE; outerClassType = outerClassType.getPlainNodeReference(); addFieldInit(thisParameter, thisField, block);
private void addThisReference(ConstructorNode node) { if (!shouldHandleImplicitThisForInnerClass(classNode)) return; Statement code = node.getCode(); Parameter[] newParams = new Parameter[params.length + 1]; System.arraycopy(params, 0, newParams, 1, params.length); Parameter thisPara = new Parameter(classNode.getOuterClass().getPlainNodeReference(), getUniqueName(params, node)); newParams[0] = thisPara; node.setParameters(newParams); addFieldInit(thisPara, thisField, newCode); ConstructorCallExpression cce = getFirstIfSpecialConstructorCall(block); if (cce == null) { cce = new ConstructorCallExpression(ClassNode.SUPER, new TupleExpression()); block.getStatements().add(0, new ExpressionStatement(cce)); if (shouldImplicitlyPassThisPara(cce)) {
super.visitConstructorCallExpression(call); if (!call.isUsingAnonymousInnerClass()) { passThisReference(call); return; ClassNode outerClassType = getClassNode(innerClass.getOuterClass(), isStatic).getPlainNodeReference(); Parameter thisParameter = new Parameter(outerClassType, "p" + pCount); parameters.add(pCount, thisParameter); addFieldInit(thisParameter, thisField, block);
private void passThisReference(ConstructorCallExpression call) { ClassNode cn = call.getType().redirect(); if (!shouldHandleImplicitThisForInnerClass(cn)) return; addError("No enclosing instance passed in constructor call of a non-static inner class", call);
@Override public void visitClass(ClassNode node) { this.classNode = node; thisField = null; InnerClassNode innerClass = null; if (!node.isEnum() && !node.isInterface() && node instanceof InnerClassNode) { innerClass = (InnerClassNode) node; if (!isStatic(innerClass) && innerClass.getVariableScope() == null) { thisField = innerClass.addField("this$0", PUBLIC_SYNTHETIC, node.getOuterClass().getPlainNodeReference(), null); } } super.visitClass(node); if (node.isEnum() || node.isInterface()) return; if (innerClass == null) return; if (node.getSuperClass().isInterface() || Traits.isAnnotatedWithTrait(node.getSuperClass())) { node.addInterface(node.getUnresolvedSuperClass()); node.setUnresolvedSuperClass(ClassHelper.OBJECT_TYPE); } }
private String getUniqueName(Parameter[] params, ConstructorNode node) { String namePrefix = "$p"; outer: for (int i = 0; i < 100; i++) { namePrefix = namePrefix + "$"; for (Parameter p : params) { if (p.getName().equals(namePrefix)) continue outer; } return namePrefix; } addError("unable to find a unique prefix name for synthetic this reference", node); return namePrefix; }
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; }
@Override public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException { InnerClassVisitor iv = new InnerClassVisitor(CompilationUnit.this, source); iv.visitClass(classNode); } }, Phases.SEMANTIC_ANALYSIS);
@Override protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) { this.currentMethod = node; visitAnnotations(node); visitClassCodeContainer(node.getCode()); // GROOVY-5681: initial expressions should be visited too! for (Parameter param : node.getParameters()) { if (param.hasInitialExpression()) { param.getInitialExpression().visit(this); } visitAnnotations(param); } this.currentMethod = null; }
@Override public void visitClass(ClassNode node) { this.classNode = node; thisField = null; InnerClassNode innerClass = null; if (!node.isEnum() && !node.isInterface() && node instanceof InnerClassNode) { innerClass = (InnerClassNode) node; if (!isStatic(innerClass) && innerClass.getVariableScope() == null) { thisField = innerClass.addField("this$0", PUBLIC_SYNTHETIC, node.getOuterClass().getPlainNodeReference(), null); } if (innerClass.getVariableScope() == null && innerClass.getDeclaredConstructors().isEmpty()) { // add dummy constructor innerClass.addConstructor(ACC_PUBLIC, new Parameter[0], null, null); } } super.visitClass(node); if (node.isEnum() || node.isInterface()) return; if (innerClass == null) return; if (node.getSuperClass().isInterface()) { node.addInterface(node.getUnresolvedSuperClass()); node.setUnresolvedSuperClass(ClassHelper.OBJECT_TYPE); } }