Example usage for org.eclipse.jdt.core.dom ITypeBinding isAssignmentCompatible

List of usage examples for org.eclipse.jdt.core.dom ITypeBinding isAssignmentCompatible

Introduction

In this page you can find the example usage for org.eclipse.jdt.core.dom ITypeBinding isAssignmentCompatible.

Prototype

public boolean isAssignmentCompatible(ITypeBinding variableType);

Source Link

Document

Returns whether an expression of this type can be assigned to a variable of the given type, as specified in section 5.2 of The Java Language Specification, Third Edition (JLS3).

Usage

From source file:ca.ecliptical.pde.internal.ds.AnnotationProcessor.java

License:Open Source License

private void validateComponentService(Annotation annotation, ITypeBinding componentType,
        ITypeBinding serviceType, int index, Collection<DSAnnotationProblem> problems) {
    if (!errorLevel.isNone() && !componentType.isAssignmentCompatible(serviceType))
        reportProblem(annotation, "service", problems, //$NON-NLS-1$
                NLS.bind(Messages.AnnotationProcessor_invalidComponentService, serviceType.getName()),
                serviceType.getName());/*from  ww w. j ava 2 s . c o m*/
}

From source file:ca.ecliptical.pde.internal.ds.AnnotationProcessor.java

License:Open Source License

