Example usage for org.eclipse.jdt.internal.compiler.lookup MethodBinding problemId

List of usage examples for org.eclipse.jdt.internal.compiler.lookup MethodBinding problemId

Introduction

In this page you can find the example usage for org.eclipse.jdt.internal.compiler.lookup MethodBinding problemId.

Prototype

public int problemId() 

Source Link

Usage

From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java

License:Open Source License

public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes,
        InvocationSite invocationSite, boolean inStaticContext) {
    ReferenceBinding currentType = receiverType;
    boolean receiverTypeIsInterface = receiverType.isInterface();
    ObjectVector found = new ObjectVector(3);
    CompilationUnitScope unitScope = compilationUnitScope();
    unitScope.recordTypeReferences(argumentTypes);

    if (receiverTypeIsInterface) {
        unitScope.recordTypeReference(receiverType);
        MethodBinding[] receiverMethods = receiverType.getMethods(selector, argumentTypes.length);
        if (receiverMethods.length > 0)
            found.addAll(receiverMethods);
        findMethodInSuperInterfaces(receiverType, selector, found, invocationSite);
        currentType = getJavaLangObject();
    }//  w w w .  j a v  a2 s.c  o m

    // superclass lookup
    long complianceLevel = compilerOptions().complianceLevel;
    boolean isCompliant14 = complianceLevel >= ClassFileConstants.JDK1_4;
    boolean isCompliant15 = complianceLevel >= ClassFileConstants.JDK1_5;
    ReferenceBinding classHierarchyStart = currentType;
    MethodVerifier verifier = environment().methodVerifier();
    while (currentType != null) {
        unitScope.recordTypeReference(currentType);
        currentType = (ReferenceBinding) currentType.capture(this,
                invocationSite == null ? 0 : invocationSite.sourceEnd());
        MethodBinding[] currentMethods = currentType.getMethods(selector, argumentTypes.length);
        int currentLength = currentMethods.length;
        if (currentLength > 0) {
            if (isCompliant14 && (receiverTypeIsInterface || found.size > 0)) {
                nextMethod: for (int i = 0, l = currentLength; i < l; i++) { // currentLength can be modified inside the loop
                    MethodBinding currentMethod = currentMethods[i];
                    if (currentMethod == null)
                        continue nextMethod;
                    if (receiverTypeIsInterface && !currentMethod.isPublic()) { // only public methods from Object are visible to interface receiverTypes
                        currentLength--;
                        currentMethods[i] = null;
                        continue nextMethod;
                    }

                    // if 1.4 compliant, must filter out redundant protected methods from superclasses
                    // protected method need to be checked only - default access is already dealt with in #canBeSeen implementation
                    // when checking that p.C -> q.B -> p.A cannot see default access members from A through B.
                    // if ((currentMethod.modifiers & AccProtected) == 0) continue nextMethod;
                    // BUT we can also ignore any overridden method since we already know the better match (fixes 80028)
                    for (int j = 0, max = found.size; j < max; j++) {
                        MethodBinding matchingMethod = (MethodBinding) found.elementAt(j);
                        MethodBinding matchingOriginal = matchingMethod.original();
                        MethodBinding currentOriginal = matchingOriginal
                                .findOriginalInheritedMethod(currentMethod);
                        if (currentOriginal != null
                                && verifier.isParameterSubsignature(matchingOriginal, currentOriginal)) {
                            if (isCompliant15) {
                                if (matchingMethod.isBridge() && !currentMethod.isBridge())
                                    continue nextMethod; // keep inherited methods to find concrete method over a bridge method
                            }
                            currentLength--;
                            currentMethods[i] = null;
                            continue nextMethod;
                        }
                    }
                }
            }

            if (currentLength > 0) {
                // append currentMethods, filtering out null entries
                if (currentMethods.length == currentLength) {
                    found.addAll(currentMethods);
                } else {
                    for (int i = 0, max = currentMethods.length; i < max; i++) {
                        MethodBinding currentMethod = currentMethods[i];
                        if (currentMethod != null)
                            found.add(currentMethod);
                    }
                }
            }
        }
        currentType = currentType.superclass();
    }

    // if found several candidates, then eliminate those not matching argument types
    int foundSize = found.size;
    MethodBinding[] candidates = null;
    int candidatesCount = 0;
    MethodBinding problemMethod = null;
    boolean searchForDefaultAbstractMethod = isCompliant14 && !receiverTypeIsInterface
            && (receiverType.isAbstract() || receiverType.isTypeVariable());
    if (foundSize > 0) {
        // argument type compatibility check
        for (int i = 0; i < foundSize; i++) {
            MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
            MethodBinding compatibleMethod = computeCompatibleMethod(methodBinding, argumentTypes,
                    invocationSite);
            if (compatibleMethod != null) {
                if (compatibleMethod.isValidBinding()) {
                    if (foundSize == 1 && compatibleMethod.canBeSeenBy(receiverType, invocationSite, this)) {
                        // return the single visible match now
                        if (searchForDefaultAbstractMethod)
                            return findDefaultAbstractMethod(receiverType, selector, argumentTypes,
                                    invocationSite, classHierarchyStart, found, compatibleMethod);
                        unitScope.recordTypeReferences(compatibleMethod.thrownExceptions);
                        return compatibleMethod;
                    }
                    if (candidatesCount == 0)
                        candidates = new MethodBinding[foundSize];
                    candidates[candidatesCount++] = compatibleMethod;
                } else if (problemMethod == null) {
                    problemMethod = compatibleMethod;
                }
            }
        }
    }

    // no match was found
    if (candidatesCount == 0) {
        if (problemMethod != null) {
            switch (problemMethod.problemId()) {
            case ProblemReasons.TypeArgumentsForRawGenericMethod:
            case ProblemReasons.TypeParameterArityMismatch:
                return problemMethod;
            }
        }
        // abstract classes may get a match in interfaces; for non abstract
        // classes, reduces secondary errors since missing interface method
        // error is already reported
        MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes,
                invocationSite, classHierarchyStart, found, null);
        if (interfaceMethod != null)
            return interfaceMethod;
        if (found.size == 0)
            return null;
        if (problemMethod != null)
            return problemMethod;

        // still no match; try to find a close match when the parameter
        // order is wrong or missing some parameters

        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=69471
        // bad guesses are foo(), when argument types have been supplied
        // and foo(X, Y), when the argument types are (int, float, Y)
        // so answer the method with the most argType matches and least parameter type mismatches
        int bestArgMatches = -1;
        MethodBinding bestGuess = (MethodBinding) found.elementAt(0); // if no good match so just use the first one found
        int argLength = argumentTypes.length;
        foundSize = found.size;
        nextMethod: for (int i = 0; i < foundSize; i++) {
            MethodBinding methodBinding = (MethodBinding) found.elementAt(i);
            TypeBinding[] params = methodBinding.parameters;
            int paramLength = params.length;
            int argMatches = 0;
            next: for (int a = 0; a < argLength; a++) {
                TypeBinding arg = argumentTypes[a];
                for (int p = a == 0 ? 0 : a - 1; p < paramLength && p < a + 1; p++) { // look one slot before & after to see if the type matches
                    if (params[p] == arg) {
                        argMatches++;
                        continue next;
                    }
                }
            }
            if (argMatches < bestArgMatches)
                continue nextMethod;
            if (argMatches == bestArgMatches) {
                int diff1 = paramLength < argLength ? 2 * (argLength - paramLength) : paramLength - argLength;
                int bestLength = bestGuess.parameters.length;
                int diff2 = bestLength < argLength ? 2 * (argLength - bestLength) : bestLength - argLength;
                if (diff1 >= diff2)
                    continue nextMethod;
            }
            bestArgMatches = argMatches;
            bestGuess = methodBinding;
        }
        return new ProblemMethodBinding(bestGuess, bestGuess.selector, argumentTypes, ProblemReasons.NotFound);
    }

    // tiebreak using visibility check
    int visiblesCount = 0;
    if (receiverTypeIsInterface) {
        if (candidatesCount == 1) {
            unitScope.recordTypeReferences(candidates[0].thrownExceptions);
            return candidates[0];
        }
        visiblesCount = candidatesCount;
    } else {
        for (int i = 0; i < candidatesCount; i++) {
            MethodBinding methodBinding = candidates[i];
            if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) {
                if (visiblesCount != i) {
                    candidates[i] = null;
                    candidates[visiblesCount] = methodBinding;
                }
                visiblesCount++;
            }
        }
        switch (visiblesCount) {
        case 0:
            MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes,
                    invocationSite, classHierarchyStart, found, null);
            if (interfaceMethod != null)
                return interfaceMethod;
            return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters,
                    ProblemReasons.NotVisible);
        case 1:
            if (searchForDefaultAbstractMethod)
                return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite,
                        classHierarchyStart, found, candidates[0]);
            unitScope.recordTypeReferences(candidates[0].thrownExceptions);
            return candidates[0];
        default:
            break;
        }
    }

    if (complianceLevel <= ClassFileConstants.JDK1_3) {
        ReferenceBinding declaringClass = candidates[0].declaringClass;
        return !declaringClass.isInterface()
                ? mostSpecificClassMethodBinding(candidates, visiblesCount, invocationSite)
                : mostSpecificInterfaceMethodBinding(candidates, visiblesCount, invocationSite);
    }

    // check for duplicate parameterized methods
    if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
        for (int i = 0; i < visiblesCount; i++) {
            MethodBinding candidate = candidates[i];
            if (candidate instanceof ParameterizedGenericMethodBinding)
                candidate = ((ParameterizedGenericMethodBinding) candidate).originalMethod;
            if (candidate.hasSubstitutedParameters()) {
                for (int j = i + 1; j < visiblesCount; j++) {
                    MethodBinding otherCandidate = candidates[j];
                    if (otherCandidate.hasSubstitutedParameters()) {
                        if (otherCandidate == candidate
                                || (candidate.declaringClass == otherCandidate.declaringClass
                                        && candidate.areParametersEqual(otherCandidate))) {
                            return new ProblemMethodBinding(candidates[i], candidates[i].selector,
                                    candidates[i].parameters, ProblemReasons.Ambiguous);
                        }
                    }
                }
            }
        }
    }
    if (inStaticContext) {
        MethodBinding[] staticCandidates = new MethodBinding[visiblesCount];
        int staticCount = 0;
        for (int i = 0; i < visiblesCount; i++)
            if (candidates[i].isStatic())
                staticCandidates[staticCount++] = candidates[i];
        if (staticCount == 1)
            return staticCandidates[0];
        if (staticCount > 1)
            return mostSpecificMethodBinding(staticCandidates, staticCount, argumentTypes, invocationSite,
                    receiverType);
    }

    MethodBinding mostSpecificMethod = mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes,
            invocationSite, receiverType);
    if (searchForDefaultAbstractMethod) { // search interfaces for a better match
        if (mostSpecificMethod.isValidBinding())
            // see if there is a better match in the interfaces - see AutoBoxingTest 99, LookupTest#81
            return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite,
                    classHierarchyStart, found, mostSpecificMethod);
        // see if there is a match in the interfaces - see LookupTest#84
        MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes,
                invocationSite, classHierarchyStart, found, null);
        if (interfaceMethod != null
                && interfaceMethod.isValidBinding() /* else return the same error as before */)
            return interfaceMethod;
    }
    return mostSpecificMethod;
}