private boolean processReference(MethodDeclaration method, IMethodBinding methodBinding, Annotation annotation,
        IAnnotationBinding annotationBinding, IDSDocumentFactory factory, Collection<IDSReference> collector,
        Map<String, Annotation> names, Collection<DSAnnotationProblem> problems) {
    HashMap<String, Object> params = new HashMap<String, Object>();
    for (IMemberValuePairBinding pair : annotationBinding.getDeclaredMemberValuePairs()) {
        params.put(pair.getName(), pair.getValue());
    }//from w  w w  . j  ava  2s.c  om

    boolean requiresV12 = false;

    ITypeBinding[] argTypes = methodBinding.getParameterTypes();

    ITypeBinding serviceType;
    Object value;
    if ((value = params.get("service")) instanceof ITypeBinding) { //$NON-NLS-1$
        serviceType = (ITypeBinding) value;
        if (!errorLevel.isNone() && argTypes.length > 0) {
            ITypeBinding[] typeArgs;
            if (!(ServiceReference.class.getName().equals(argTypes[0].getErasure().getQualifiedName())
                    && ((typeArgs = argTypes[0].getTypeArguments()).length == 0
                            || serviceType.isAssignmentCompatible(typeArgs[0])))
                    && !serviceType.isAssignmentCompatible(argTypes[0]))
                reportProblem(annotation, "service", problems, //$NON-NLS-1$
                        NLS.bind(Messages.AnnotationProcessor_invalidReferenceService, argTypes[0].getName(),
                                serviceType.getName()),
                        serviceType.getName());
        }
    } else if (argTypes.length > 0) {
        if (ServiceReference.class.getName().equals(argTypes[0].getErasure().getQualifiedName())) {
            ITypeBinding[] typeArgs = argTypes[0].getTypeArguments();
            if (typeArgs.length > 0)
                serviceType = typeArgs[0];
            else
                serviceType = null;
        } else {
            serviceType = argTypes[0].isPrimitive() ? getObjectType(method.getAST(), argTypes[0]) : argTypes[0];
        }
    } else {
        serviceType = null;
    }

    if (serviceType == null) {
        reportProblem(annotation, null, problems, Messages.AnnotationProcessor_invalidReferenceServiceUnknown);

        serviceType = method.getAST().resolveWellKnownType(Object.class.getName());
    }

    validateReferenceBindMethod(annotation, serviceType, methodBinding, problems);

    String service = serviceType == null ? null : serviceType.getBinaryName();

    String methodName = methodBinding.getName();
    String name;
    if ((value = params.get("name")) instanceof String) { //$NON-NLS-1$
        name = (String) value;
    } else if (methodName.startsWith("bind")) { //$NON-NLS-1$
        name = methodName.substring("bind".length()); //$NON-NLS-1$
    } else if (methodName.startsWith("set")) { //$NON-NLS-1$
        name = methodName.substring("set".length()); //$NON-NLS-1$
    } else if (methodName.startsWith("add")) { //$NON-NLS-1$
        name = methodName.substring("add".length()); //$NON-NLS-1$
    } else {
        name = methodName;
    }

    if (!errorLevel.isNone()) {
        if (names.containsKey(name)) {
            reportProblem(annotation, "name", problems, //$NON-NLS-1$
                    NLS.bind(Messages.AnnotationProcessor_duplicateReferenceName, name), name);
            Annotation duplicate = names.put(name, null);
            if (duplicate != null)
                reportProblem(duplicate, "name", problems, //$NON-NLS-1$
                        NLS.bind(Messages.AnnotationProcessor_duplicateReferenceName, name), name);
        } else {
            names.put(name, annotation);
        }
    }

    String cardinality = null;
    if ((value = params.get("cardinality")) instanceof IVariableBinding) { //$NON-NLS-1$
        IVariableBinding cardinalityBinding = (IVariableBinding) value;
        ReferenceCardinality cardinalityLiteral = ReferenceCardinality.valueOf(cardinalityBinding.getName());
        if (cardinalityLiteral != null)
            cardinality = cardinalityLiteral.toString();
    }

    String policy = null;
    if ((value = params.get("policy")) instanceof IVariableBinding) { //$NON-NLS-1$
        IVariableBinding policyBinding = (IVariableBinding) value;
        ReferencePolicy policyLiteral = ReferencePolicy.valueOf(policyBinding.getName());
        if (policyLiteral != null)
            policy = policyLiteral.toString();
    }

    String target = null;
    if ((value = params.get("target")) instanceof String) { //$NON-NLS-1$
        target = (String) value;
        validateReferenceTarget(annotation, target, problems);
    }

    String unbind;
    if ((value = params.get("unbind")) instanceof String) { //$NON-NLS-1$
        String unbindValue = (String) value;
        if ("-".equals(unbindValue)) { //$NON-NLS-1$
            unbind = null;
        } else {
            unbind = unbindValue;
            if (!errorLevel.isNone() && serviceType != null) {
                IMethodBinding unbindMethod = findReferenceMethod(methodBinding.getDeclaringClass(),
                        serviceType, unbind);
                if (unbindMethod == null)
                    reportProblem(annotation, "unbind", problems, //$NON-NLS-1$
                            NLS.bind(Messages.AnnotationProcessor_invalidReferenceUnbind, unbind), unbind);
            }
        }
    } else if (serviceType != null) {
        String unbindCandidate;
        if (methodName.startsWith("add")) { //$NON-NLS-1$
            unbindCandidate = "remove" + methodName.substring("add".length()); //$NON-NLS-1$ //$NON-NLS-2$
        } else {
            unbindCandidate = "un" + methodName; //$NON-NLS-1$
        }

        IMethodBinding unbindMethod = findReferenceMethod(methodBinding.getDeclaringClass(), serviceType,
                unbindCandidate);
        if (unbindMethod == null)
            unbind = null;
        else
            unbind = unbindMethod.getName();
    } else {
        unbind = null;
    }

    String policyOption = null;
    if ((value = params.get("policyOption")) instanceof IVariableBinding) { //$NON-NLS-1$
        IVariableBinding policyOptionBinding = (IVariableBinding) value;
        ReferencePolicyOption policyOptionLiteral = ReferencePolicyOption
                .valueOf(policyOptionBinding.getName());
        if (policyOptionLiteral != null) {
            policyOption = policyOptionLiteral.toString();
            requiresV12 = true;
        }
    }

    String updated;
    if ((value = params.get("updated")) instanceof String) { //$NON-NLS-1$
        String updatedValue = (String) value;
        if ("-".equals(updatedValue)) { //$NON-NLS-1$
            updated = null;
        } else {
            updated = updatedValue;
            if (!errorLevel.isNone() && serviceType != null) {
                IMethodBinding updatedMethod = findReferenceMethod(methodBinding.getDeclaringClass(),
                        serviceType, updated);
                if (updatedMethod == null)
                    reportProblem(annotation, "updated", problems, //$NON-NLS-1$
                            NLS.bind(Messages.AnnotationProcessor_invalidReferenceUpdated, updated), updated);
            }
        }

        requiresV12 = true;
    } else if (serviceType != null) {
        String updatedCandidate;
        if (methodName.startsWith("bind")) { //$NON-NLS-1$
            updatedCandidate = "updated" + methodName.substring("bind".length()); //$NON-NLS-1$ //$NON-NLS-2$
        } else if (methodName.startsWith("set")) { //$NON-NLS-1$
            updatedCandidate = "updated" + methodName.substring("set".length()); //$NON-NLS-1$ //$NON-NLS-2$
        } else if (methodName.startsWith("add")) { //$NON-NLS-1$
            updatedCandidate = "updated" + methodName.substring("add".length()); //$NON-NLS-1$ //$NON-NLS-2$
        } else {
            updatedCandidate = "updated" + methodName; //$NON-NLS-1$
        }

        IMethodBinding updatedMethod = findReferenceMethod(methodBinding.getDeclaringClass(), serviceType,
                updatedCandidate);
        if (updatedMethod == null)
            updated = null;
        else
            updated = updatedMethod.getName();
    } else {
        updated = null;
    }

    IDSReference reference = factory.createReference();
    collector.add(reference);

    reference.setReferenceBind(methodName);

    if (name != null)
        reference.setReferenceName(name);

    if (service != null)
        reference.setReferenceInterface(service);

    if (cardinality != null)
        reference.setReferenceCardinality(cardinality);

    if (policy != null)
        reference.setReferencePolicy(policy);

    if (target != null)
        reference.setReferenceTarget(target);

    if (unbind != null)
        reference.setReferenceUnbind(unbind);

    if (policyOption != null)
        reference.setXMLAttribute("policy-option", policyOption); //$NON-NLS-1$

    if (updated != null)
        reference.setXMLAttribute("updated", updated); //$NON-NLS-1$

    return requiresV12;
}

From source file:ca.ecliptical.pde.internal.ds.AnnotationProcessor.java

License:Open Source License

private void validateReferenceBindMethod(Annotation annotation, ITypeBinding serviceType,
        IMethodBinding methodBinding, Collection<DSAnnotationProblem> problems) {
    if (errorLevel.isNone())
        return;//from  w  w  w  .java 2 s  .co  m

    String returnTypeName = methodBinding.getReturnType().getName();
    if (!Void.TYPE.getName().equals(returnTypeName))
        reportProblem(annotation, null, problems,
                NLS.bind(Messages.AnnotationProcessor_invalidBindMethodReturnType, returnTypeName),
                returnTypeName);

    ITypeBinding[] paramTypeBindings = methodBinding.getParameterTypes();
    if (!(paramTypeBindings.length == 1
            && (ServiceReference.class.getName().equals(paramTypeBindings[0].getErasure().getQualifiedName())
                    || serviceType == null || serviceType.isAssignmentCompatible(paramTypeBindings[0])))
            && !(paramTypeBindings.length == 2
                    && (serviceType == null || serviceType.isAssignmentCompatible(paramTypeBindings[0]))
                    && Map.class.getName().equals(paramTypeBindings[1].getErasure().getQualifiedName()))) {
        String[] params = new String[paramTypeBindings.length];
        StringBuilder buf = new StringBuilder(64);
        buf.append('(');
        for (int i = 0; i < params.length; ++i) {
            params[i] = paramTypeBindings[i].getName();
            if (buf.length() > 1)
                buf.append(", "); //$NON-NLS-1$

            buf.append(params[i]);
        }

        buf.append(')');
        reportProblem(annotation, null, problems,
                NLS.bind(Messages.AnnotationProcessor_invalidBindMethodParameters, buf,
                        serviceType == null ? Messages.AnnotationProcessor_unknownServiceTypeLabel
                                : serviceType.getName()),
                params);
    }
}