From source file:org.eclipse.jdt.internal.compiler.lookup.Scope.java

License:Open Source License

public MethodBinding getImplicitMethod(char[] selector, TypeBinding[] argumentTypes,
        InvocationSite invocationSite) {

    boolean insideStaticContext = false;
    boolean insideConstructorCall = false;
    boolean insideTypeAnnotation = false;
    MethodBinding foundMethod = null;//  w  w w. j a v a  2  s  .  c  o  m
    MethodBinding foundProblem = null;
    boolean foundProblemVisible = false;
    Scope scope = this;
    int depth = 0;
    // in 1.4 mode (inherited visible shadows enclosing)
    CompilerOptions options;
    boolean inheritedHasPrecedence = (options = compilerOptions()).complianceLevel >= ClassFileConstants.JDK1_4;

    done: while (true) { // done when a COMPILATION_UNIT_SCOPE is found
        switch (scope.kind) {
        case METHOD_SCOPE:
            MethodScope methodScope = (MethodScope) scope;
            insideStaticContext |= methodScope.isStatic;
            insideConstructorCall |= methodScope.isConstructorCall;
            insideTypeAnnotation = methodScope.insideTypeAnnotation;
            break;
        case CLASS_SCOPE:
            ClassScope classScope = (ClassScope) scope;
            ReferenceBinding receiverType = classScope.enclosingReceiverType();
            if (!insideTypeAnnotation) {
                // retrieve an exact visible match (if possible)
                // compilationUnitScope().recordTypeReference(receiverType);   not needed since receiver is the source type
                MethodBinding methodBinding = classScope.findExactMethod(receiverType, selector, argumentTypes,
                        invocationSite);
                if (methodBinding == null)
                    methodBinding = classScope.findMethod(receiverType, selector, argumentTypes,
                            invocationSite);
                if (methodBinding != null) { // skip it if we did not find anything
                    if (foundMethod == null) {
                        if (methodBinding.isValidBinding()) {
                            if (!methodBinding.isStatic() && (insideConstructorCall || insideStaticContext)) {
                                if (foundProblem != null
                                        && foundProblem.problemId() != ProblemReasons.NotVisible)
                                    return foundProblem; // takes precedence
                                return new ProblemMethodBinding(methodBinding, // closest match
                                        methodBinding.selector, methodBinding.parameters,
                                        insideConstructorCall
                                                ? ProblemReasons.NonStaticReferenceInConstructorInvocation
                                                : ProblemReasons.NonStaticReferenceInStaticContext);
                            }
                            if (inheritedHasPrecedence || receiverType == methodBinding.declaringClass
                                    || (receiverType.getMethods(selector)) != Binding.NO_METHODS) {
                                // found a valid method in the 'immediate' scope (i.e. not inherited)
                                // OR in 1.4 mode (inherited visible shadows enclosing)
                                // OR the receiverType implemented a method with the correct name
                                // return the methodBinding if it is not declared in a superclass of the scope's binding (that is, inherited)
                                if (foundProblemVisible) {
                                    return foundProblem;
                                }
                                if (depth > 0) {
                                    invocationSite.setDepth(depth);
                                    invocationSite.setActualReceiverType(receiverType);
                                }
                                // special treatment for Object.getClass() in 1.5 mode (substitute parameterized return type)
                                if (argumentTypes == Binding.NO_PARAMETERS
                                        && CharOperation.equals(selector, TypeConstants.GETCLASS)
                                        && methodBinding.returnType.isParameterizedType()/*1.5*/) {
                                    return environment().createGetClassMethod(receiverType, methodBinding,
                                            this);
                                }
                                return methodBinding;
                            }

                            if (foundProblem == null || foundProblem.problemId() == ProblemReasons.NotVisible) {
                                if (foundProblem != null)
                                    foundProblem = null;
                                // only remember the methodBinding if its the first one found
                                // remember that private methods are visible if defined directly by an enclosing class
                                if (depth > 0) {
                                    invocationSite.setDepth(depth);
                                    invocationSite.setActualReceiverType(receiverType);
                                }
                                foundMethod = methodBinding;
                            }
                        } else { // methodBinding is a problem method
                            if (methodBinding.problemId() != ProblemReasons.NotVisible
                                    && methodBinding.problemId() != ProblemReasons.NotFound)
                                return methodBinding; // return the error now
                            if (foundProblem == null) {
                                foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible
                            }
                            if (!foundProblemVisible && methodBinding.problemId() == ProblemReasons.NotFound) {
                                MethodBinding closestMatch = ((ProblemMethodBinding) methodBinding).closestMatch;
                                if (closestMatch != null
                                        && closestMatch.canBeSeenBy(receiverType, invocationSite, this)) {
                                    foundProblem = methodBinding; // hold onto the first not visible/found error and keep the second not found if first is not visible
                                    foundProblemVisible = true;
                                }
                            }
                        }
                    } else { // found a valid method so check to see if this is a hiding case
                        if (methodBinding.problemId() == ProblemReasons.Ambiguous
                                || (foundMethod.declaringClass != methodBinding.declaringClass
                                        && (receiverType == methodBinding.declaringClass
                                                || receiverType.getMethods(selector) != Binding.NO_METHODS)))
                            // ambiguous case -> must qualify the method (javac generates an ambiguous error instead)
                            // otherwise if a method was found, complain when another is found in an 'immediate' enclosing type (that is, not inherited)
                            // NOTE: Unlike fields, a non visible method hides a visible method
                            return new ProblemMethodBinding(methodBinding, // closest match
                                    selector, argumentTypes, ProblemReasons.InheritedNameHidesEnclosingName);
                    }
                }
            }
            insideTypeAnnotation = false;
            depth++;
            insideStaticContext |= receiverType.isStatic();
            // 1EX5I8Z - accessing outer fields within a constructor call is permitted
            // in order to do so, we change the flag as we exit from the type, not the method
            // itself, because the class scope is used to retrieve the fields.
            MethodScope enclosingMethodScope = scope.methodScope();
            insideConstructorCall = enclosingMethodScope == null ? false
                    : enclosingMethodScope.isConstructorCall;
            break;
        case COMPILATION_UNIT_SCOPE:
            break done;
        }
        scope = scope.parent;
    }

    if (insideStaticContext && options.sourceLevel >= ClassFileConstants.JDK1_5) {
        if (foundProblem != null) {
            if (foundProblem.declaringClass != null
                    && foundProblem.declaringClass.id == TypeIds.T_JavaLangObject)
                return foundProblem; // static imports lose to methods from Object
            if (foundProblem.problemId() == ProblemReasons.NotFound && foundProblemVisible) {
                return foundProblem; // visible method selectors take precedence
            }
        }

        // at this point the scope is a compilation unit scope & need to check for imported static methods
        CompilationUnitScope unitScope = (CompilationUnitScope) scope;
        unitScope.faultInImports(); // field constants can cause static imports to be accessed before they're resolved
        ImportBinding[] imports = unitScope.imports;
        if (imports != null) {
            ObjectVector visible = null;
            boolean skipOnDemand = false; // set to true when matched static import of method name so stop looking for on demand methods
            for (int i = 0, length = imports.length; i < length; i++) {
                ImportBinding importBinding = imports[i];
                if (importBinding.isStatic()) {
                    Binding resolvedImport = importBinding.resolvedImport;
                    MethodBinding possible = null;
                    if (importBinding.onDemand) {
                        if (!skipOnDemand && resolvedImport instanceof ReferenceBinding)
                            // answers closest approximation, may not check argumentTypes or visibility
                            possible = findMethod((ReferenceBinding) resolvedImport, selector, argumentTypes,
                                    invocationSite, true);
                    } else {
                        if (resolvedImport instanceof MethodBinding) {
                            MethodBinding staticMethod = (MethodBinding) resolvedImport;
                            if (CharOperation.equals(staticMethod.selector, selector))
                                // answers closest approximation, may not check argumentTypes or visibility
                                possible = findMethod(staticMethod.declaringClass, selector, argumentTypes,
                                        invocationSite, true);
                        } else if (resolvedImport instanceof FieldBinding) {
                            // check to see if there are also methods with the same name
                            FieldBinding staticField = (FieldBinding) resolvedImport;
                            if (CharOperation.equals(staticField.name, selector)) {
                                // must find the importRef's type again since the field can be from an inherited type
                                char[][] importName = importBinding.reference.tokens;
                                TypeBinding referencedType = getType(importName, importName.length - 1);
                                if (referencedType != null)
                                    // answers closest approximation, may not check argumentTypes or visibility
                                    possible = findMethod((ReferenceBinding) referencedType, selector,
                                            argumentTypes, invocationSite, true);
                            }
                        }
                    }
                    if (possible != null && possible != foundProblem) {
                        if (!possible.isValidBinding()) {
                            if (foundProblem == null)
                                foundProblem = possible; // answer as error case match
                        } else if (possible.isStatic()) {
                            MethodBinding compatibleMethod = computeCompatibleMethod(possible, argumentTypes,
                                    invocationSite);
                            if (compatibleMethod != null) {
                                if (compatibleMethod.isValidBinding()) {
                                    if (compatibleMethod.canBeSeenBy(unitScope.fPackage)) {
                                        if (visible == null || !visible.contains(compatibleMethod)) {
                                            ImportReference importReference = importBinding.reference;
                                            if (importReference != null) {
                                                importReference.bits |= ASTNode.Used;
                                            }
                                            if (!skipOnDemand && !importBinding.onDemand) {
                                                visible = null; // forget previous matches from on demand imports
                                                skipOnDemand = true;
                                            }
                                            if (visible == null)
                                                visible = new ObjectVector(3);
                                            visible.add(compatibleMethod);
                                        }
                                    } else if (foundProblem == null) {
                                        foundProblem = new ProblemMethodBinding(compatibleMethod, selector,
                                                compatibleMethod.parameters, ProblemReasons.NotVisible);
                                    }
                                } else if (foundProblem == null) {
                                    foundProblem = compatibleMethod;
                                }
                            } else if (foundProblem == null) {
                                foundProblem = new ProblemMethodBinding(possible, selector, argumentTypes,
                                        ProblemReasons.NotFound);
                            }
                        }
                    }
                }
            }
            if (visible != null) {
                MethodBinding[] temp = new MethodBinding[visible.size];
                visible.copyInto(temp);
                foundMethod = mostSpecificMethodBinding(temp, temp.length, argumentTypes, invocationSite, null);
            }
        }
    }

    if (foundMethod != null) {
        invocationSite.setActualReceiverType(foundMethod.declaringClass);
        return foundMethod;
    }
    if (foundProblem != null)
        return foundProblem;

    return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
}