From source file:ca.ecliptical.pde.internal.ds.AnnotationProcessor.java

License:Open Source License

private IMethodBinding findReferenceMethod(ITypeBinding componentClass, ITypeBinding serviceType, String name) {
    ITypeBinding testedClass = componentClass;

    IMethodBinding candidate = null;//from w  w  w.j av a 2s  . c  o  m
    int priority = 0;
    // priority:
    // 0: <assignment-compatible-type>, Map
    // 1: <exact-type>, Map
    // 2: <assignment-compatible-type>
    // 3: <exact-type>
    do {
        for (IMethodBinding declaredMethod : testedClass.getDeclaredMethods()) {
            if (name.equals(declaredMethod.getName())
                    && Void.TYPE.getName().equals(declaredMethod.getReturnType().getName())
                    && (testedClass.isEqualTo(componentClass)
                            || Modifier.isPublic(declaredMethod.getModifiers())
                            || Modifier.isProtected(declaredMethod.getModifiers())
                            || (!Modifier.isPrivate(declaredMethod.getModifiers())
                                    && testedClass.getPackage().isEqualTo(componentClass.getPackage())))) {
                ITypeBinding[] paramTypes = declaredMethod.getParameterTypes();
                if (paramTypes.length == 1) {
                    if (ServiceReference.class.getName().equals(paramTypes[0].getErasure().getQualifiedName()))
                        // we have the winner
                        return declaredMethod;

                    if (priority < 3 && serviceType.isEqualTo(paramTypes[0]))
                        priority = 3;
                    else if (priority < 2 && serviceType.isAssignmentCompatible(paramTypes[0]))
                        priority = 2;
                    else
                        continue;

                    // we have a (better) candidate
                    candidate = declaredMethod;
                } else if (paramTypes.length == 2) {
                    if (priority < 1 && serviceType.isEqualTo(paramTypes[0])
                            && Map.class.getName().equals(paramTypes[1].getErasure().getQualifiedName()))
                        priority = 1;
                    else if (candidate != null || !serviceType.isAssignmentCompatible(paramTypes[0])
                            || !Map.class.getName().equals(paramTypes[1].getErasure().getQualifiedName()))
                        continue;

                    // we have a candidate
                    candidate = declaredMethod;
                }
            }
        }
    } while ((testedClass = testedClass.getSuperclass()) != null);

    return candidate;
}

From source file:cideplus.ui.astview.TrayContentProvider.java

License:Open Source License

private void addTypeBindingComparions(ArrayList result, Binding trayElement) {
    class IsSubTypeCompatibleProperty extends DynamicBindingProperty {
        public IsSubTypeCompatibleProperty(Binding parent) {
            super(parent);
        }//from   w  w  w. j a va  2 s.  c  o  m

        protected String getName() {
            return "*.isSubTypeCompatible(this): "; //$NON-NLS-1$
        }

        protected String executeQuery(IBinding viewerBinding, IBinding trayBinding) {
            if (viewerBinding instanceof ITypeBinding) {
                ITypeBinding viewerTB = (ITypeBinding) viewerBinding;
                ITypeBinding trayTB = (ITypeBinding) trayBinding;
                return Boolean.toString(viewerTB.isSubTypeCompatible(trayTB));
            } else {
                return "* not an ITypeBinding"; //$NON-NLS-1$
            }
        }
    }
    result.add(new IsSubTypeCompatibleProperty(trayElement));

    class IsCastCompatibleProperty extends DynamicBindingProperty {
        public IsCastCompatibleProperty(Binding parent) {
            super(parent);
        }

        protected String getName() {
            return "*.isCastCompatible(this): "; //$NON-NLS-1$
        }

        protected String executeQuery(IBinding viewerBinding, IBinding trayBinding) {
            if (viewerBinding instanceof ITypeBinding) {
                ITypeBinding viewerTB = (ITypeBinding) viewerBinding;
                ITypeBinding trayTB = (ITypeBinding) trayBinding;
                return Boolean.toString(viewerTB.isCastCompatible(trayTB));
            } else {
                return "* not an ITypeBinding"; //$NON-NLS-1$
            }
        }
    }
    result.add(new IsCastCompatibleProperty(trayElement));

    class IsAssignmentCompatibleProperty extends DynamicBindingProperty {
        public IsAssignmentCompatibleProperty(Binding parent) {
            super(parent);
        }

        protected String getName() {
            return "*.isAssignmentCompatible(this): "; //$NON-NLS-1$
        }

        protected String executeQuery(IBinding viewerBinding, IBinding trayBinding) {
            if (viewerBinding instanceof ITypeBinding) {
                ITypeBinding viewerTB = (ITypeBinding) viewerBinding;
                ITypeBinding trayTB = (ITypeBinding) trayBinding;
                return Boolean.toString(viewerTB.isAssignmentCompatible(trayTB));
            } else {
                return "* not an ITypeBinding"; //$NON-NLS-1$
            }
        }
    }
    result.add(new IsAssignmentCompatibleProperty(trayElement));
}

From source file:com.google.devtools.cyclefinder.ReferenceGraph.java

License:Apache License

private void addFieldEdges() {
    for (ITypeBinding type : allTypes.values()) {
        for (IVariableBinding field : type.getDeclaredFields()) {
            ITypeBinding fieldType = getElementType(field.getType());
            if (!whitelist.containsField(field) && !whitelist.containsType(fieldType)
                    && !fieldType.isPrimitive() && !Modifier.isStatic(field.getModifiers())
                    // Exclude self-referential fields. (likely linked DS or delegate pattern)
                    && !type.isAssignmentCompatible(fieldType) && !BindingUtil.isWeakReference(field)) {
                addEdge(Edge.newFieldEdge(type, field));
            }//ww  w. j  av  a  2s.  co  m
        }
    }
}

From source file:com.google.devtools.j2cpp.gen.CppStatementGenerator.java

License:Open Source License

@SuppressWarnings("unchecked")
@Override/*  w ww .j a  v a2  s .  co m*/
public boolean visit(MethodInvocation node) {
    invocations.push(node);
    String methodName = NameTable.getName(node.getName());
    IMethodBinding binding = Types.getMethodBinding(node);
    assert binding != null;
    // Object receiving the message, or null if it's a method in this class.
    Expression receiver = node.getExpression();
    ITypeBinding receiverType = receiver != null ? Types.getTypeBinding(receiver) : null;
    buffer.append(' ');
    if ((receiverType != null) && (receiver instanceof SimpleName)) {
        buffer.append(((SimpleName) receiver).getIdentifier()).append('.');
    }
    if (Types.isFunction(binding)) {
        buffer.append(methodName);
        buffer.append("(");
        for (Iterator<Expression> it = node.arguments().iterator(); it.hasNext();) {
            it.next().accept(this);
            if (it.hasNext()) {
                buffer.append(", ");
            }
        }
        buffer.append(")");
    } else {
        boolean castAttempted = false;
        boolean castReturnValue = false;
        if (node.getParent() instanceof Expression || node.getParent() instanceof ReturnStatement
                || node.getParent() instanceof VariableDeclarationFragment) {
            ITypeBinding actualType = binding.getMethodDeclaration().getReturnType();
            if (actualType.isArray()) {
                actualType = Types.resolveArrayType(actualType.getComponentType());
            }
            ITypeBinding expectedType;
            if (node.getParent() instanceof VariableDeclarationFragment) {
                expectedType = Types.getTypeBinding(node.getParent());
            } else {
                expectedType = binding.getReturnType();
            }
            if (expectedType.isArray()) {
                expectedType = Types.resolveArrayType(expectedType.getComponentType());
            }
            if (!actualType.isAssignmentCompatible(expectedType)) {
                if (!actualType.isEqualTo(node.getAST().resolveWellKnownType("void"))) {
                    // Since type parameters aren't passed to Obj-C, add cast for it.
                    // However, this is only needed with nested invocations.
                    if (invocations.size() > 0) {
                        // avoid a casting again below, and know to print a closing ')'
                        // after the method invocation.
                        castReturnValue = printCast(expectedType);
                        castAttempted = true;
                    }
                }
            }
        }
        ITypeBinding typeBinding = binding.getDeclaringClass();

        if (receiver != null) {
            boolean castPrinted = false;
            IMethodBinding methodReceiver = Types.getMethodBinding(receiver);
            if (methodReceiver != null) {
                if (methodReceiver.isConstructor()) {
                    // gcc sometimes fails to discern the constructor's type when
                    // chaining, so add a cast.
                    if (!castAttempted) {
                        castPrinted = printCast(typeBinding);
                        castAttempted = true;
                    }
                } else {
                    ITypeBinding receiverReturnType = methodReceiver.getReturnType();
                    if (receiverReturnType.isInterface()) {
                        // Add interface cast, so Obj-C knows the type node's receiver is.
                        if (!castAttempted) {
                            castPrinted = printCast(receiverReturnType);
                            castAttempted = true;
                        }
                    }
                }
            } else {
                IVariableBinding var = Types.getVariableBinding(receiver);
                if (var != null) {
                    if (Types.variableHasCast(var)) {
                        castPrinted = printCast(Types.getCastForVariable(var));
                    }
                }
            }
            //        printNilCheck(receiver, !castPrinted);
            if (castPrinted) {
                buffer.append(')');
            }
        } else {
            //        if ((binding.getModifiers() & Modifier.STATIC) > 0) {
            //          buffer.append(NameTable.getFullName(typeBinding));
            //        } else {
            //          buffer.append("self");
            //        }
        }
        if (binding instanceof IOSMethodBinding) {
            buffer.append(binding.getName());
        } else {
            buffer.append(methodName);
        }
        buffer.append("(");
        printArguments(binding, node.arguments());
        buffer.append(")");
        if (castReturnValue) {
            buffer.append(')');
        }
    }
    invocations.pop();
    return false;
}