From source file:org.eclipse.objectteams.otdt.internal.codeassist.SelectionOnMethodSpec.java

License:Open Source License

@Override
public void resolveFinished() {
    MethodBinding binding = this.resolvedMethod;
    // tolerate some error cases
    if (binding == null || !(binding.isValidBinding() || binding.problemId() == ProblemReasons.NotVisible
            || binding.problemId() == ProblemReasons.InheritedNameHidesEnclosingName
            || binding.problemId() == ProblemReasons.NonStaticReferenceInConstructorInvocation
            || binding.problemId() == ProblemReasons.NonStaticReferenceInStaticContext)) {
        throw new SelectionNodeFound();
    } else {/*  www  .  j a  va 2s .c  o  m*/
        //{ObjectTeams:
        //method is part of a role
        if (binding.declaringClass.isRole()) {
            // method is copy inherited: use the original binding:
            if (binding.copyInheritanceSrc != null)
                throw new SelectionNodeFound(binding.copyInheritanceSrc);
        }
        //haebor}
    }
    throw new SelectionNodeFound(this.resolvedMethod);
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend.java

License:Open Source License

@Override
protected TypeBinding findMethodBinding(BlockScope scope) {

    // check: is a tsuper call legal in the current context?

    AbstractMethodDeclaration context = scope.methodScope().referenceMethod();
    if (context == null || !CharOperation.equals(this.selector, context.selector)
            || context.binding.parameters.length != this.argumentTypes.length) {
        scope.problemReporter().tsuperCallsWrongMethod(this);
        return null;
    }//  ww w .j  ava 2  s .c  o  m

    ReferenceBinding receiverRole;
    if (!(this.actualReceiverType instanceof ReferenceBinding)
            || !(receiverRole = (ReferenceBinding) this.actualReceiverType).isSourceRole()) {
        scope.problemReporter().tsuperOutsideRole(context, this, this.actualReceiverType);
        return null;
    }

    ReferenceBinding[] tsuperRoleBindings = receiverRole.roleModel.getTSuperRoleBindings();
    if (tsuperRoleBindings.length == 0) {
        scope.problemReporter().tsuperCallWithoutTsuperRole(receiverRole, this);
        return null;
    }

    // context is OK, start searching:

    this.tsuperReference.resolveType(scope);
    // qualified tsuper? => directly search within the designated tsuper role:
    if (this.tsuperReference.qualification != null) {
        TypeBinding tsuperRole = this.tsuperReference.resolvedType;
        if (tsuperRole == null || !tsuperRole.isRole())
            return null;
        this.binding = scope.getMethod(tsuperRole, this.selector, this.argumentTypes, this);
        if (!this.binding.isValidBinding() && ((ProblemMethodBinding) this.binding).declaringClass == null)
            this.binding.declaringClass = (ReferenceBinding) tsuperRole;
        resolvePolyExpressionArguments(this, this.binding, this.argumentTypes, scope);
        return this.binding.returnType;
    }
    // no qualification => search all tsupers by priority:
    MethodBinding bestMatch = null;
    for (int i = tsuperRoleBindings.length - 1; i >= 0; i--) {
        ReferenceBinding tsuperRole = tsuperRoleBindings[i];
        MethodBinding candidate = scope.getMethod(tsuperRole, this.selector, this.argumentTypes, this);
        if (candidate.isValidBinding()) {
            if (scope.parameterCompatibilityLevel(candidate, this.argumentTypes) != Scope.COMPATIBLE) {
                scope.problemReporter().tsuperCallsWrongMethod(this);
                return candidate.returnType;
            }
            this.binding = candidate;
            resolvePolyExpressionArguments(this, this.binding, this.argumentTypes, scope);
            return this.binding.returnType;
        }
        if (bestMatch == null || (bestMatch.problemId() == ProblemReasons.NotFound
                && candidate.problemId() != ProblemReasons.NotFound))
            bestMatch = candidate;
    }
    if (bestMatch == null)
        bestMatch = new ProblemMethodBinding(this.selector, this.argumentTypes, ProblemReasons.NotFound);
    if (bestMatch.declaringClass == null)
        bestMatch.declaringClass = (ReferenceBinding) this.tsuperReference.resolvedType;
    this.binding = bestMatch;
    return this.binding.returnType;
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend.java

License:Open Source License

@Override
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
    // for code gen we need to add the marker arg... 
    int len = this.binding.parameters.length;
    TypeBinding[] extendedParameters = new TypeBinding[len + 1];
    System.arraycopy(this.binding.parameters, 0, extendedParameters, 0, len);
    char[] tSuperMarkName = TSuperHelper.getTSuperMarkName(this.tsuperReference.resolvedType.enclosingType());
    extendedParameters[len] = currentScope.getType(tSuperMarkName);

    // ... and find the copied method binding
    MethodBinding codegenBinding = currentScope.getMethod(this.actualReceiverType, this.selector,
            extendedParameters, this);

    if (codegenBinding.problemId() == ProblemReasons.NotFound) {
        // tsuper.m() may in fact refer to tsuper.super.m().
        // try to find the method as super.tsuper() instead:
        ReferenceBinding superRole = ((ReferenceBinding) this.receiver.resolvedType).superclass();
        codegenBinding = getAlternateMethod(currentScope, superRole, extendedParameters);
        if (codegenBinding == null)
            codegenBinding = getAlternateMethod(currentScope, superRole, this.binding.parameters);
        if (codegenBinding == null)
            throw new InternalCompilerError("cannot find real method binding for tsuper call!"); //$NON-NLS-1$

        this.receiver = new SuperReference(this.receiver.sourceStart, this.receiver.sourceEnd);
        this.receiver.resolvedType = superRole;
        this.receiver.constant = Constant.NotAConstant;
        this.actualReceiverType = superRole;
    }//from w ww .j  a va  2s .  co  m

    MethodBinding tsuperMethod = this.binding;
    this.binding = codegenBinding;
    try {
        super.generateCode(currentScope, codeStream, valueRequired);
    } finally {
        this.binding = tsuperMethod;
    }

    if (valueRequired && this.binding.isCallin()) {
        if (this.resolvedType != null && this.resolvedType.isValidBinding()) {
            if (this.resolvedType.isBaseType()) {
                // something like: ((Integer)result).intValue()
                char[][] boxtypeName = AstGenerator.boxTypeName((BaseTypeBinding) this.resolvedType);
                codeStream.checkcast(currentScope.getType(boxtypeName, 3));
                codeStream.generateUnboxingConversion(this.resolvedType.id);
            } else {
                // (RefType)result
                codeStream.checkcast(this.resolvedType);
            }
        }
    }
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.ast.TSuperMessageSend.java

License:Open Source License

private MethodBinding getAlternateMethod(Scope scope, ReferenceBinding superRole,
        TypeBinding[] extendedArgumentTypes) {
    MethodBinding alternateMethod = scope.getMethod(superRole, this.selector, extendedArgumentTypes, this);
    if (alternateMethod.problemId() == ProblemReasons.NotVisible) {
        return alternateMethod; // want to see this error as IProblem.IndirectTSuperInvisible, cf. ProblemReporter.invalidMethod
    }/*from w w w.j ava 2 s  .  co m*/
    MethodBinding alternateSrc = alternateMethod.copyInheritanceSrc;
    // TODO(SH): binary verbatim copies (no marker arg) are not recognized as copies!
    if (alternateSrc != null && isRoleOfSuperTeam(alternateSrc.declaringClass, scope))
        return alternateMethod;
    return null;
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding.java

License:Open Source License

/** Get the problemId of the first erroneous method binding or NoError. */
public int problemId() {
    if (this._roleMethodBinding != null && !this._roleMethodBinding.isValidBinding())
        return this._roleMethodBinding.problemId();
    if (this._baseMethods != null)
        for (MethodBinding method : this._baseMethods)
            if (!method.isValidBinding())
                return method.problemId();
    if (this._baseField != null)
        return this._baseField.problemId();
    return ProblemReasons.NoError;
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementor.java

License:Open Source License

/** This method drives the creation of a callout implementation for one callout mapping. */
private MethodDeclaration createCallout(CalloutMappingDeclaration calloutMappingDeclaration, boolean needBody,
        boolean isInferred) {
    CallinCalloutScope calloutScope = calloutMappingDeclaration.scope;

    calloutMappingDeclaration.updateTSuperMethods();

    // This binding is part of the interface part of a role:
    MethodBinding roleMethodBinding = calloutMappingDeclaration.getRoleMethod();

    if (roleMethodBinding == null) // CLOVER: never true in jacks suite
    {//  w w w .  j  a v a  2  s  .  c  o m
        // problemreporting already done in find-Base/Role-MethodBinding
        assert (calloutMappingDeclaration.ignoreFurtherInvestigation);
        return null;
    }
    if (!roleMethodBinding.isValidBinding()) {
        if (roleMethodBinding.problemId() != ProblemReasons.NotFound) {
            // CLOVER: never true in jacks suite
            calloutMappingDeclaration.tagAsHavingErrors();
            // hopefully error has been reported!
            return null;
        } else { // shorthand style callout
            // help sourceMethod() below to find another callout method
            MethodBinding existingMethod = calloutScope.enclosingSourceType().getExactMethod(
                    roleMethodBinding.selector, roleMethodBinding.parameters,
                    calloutScope.compilationUnitScope());
            if (existingMethod != null)
                roleMethodBinding = existingMethod;
        }
    }

    MethodDeclaration roleMethodDeclaration = null;
    if (TypeBinding.equalsEquals(roleMethodBinding.declaringClass, calloutScope.enclosingSourceType()))
        roleMethodDeclaration = (MethodDeclaration) roleMethodBinding.sourceMethod();

    // have a binding but no declaration for method? -> requires creation of declaration
    boolean foundRoleDecl = roleMethodDeclaration != null;
    MethodBinding overriddenTSuper = null;
    // The following code allows to use tsuper in parameter mappings
    // (see 3.2.32-otjld-tsuper-access-1)
    if (foundRoleDecl && roleMethodDeclaration.isCopied // foundRoleDecl => (roleMethodDeclaration != null)
            && (roleMethodDeclaration.modifiers & AccAbstract) == 0
            && !TSuperHelper.isTSuper(roleMethodDeclaration.binding)) {
        // mapping conflicts with an implicitly inherited method.
        // make the latter a tsuper version, now.
        overriddenTSuper = roleMethodBinding;
        // save a clone of the method binding before adding the marker arg, for use below.
        roleMethodBinding = new MethodBinding(roleMethodBinding, roleMethodBinding.declaringClass); // clone

        TSuperHelper.addMarkerArg(roleMethodDeclaration,
                roleMethodDeclaration.binding.copyInheritanceSrc.declaringClass.enclosingType());
        foundRoleDecl = false; // re-create the method;
    }

    if (!foundRoleDecl) {
        roleMethodDeclaration = createAbstractRoleMethodDeclaration(roleMethodBinding,
                calloutMappingDeclaration);
        if (overriddenTSuper != null)
            roleMethodDeclaration.binding.addOverriddenTSuper(overriddenTSuper);
    } else {
        roleMethodDeclaration.isReusingSourceMethod = true; // foundRoleDecl => (roleMethodDeclaration != null)
        // mark existing method as generated by the callout mapping:
        roleMethodDeclaration.isMappingWrapper = WrapperKind.CALLOUT;

        // match locator may want to know this for the interface part, too:
        // (SH: unsure, if this is really needed, but it doesn't hurt either ;-)
        if (roleMethodDeclaration.interfacePartMethod != null) {
            roleMethodDeclaration.interfacePartMethod.isReusingSourceMethod = true;
            roleMethodDeclaration.interfacePartMethod.isMappingWrapper = WrapperKind.CALLOUT;
        }
    }

    if (calloutMappingDeclaration.hasSignature) {
        // Adjust arguments:
        Argument[] args = calloutMappingDeclaration.roleMethodSpec.arguments;
        if (args != null) {
            for (int i = 0; i < args.length; i++) {
                // if we already have a declaration and if we have signatures
                // in the mapping declaration, use the argument names from the
                // method mapping rather than those from the original declaration
                // (needed for parameter mapping!).
                if (foundRoleDecl)
                    roleMethodDeclaration.arguments[i].updateName(args[i].name);

                // also link best names of arguments of roleMethodSpec and actual wrapper
                // ( requires wrapper argument to be bound, do this first.
                //   Note that all args must be bound in order!).
                roleMethodDeclaration.arguments[i].bind(roleMethodDeclaration.scope, args[i].binding.type,
                        false);
                args[i].binding.setBestNameFromStat(roleMethodDeclaration.arguments[i]);
            }
        }
    }

    if (roleMethodDeclaration != null) // try again
    {
        // Note: do not query the binding (as isAbstract() would do).
        // Binding may have corrected modifiers, but take the raw modifiers.
        if (!roleMethodDeclaration.isCopied && !roleMethodDeclaration.isGenerated
                && (roleMethodDeclaration.modifiers & AccAbstract) == 0) {
            // bad overriding of existing / non-existant methods is handled in MethodMappingResolver already
            roleMethodDeclaration.ignoreFurtherInvestigation = true; // don't throw "abstract method.. can only be defined by abstract class" error
            calloutScope.problemReporter().calloutOverridesLocal(this._role.getAst(), calloutMappingDeclaration,
                    roleMethodDeclaration.binding);
            return null;
        }

        // fix flags (even if not needing body):
        roleMethodDeclaration.isCopied = false;
        int flagsToRemove = AccAbstract | ExtraCompilerModifiers.AccSemicolonBody | AccNative;
        roleMethodDeclaration.modifiers &= ~flagsToRemove;
        roleMethodDeclaration.binding.modifiers &= ~flagsToRemove;
        roleMethodDeclaration.isGenerated = true; // even if not generated via AstGenerator.
        if (needBody && calloutMappingDeclaration.binding.isValidBinding()) {
            // defer generation of statements:
            final CalloutMappingDeclaration mappingDeclaration = calloutMappingDeclaration;
            MethodModel methodModel = MethodModel.getModel(roleMethodDeclaration);
            if (isInferred)
                methodModel._inferredCallout = mappingDeclaration;
            methodModel.setStatementsGenerator(new AbstractStatementsGenerator() {
                public boolean generateStatements(AbstractMethodDeclaration methodDecl) {
                    createCalloutMethodBody((MethodDeclaration) methodDecl, mappingDeclaration);
                    return true;
                }
            });
        } else if (calloutMappingDeclaration.ignoreFurtherInvestigation) {
            roleMethodDeclaration.binding.bytecodeMissing = true; // will not be generated, so don't complain later.
        }
    } else // roleMethodDeclaration still null
    {
        // CLOVER: never reached in jacks suite ;-)
        throw new InternalCompilerError("OT-Compiler Error: couldn't create method declaration for callout! " //$NON-NLS-1$
                + calloutMappingDeclaration.toString());
    }
    return roleMethodDeclaration;
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.mappings.CalloutImplementor.java

License:Open Source License

/**
  * Creates method in interface or class-part of _role.
 * @param templateBinding this method is used as a template for the method that
 *        will be created.// w ww .  ja v  a2  s . c  o m
 * @param calloutBindingDeclaration
 * @param part CLASS or INTERFACE
 * @return an empty method declaration
 */
private MethodDeclaration createAbstractRoleMethodDeclarationPart(MethodBinding templateBinding,
        CalloutMappingDeclaration calloutBindingDeclaration, int modifiers, int part) {
    assert (templateBinding != null);

    AstGenerator gen = new AstGenerator(calloutBindingDeclaration.sourceStart,
            calloutBindingDeclaration.sourceEnd);
    TypeBinding returnType;
    if (calloutBindingDeclaration.roleMethodSpec.returnType != null)
        // if this one is given, it might be instantiated:
        returnType = calloutBindingDeclaration.roleMethodSpec.returnType.resolvedType;
    else
        // this one should exist in any case:
        returnType = calloutBindingDeclaration.roleMethodSpec.resolvedMethod.returnType;
    MethodDeclaration newMethod = gen.method(calloutBindingDeclaration.compilationResult, modifiers, // start from these, adapt below.
            returnType, templateBinding.selector, copyArguments(gen, calloutBindingDeclaration.scope,
                    templateBinding.parameters, calloutBindingDeclaration.roleMethodSpec));
    newMethod.typeParameters = getTypeParameters(calloutBindingDeclaration.hasSignature, templateBinding,
            calloutBindingDeclaration.roleMethodSpec, gen);
    if (templateBinding.problemId() == ProblemReasons.NotFound) {
        // this is a short hand callout declaration:
        MethodSpec baseMethodSpec = calloutBindingDeclaration.baseMethodSpec;
        if (baseMethodSpec != null) { // null if missing in source code (e.g. during completion)
            if (baseMethodSpec.isStatic())
                newMethod.modifiers |= AccStatic;
            if (baseMethodSpec.resolvedMethod != null) {
                newMethod.thrownExceptions = AstClone.copyExceptions(baseMethodSpec.resolvedMethod, gen);
            }
        }
    } else {
        newMethod.thrownExceptions = AstClone.copyExceptions(templateBinding, gen);
    }
    newMethod.isMappingWrapper = WrapperKind.CALLOUT;

    if (part == INTERFACE) {
        // generated callout method must also be added to the interface-part since
        // role-splitting already happened
        // Note: Interface part has the access modifiers!
        newMethod.modifiers |= ExtraCompilerModifiers.AccSemicolonBody | AccAbstract;
        AstEdit.addMethod(this._role.getInterfaceAst(), newMethod);
    } else // == CLASS
    {
        if ((modifiers & AccPrivate) != 0) { // don't advertize in ifc
            // FIXME(SH): need to generate bridge methdods?
        } else if (calloutBindingDeclaration.binding.inferred.isAdvertisedInInterface()) { // only if actually advertised in the ifc-part
            // generated callout method must be public in the classPart.
            // access control is done only via the interface part.
            MethodModel.getModel(newMethod).storeModifiers(newMethod.modifiers);
            newMethod.modifiers &= ~(AccProtected);
            newMethod.modifiers |= AccPublic;
        }
        // abstract will be cleared once we are done.
        AstEdit.addMethod(this._role.getAst(), newMethod);
    }
    calloutBindingDeclaration.updateRoleMethod(newMethod.binding);
    return newMethod;
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.mappings.MethodMappingResolver.java

License:Open Source License

/**
  * Resolve everything about a callin binding except for argument mappings if present.
  * Reports as many errors as can be found.
  * @return true if no error occurred/*  w  w w .  ja  v a  2 s. c om*/
  */
private boolean resolveCalloutMapping(CalloutMappingDeclaration calloutMappingDeclaration) {
    if (calloutMappingDeclaration.scope == null) { // severe error
        assert calloutMappingDeclaration.hasErrors();
        return false;
    }

    // main resolving task:
    // A callout-with-signatures should always resolve its base method,
    // because that base method could determine the static flag.
    calloutMappingDeclaration.resolveMethodSpecs(this._role, this._role.getBaseTypeBinding(),
            this.resolveBaseMethods || calloutMappingDeclaration.hasSignature);

    //      This binding is part of the interface part of a role:
    MethodBinding roleMethodBinding = calloutMappingDeclaration.roleMethodSpec.resolvedMethod;

    calloutMappingDeclaration.binding._roleMethodBinding = roleMethodBinding;
    if (this.resolveBaseMethods) {
        MethodSpec baseMethodSpec = calloutMappingDeclaration.baseMethodSpec;
        if (baseMethodSpec != null) {
            if (baseMethodSpec.resolvedMethod != null) {
                calloutMappingDeclaration.binding._baseMethods = new MethodBinding[] {
                        baseMethodSpec.resolvedMethod };
            } else if (baseMethodSpec instanceof FieldAccessSpec
                    && ((FieldAccessSpec) baseMethodSpec).resolvedField != null) {
                calloutMappingDeclaration.binding._baseField = ((FieldAccessSpec) baseMethodSpec).resolvedField;
            } else {
                calloutMappingDeclaration.binding._baseMethods = Binding.NO_METHODS;
                calloutMappingDeclaration.tagAsHavingErrors();
            }
        }
    }
    if (roleMethodBinding != null
            && (roleMethodBinding.isValidBinding() || (roleMethodBinding.problemId() == ProblemReasons.NotFound
                    && calloutMappingDeclaration.hasSignature))) // short-hand, method will be generated
    {
        // store the methodMapping in a map indexed by the role method's name&signature 
        // for later duplication check.
        String methodKey = String
                .valueOf(CharOperation.concat(roleMethodBinding.selector, roleMethodBinding.signature()));
        List<CalloutMappingDeclaration> mappings = this._foundRoleMethods.get(methodKey);
        if (mappings == null) {
            mappings = new LinkedList<CalloutMappingDeclaration>();
            this._foundRoleMethods.put(methodKey, mappings);
        }
        mappings.add(calloutMappingDeclaration);
    }
    return !calloutMappingDeclaration.hasErrors();
}