From source file:com.google.devtools.j2cpp.translate.AnonymousClassConverter.java

License:Open Source License

private IMethodBinding findSuperConstructorBinding(ITypeBinding clazz, List<Expression> superArgs) {
    if (clazz == null) {
        throw new AssertionError("could not find constructor");
    }//from w ww . j a  va 2  s.  co m
    outer: for (IMethodBinding m : clazz.getDeclaredMethods()) {
        if (m.isConstructor()) {
            ITypeBinding[] paramTypes = m.getParameterTypes();
            if (superArgs.size() == paramTypes.length) {
                for (int i = 0; i < paramTypes.length; i++) {
                    ITypeBinding argType = Types.getTypeBinding(superArgs.get(i)).getErasure();
                    if (!argType.isAssignmentCompatible(paramTypes[i].getErasure())) {
                        continue outer;
                    }
                }
                return m;
            }
        }
    }
    return findSuperConstructorBinding(clazz.getSuperclass(), superArgs);
}

From source file:com.google.devtools.j2cpp.translate.ClassConverter.java

License:Open Source License

/**
 * Returns a list of inner variables that need to be added to an inner type,
 * to resolve its references to outer classes.
 *///w w  w .j  a  v a2s  .  com
protected List<IVariableBinding> getInnerVars(List<ReferenceDescription> references) {
    List<IVariableBinding> innerVars = Lists.newArrayList();
    outer: for (ReferenceDescription desc : references) {
        ITypeBinding declaringClass = desc.declaringClass;
        if (declaringClass == null) {
            declaringClass = desc.binding.getType();
        }
        declaringClass = declaringClass.getTypeDeclaration();
        if (desc.binding.isField()) {
            // Combine references to a type and its supertypes.
            for (int i = 0; i < innerVars.size(); i++) {
                IVariableBinding var = innerVars.get(i);
                ITypeBinding varType = var.getDeclaringClass();
                if (varType != null && varType.isAssignmentCompatible(declaringClass)) {
                    desc.declaringClass = varType;
                    continue outer;
                } else if (varType == null) {
                    desc.declaringMethod = var.getDeclaringMethod();
                }
            }
        }
        if (!innerVars.contains(desc.binding)) {
            innerVars.add(desc.binding);
        }
    }
    return innerVars;
}

From source file:com.google.devtools.j2cpp.translate.InnerClassExtractor.java

License:Open Source License

private void addOuterFields(AbstractTypeDeclaration node) {
    @SuppressWarnings("unchecked")
    List<BodyDeclaration> members = node.bodyDeclarations(); // safe by definition
    AST ast = node.getAST();// w  w w .j  ava  2 s .c  o m
    ITypeBinding clazz = Types.getTypeBinding(node);
    ITypeBinding outerClazz = clazz.getDeclaringClass();
    assert outerClazz != null;

    List<IVariableBinding> innerFields = Lists.newArrayList();
    // Ensure that the new outer field does not conflict with a field in a superclass.
    ITypeBinding superClazz = clazz.getSuperclass();
    ITypeBinding superDeclaringClazz = superClazz.getDeclaringClass();
    int suffix = 0;
    while (superClazz.getDeclaringClass() != null) {
        if (!Modifier.isStatic(superClazz.getModifiers())) {
            suffix++;
        }
        superClazz = superClazz.getSuperclass();
    }
    String outerFieldName = "this$" + suffix;

    FieldDeclaration outerField = createField(outerFieldName, outerClazz, clazz, ast);
    members.add(0, outerField);
    IVariableBinding outerVar = Types.getVariableBinding(outerField.fragments().get(0));
    innerFields.add(outerVar);

    if (superDeclaringClazz != null && !Modifier.isStatic(clazz.getSuperclass().getModifiers())
            && !outerClazz.isAssignmentCompatible(superDeclaringClazz.getTypeDeclaration())) {
        // The super class is an inner class, and it's declaring class and the
        // current node's declaring class don't match, so we need another outer
        // var. This var is only a parameter, not a field, an it's name doesn't
        // matter because addInnerParameters will assign a different name to it
        // anyway.
        IVariableBinding secondOuterVar = new GeneratedVariableBinding("", Modifier.FINAL, superDeclaringClazz,
                false, true, superClazz, null);
        innerFields.add(secondOuterVar);
    }

    // Insert new parameters for each constructor in class.
    boolean needsConstructor = true;
    for (BodyDeclaration member : members) {
        if (member instanceof MethodDeclaration && ((MethodDeclaration) member).isConstructor()) {
            needsConstructor = false;
            MethodDeclaration constructor = (MethodDeclaration) member;
            IMethodBinding oldBinding = Types.getMethodBinding(constructor);
            GeneratedMethodBinding newBinding = new GeneratedMethodBinding(oldBinding);
            Types.addBinding(constructor, newBinding);
            addInnerParameters(constructor, newBinding, innerFields, ast, false);
            assert constructor.parameters().size() == newBinding.getParameterTypes().length;
        }
    }

    if (needsConstructor) {
        MethodDeclaration constructor = ast.newMethodDeclaration();
        constructor.setConstructor(true);
        ITypeBinding voidType = ast.resolveWellKnownType("void");
        GeneratedMethodBinding binding = new GeneratedMethodBinding("init", 0, voidType, clazz, true, false,
                true);
        Types.addBinding(constructor, binding);
        Types.addBinding(constructor.getReturnType2(), voidType);
        SimpleName name = ast.newSimpleName("init");
        Types.addBinding(name, binding);
        constructor.setName(name);
        constructor.setBody(ast.newBlock());
        addInnerParameters(constructor, binding, innerFields, ast, false);
        members.add(constructor);
        assert constructor.parameters().size() == binding.getParameterTypes().length;
    }
}