Example usage for org.eclipse.jdt.internal.compiler.lookup Scope environment

List of usage examples for org.eclipse.jdt.internal.compiler.lookup Scope environment

Introduction

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

Prototype

public final LookupEnvironment environment() 

Source Link

Usage

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

License:Open Source License

public MethodBinding getStaticFactory(ReferenceBinding allocationType, ReferenceBinding originalEnclosingType,
        TypeBinding[] argumentTypes, final InvocationSite allocationSite) {
    TypeVariableBinding[] classTypeVariables = allocationType.typeVariables();
    int classTypeVariablesArity = classTypeVariables.length;
    MethodBinding[] methods = allocationType.getMethods(TypeConstants.INIT, argumentTypes.length);
    MethodBinding[] staticFactories = new MethodBinding[methods.length];
    int sfi = 0;//  w w w  .  ja v a2  s.  c o m
    for (int i = 0, length = methods.length; i < length; i++) {
        MethodBinding method = methods[i];
        int paramLength = method.parameters.length;
        boolean isVarArgs = method.isVarargs();
        if (argumentTypes.length != paramLength)
            if (!isVarArgs || argumentTypes.length < paramLength - 1)
                continue; // incompatible
        TypeVariableBinding[] methodTypeVariables = method.typeVariables();
        int methodTypeVariablesArity = methodTypeVariables.length;

        MethodBinding staticFactory = new MethodBinding(method.modifiers | ClassFileConstants.AccStatic,
                TypeConstants.SYNTHETIC_STATIC_FACTORY, null, null, null, method.declaringClass);
        staticFactory.typeVariables = new TypeVariableBinding[classTypeVariablesArity
                + methodTypeVariablesArity];
        final SimpleLookupTable map = new SimpleLookupTable(classTypeVariablesArity + methodTypeVariablesArity);
        // Rename each type variable T of the type to T'
        final LookupEnvironment environment = environment();
        for (int j = 0; j < classTypeVariablesArity; j++) {
            map.put(classTypeVariables[j],
                    staticFactory.typeVariables[j] = new TypeVariableBinding(
                            CharOperation.concat(classTypeVariables[j].sourceName, "'".toCharArray()), //$NON-NLS-1$
                            staticFactory, j, environment));
        }
        // Rename each type variable U of method U to U''.
        for (int j = classTypeVariablesArity, max = classTypeVariablesArity
                + methodTypeVariablesArity; j < max; j++) {
            map.put(methodTypeVariables[j - classTypeVariablesArity],
                    (staticFactory.typeVariables[j] = new TypeVariableBinding(
                            CharOperation.concat(methodTypeVariables[j - classTypeVariablesArity].sourceName,
                                    "''".toCharArray()), //$NON-NLS-1$
                            staticFactory, j, environment)));
        }
        ReferenceBinding enclosingType = originalEnclosingType;
        while (enclosingType != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=345968
            if (enclosingType.kind() == Binding.PARAMETERIZED_TYPE) {
                final ParameterizedTypeBinding parameterizedType = (ParameterizedTypeBinding) enclosingType;
                final ReferenceBinding genericType = parameterizedType.genericType();
                TypeVariableBinding[] enclosingClassTypeVariables = genericType.typeVariables();
                int enclosingClassTypeVariablesArity = enclosingClassTypeVariables.length;
                for (int j = 0; j < enclosingClassTypeVariablesArity; j++) {
                    map.put(enclosingClassTypeVariables[j], parameterizedType.arguments[j]);
                }
            }
            enclosingType = enclosingType.enclosingType();
        }
        final Scope scope = this;
        Substitution substitution = new Substitution() {
            public LookupEnvironment environment() {
                return scope.environment();
            }

            public boolean isRawSubstitution() {
                return false;
            }

            public TypeBinding substitute(TypeVariableBinding typeVariable) {
                TypeBinding retVal = (TypeBinding) map.get(typeVariable);
                return retVal != null ? retVal : typeVariable;
            }
        };

        // initialize new variable bounds
        for (int j = 0, max = classTypeVariablesArity + methodTypeVariablesArity; j < max; j++) {
            TypeVariableBinding originalVariable = j < classTypeVariablesArity ? classTypeVariables[j]
                    : methodTypeVariables[j - classTypeVariablesArity];
            TypeBinding substitutedType = (TypeBinding) map.get(originalVariable);
            if (substitutedType instanceof TypeVariableBinding) {
                TypeVariableBinding substitutedVariable = (TypeVariableBinding) substitutedType;
                TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
                ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution,
                        originalVariable.superInterfaces);
                if (originalVariable.firstBound != null) {
                    substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass
                            ? substitutedSuperclass // could be array type or interface
                            : substitutedInterfaces[0];
                }
                switch (substitutedSuperclass.kind()) {
                case Binding.ARRAY_TYPE:
                    substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT,
                            null);
                    substitutedVariable.superInterfaces = substitutedInterfaces;
                    break;
                default:
                    if (substitutedSuperclass.isInterface()) {
                        substitutedVariable.superclass = environment
                                .getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
                        int interfaceCount = substitutedInterfaces.length;
                        System.arraycopy(substitutedInterfaces, 0,
                                substitutedInterfaces = new ReferenceBinding[interfaceCount + 1], 1,
                                interfaceCount);
                        substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
                        substitutedVariable.superInterfaces = substitutedInterfaces;
                    } else {
                        substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface
                        substitutedVariable.superInterfaces = substitutedInterfaces;
                    }
                }
            }
        }
        TypeVariableBinding[] returnTypeParameters = new TypeVariableBinding[classTypeVariablesArity];
        for (int j = 0; j < classTypeVariablesArity; j++) {
            returnTypeParameters[j] = (TypeVariableBinding) map.get(classTypeVariables[j]);
        }
        staticFactory.returnType = environment.createParameterizedType(allocationType, returnTypeParameters,
                allocationType.enclosingType());
        staticFactory.parameters = Scope.substitute(substitution, method.parameters);
        staticFactory.thrownExceptions = Scope.substitute(substitution, method.thrownExceptions);
        if (staticFactory.thrownExceptions == null) {
            staticFactory.thrownExceptions = Binding.NO_EXCEPTIONS;
        }
        staticFactories[sfi++] = new ParameterizedMethodBinding(
                (ParameterizedTypeBinding) environment.convertToParameterizedType(staticFactory.declaringClass),
                staticFactory);
    }
    if (sfi == 0)
        return null;
    if (sfi != methods.length) {
        System.arraycopy(staticFactories, 0, staticFactories = new MethodBinding[sfi], 0, sfi);
    }
    MethodBinding[] compatible = new MethodBinding[sfi];
    int compatibleIndex = 0;
    for (int i = 0; i < sfi; i++) {
        MethodBinding compatibleMethod = computeCompatibleMethod(staticFactories[i], argumentTypes,
                allocationSite);
        if (compatibleMethod != null) {
            if (compatibleMethod.isValidBinding())
                compatible[compatibleIndex++] = compatibleMethod;
        }
    }

    if (compatibleIndex == 0) {
        return null;
    }
    MethodBinding[] visible = new MethodBinding[compatibleIndex];
    int visibleIndex = 0;
    for (int i = 0; i < compatibleIndex; i++) {
        MethodBinding method = compatible[i];
        if (method.canBeSeenBy(allocationSite, this))
            visible[visibleIndex++] = method;
    }
    if (visibleIndex == 0) {
        return null;
    }
    return visibleIndex == 1 ? visible[0]
            : mostSpecificMethodBinding(visible, visibleIndex, argumentTypes, allocationSite, allocationType);
}

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

License:Open Source License

/**
 * Create a DependentTypeBinding from a type reference and a TypeAnchorReference.
 * Performs the following checks:/*from   ww w.  ja v a 2s  . c om*/
 * - does the type denoted by typeReference have a value parameter?
 * - does this anchor reference match the declared type of the corresponding value parameter?
 *
 * PRE: this.anchor and typeReference have already been resolved,
 *      however, resolving of typeReference has not yet considered any parameters.
 *
 * @param scope
 * @param typeReference     the type reference decorated with this type anchor.
 * @param typeParamPosition position within the type parameter list of the generic type
 * @return a DependentTypeBinding, or and array thereof or null;
 */
public TypeBinding createDependentTypeBinding(Scope scope, TypeReference typeReference, int typeParamPosition) {
    TypeBinding type = typeReference.resolvedType;
    ITeamAnchor anchorBinding = null;
    if (this.anchor instanceof NameReference)
        anchorBinding = (ITeamAnchor) ((NameReference) this.anchor).binding;
    else if (this.anchor instanceof FieldReference)
        anchorBinding = ((FieldReference) this.anchor).binding;
    if (anchorBinding != null && type instanceof ReferenceBinding && type.isValidBinding()) {
        ReferenceBinding refBinding = (ReferenceBinding) type;
        VariableBinding currentParam = refBinding.valueParamSynthArgAt(typeParamPosition);
        if (currentParam == null) {
            scope.problemReporter().typeHasNoValueParamAt(typeReference, refBinding, typeParamPosition);
            return null;
        }
        if (currentParam.type instanceof UnresolvedReferenceBinding) {
            currentParam.type = ((UnresolvedReferenceBinding) currentParam.type).resolve(scope.environment(),
                    false);
        }
        if (currentParam.isValidBinding()
                && !anchorBinding.isTypeCompatibleWith((ReferenceBinding) currentParam.type)) {
            scope.problemReporter().incompatibleValueParameter(this, currentParam);
            return null;
        }
        TypeBinding[] typeArguments = refBinding.isParameterizedType()
                ? ((ParameterizedTypeBinding) refBinding).arguments
                : null;
        return anchorBinding.getDependentTypeBinding(refBinding, typeParamPosition, typeArguments,
                typeReference.dimensions());
    } else {
        scope.problemReporter().invalidType(typeReference,
                new ProblemReferenceBinding(typeReference.getTypeName(), null, ProblemReasons.NotFound));
        return null;
    }
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer.java

License:Open Source License

/**
 * When generating code for a role class, copy all non-wide string/integer constants
 * from all tsuper roles in order to reserve constant pool positions below 256.
 * Note, that this strategy is not safe, since multiple tsupers may introduce any
 * number of constants below 256 :(//from   w w w .j a v a 2 s  .c om
 */
public void checkCopyNonWideConstants(Scope scope, ClassFile classFile) {
    SourceTypeBinding dstType = classFile.referenceBinding;
    this._writer = new ConstantPoolObjectWriter(classFile);
    if (dstType.isRole() && !dstType.isInterface()) // for all role classes
    {

        ReferenceBinding[] tsuperRoles = dstType.roleModel.getTSuperRoleBindings();
        for (int i = 0; i < tsuperRoles.length; i++) // for all tsuper roles
        {
            RoleModel srcRole = tsuperRoles[i].roleModel;
            if (srcRole == null || !srcRole.hasByteCode())
                continue;
            byte[] srcConstantPool = srcRole.getByteCode();
            if (srcConstantPool == null)
                continue; // be shy, no idea how it could happen

            this._reader = new ConstantPoolObjectReader(srcRole, srcConstantPool, scope.environment());

            copyAllNonWideConstants(srcRole.getConstantPoolOffsets().length,
                    srcRole.getBinding().enclosingType(), dstType);
        }
    }
    if (dstType.isTeam()) {
        ReferenceBinding orgObjectteamsTeam = scope.getOrgObjectteamsTeam();
        if (!TypeAnalyzer.isOrgObjectteamsTeam(dstType) && !dstType.superclass.isTeam()) {
            TeamMethodGenerator tmg = scope.environment().getTeamMethodGenerator();
            if (tmg.requestBytes()) { // if o.o.Team is converted we don't have the bytecode - and shouldn't need it
                this._reader = new ConstantPoolObjectReader(tmg.classBytes, tmg.constantPoolOffsets,
                        orgObjectteamsTeam.getTeamModel(), scope.environment());
                copyAllNonWideConstants(tmg.constantPoolOffsets.length, dstType.superclass, dstType);
            }
        }

        TeamModel srcModel = dstType.superclass.getTeamModel();
        if (srcModel == null)
            return;
        // if the team has a copied ctor (w/ arg-lifting), bytecodes
        // for the team need to be copied from the super-team, too:
        for (MethodBinding method : dstType.methods()) {
            method = method.copyInheritanceSrc;
            if (method == null || method.model == null)
                continue; // shouldn't happen anyway
            TeamModel methodSrcTeam = srcModel;
            if (TypeBinding.notEquals(method.declaringClass, srcModel.getBinding())) {
                // copied from implicit super team - find the source:
                if (!method.declaringClass.isTeam())
                    continue;
                methodSrcTeam = method.declaringClass.getTeamModel();
            }
            if (!method.model.hasBytes())
                continue; // method not relevant for copying
            this._reader = new ConstantPoolObjectReader(method.model, methodSrcTeam, scope.environment());
            copyAllNonWideConstants(method.model.getConstantPoolOffsets().length, methodSrcTeam.getBinding(),
                    dstType);
            return; // triggered by any method, this team class is fully handled.
        }
    }
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.lifting.DeclaredLifting.java

License:Open Source License

/**
 * Copy a team constructor such that the copy is suitable for chaining
 * previous super calls through a chain of tsuper-calls. This enables
 * a team to insert lifting calls at all required locations.
 *
 * In a subteam where the role is bound, the role parameter has to be replaced
 * with the bound base class (signature & selfcall).
 *
 * @param scope          scope of location triggering this copy operation
 * @param superTeamCtor constructor to be copied
 * @param providedArgs  this are the types of arguments passed by the ExplicitConstructorCall
 * @param needsLifting  has the context (initiating constructor decl) declared lifting?
 */// w  w  w  .  j a  va 2s. c o  m
public static MethodBinding copyTeamConstructorForDeclaredLifting(Scope scope, MethodBinding superTeamCtor,
        TypeBinding[] providedArgs, boolean needsLifting) {
    TypeDeclaration teamDecl = scope.referenceType();
    AstGenerator gen = new AstGenerator(scope.methodScope().referenceMethod().sourceStart,
            scope.methodScope().referenceMethod().sourceEnd);

    if (scope.isOrgObjectteamsTeam(superTeamCtor.declaringClass))
        return maybeCreateTurningCtor(teamDecl, superTeamCtor, gen);

    // Parameter list with marker arg
    TypeBinding[] providedWithMarker = providedArgs;
    if (providedArgs.length == 0 || !TSuperHelper.isMarkerInterface(providedArgs[providedArgs.length - 1])) {
        // need to extend the param list
        TypeBinding lastParam = null;
        if (superTeamCtor.parameters.length > 0)
            lastParam = superTeamCtor.parameters[superTeamCtor.parameters.length - 1];
        TypeBinding marker = (lastParam != null && TSuperHelper.isMarkerInterface(lastParam)) ? // prefer existing marker
                lastParam : TSuperHelper.getMarkerInterface(scope, superTeamCtor.declaringClass);

        providedWithMarker = AstEdit.extendTypeArray(providedArgs, marker);
    }

    // Inner self call:
    MethodBinding selfcall = null;
    AbstractMethodDeclaration src = superTeamCtor.sourceMethod();
    if (src != null) {
        if (src.ignoreFurtherInvestigation)
            return null; // can't create ctor

        // src means: look in the AST
        ConstructorDeclaration srcCtor = (ConstructorDeclaration) src;
        if (src.isCopied) {
            if (src.model != null)
                selfcall = src.model.adjustedSelfcall;
        } else if (srcCtor.constructorCall != null) {
            Dependencies.ensureTeamState(superTeamCtor.declaringClass.getTeamModel(),
                    ITranslationStates.STATE_RESOLVED);
            selfcall = srcCtor.constructorCall.binding;
        } else {
            if (!src.scope.compilationUnitScope().referenceContext.parseMethodBodies) {
                // that's why we have no constructorCall: CU is on diet (parse); use a fake (see Trac #142):
                MethodBinding result = new MethodBinding(ClassFileConstants.AccPublic, providedArgs, null,
                        superTeamCtor.declaringClass);
                return result;
            }
            selfcall = superTeamCtor.declaringClass.superclass().getExactConstructor(Binding.NO_PARAMETERS);
        }
    } else if (superTeamCtor.bytecodeMissing || superTeamCtor.model == null) {
        return null; // can't create ctor.
    } else {
        // no src means: peek the byte code:
        selfcall = (new BytecodeTransformer()).peekConstructorCall(teamDecl.getTeamModel(), superTeamCtor.model,
                scope.environment());
    }
    MethodBinding adjustedSelfcall = null;
    if (selfcall == null) {
        if (!superTeamCtor.bytecodeMissing) // may have been set by peedConstructorCall above
            scope.problemReporter().unsupportedRoleDataflow(scope.methodScope().referenceMethod(),
                    superTeamCtor);
        // be sure to continue below, because client needs the new ctor.
    } else {

        TypeBinding[] selfCallProvidedArgs = providedWithMarker;// TODO(SH): fetch argument order from bytecode

        adjustedSelfcall = maybeCopyCtorForSelfCall(scope, selfcall, selfCallProvidedArgs, needsLifting, gen);

        // Check for presence of desired constructor:
        MethodBinding existingConstructor = teamDecl.binding.getExactConstructor(providedWithMarker);
        if (existingConstructor != null) {
            if (adjustedSelfcall != null) {
                MethodModel model = MethodModel.getModel(existingConstructor);
                model.adjustSelfcall(selfcall, adjustedSelfcall);
            }
            return existingConstructor;
        }
    }

    // Create new constructor:
    ConstructorDeclaration newCtor = gen.constructor(teamDecl.compilationResult, ClassFileConstants.AccPublic,
            teamDecl.name, AstConverter.createArgumentsFromParameters(providedWithMarker, gen));

    // adjust argument-anchored types in this signature:
    for (int i = 0; i < superTeamCtor.parameters.length; i++)
        if (RoleTypeBinding.isRoleWithExplicitAnchor(superTeamCtor.parameters[i])) {
            RoleTypeBinding requiredRTB = (RoleTypeBinding) superTeamCtor.parameters[i];
            if (requiredRTB._argumentPosition > -1) {
                // we have an arg-anchored type, adjust the anchor within this signature:
                Argument newArgument = newCtor.arguments[requiredRTB._argumentPosition]; // argument positions from the declared (super) ctor.
                newArgument.modifiers |= ClassFileConstants.AccFinal;
                newArgument.name = ((RoleTypeBinding) providedArgs[i])._teamAnchor.internalName(); // argument names from the provided types/arguments
            }
        }

    newCtor.isTSuper = true; // ??
    newCtor.isCopied = true;
    AstEdit.addMethod(teamDecl, newCtor, false /*not synthetic*/, false/*addToFront*/, superTeamCtor); // incl. resolve
    MethodModel model = MethodModel.getModel(newCtor); // already connect binding.
    if (needsLifting)
        model.liftedParams = superTeamCtor.parameters; // instructions for BytecodeTransformer
    if (adjustedSelfcall != null)
        model.adjustSelfcall(selfcall, adjustedSelfcall); // be it only strengthening
    newCtor.binding.copiedInContext = teamDecl.binding;
    newCtor.sourceMethodBinding = superTeamCtor;

    return newCtor.binding;
}

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

License:Open Source License

private TypeBinding instantiateParameter(final Scope scope, final TypeBinding parameter, final int i,
        final MethodBinding currentMethod, final boolean isMethodEnhanced) {
    return RoleTypeCreator.deepSubstitute(parameter, scope.environment(), new IDependentTypeSubstitution() {
        @SuppressWarnings("synthetic-access")
        public TypeBinding substitute(DependentTypeBinding paramDependentType, TypeBinding[] typeArguments,
                int dimensions) {
            int srcIdx = isMethodEnhanced ? (i - AnchorMapping.this._methodSignatureEnhancer.ENHANCING_ARG_LEN)
                    : i;//from ww w. j  a  v a 2s. co  m
            ITeamAnchor anchor = null;
            if (AnchorMapping.this._arguments != null)
                anchor = translateAnchor(scope, AnchorMapping.this._arguments[srcIdx], paramDependentType,
                        currentMethod);

            // missing a required anchor?
            if (anchor == null && paramDependentType.hasAnchorWithinThisMethodsSignature(currentMethod))
                return new ProblemReferenceBinding(paramDependentType.sourceName(), paramDependentType,
                        ProblemReasons.AnchorNotFound);

            if (anchor == null && AnchorMapping.this._receiver != null) {
                if (DependentTypeBinding.isDependentTypeOf(AnchorMapping.this._receiver.resolvedType,
                        paramDependentType._teamAnchor)) {
                    DependentTypeBinding depReceiver = (DependentTypeBinding) AnchorMapping.this._receiver.resolvedType;
                    return depReceiver._teamAnchor.getRoleTypeBinding(paramDependentType, typeArguments,
                            dimensions);
                }
                ITeamAnchor newAnchor = TeamAnchor.getTeamAnchor(AnchorMapping.this._receiver);
                if (newAnchor != null && newAnchor.isValidBinding()
                        && newAnchor != paramDependentType._teamAnchor) {
                    if (paramDependentType._teamAnchor.isPrefixLegal(scope.enclosingSourceType(), newAnchor)) {
                        newAnchor = paramDependentType._teamAnchor.setPathPrefix(newAnchor);
                        return newAnchor.getRoleTypeBinding(paramDependentType, typeArguments, dimensions);
                    }
                }
                if (DependentTypeBinding.isDependentTypeVariable(currentMethod.parameters[i])) {
                    TypeVariableBinding typeVariable = (TypeVariableBinding) ((DependentTypeBinding) currentMethod.parameters[i]).type;
                    ITeamAnchor[] anchors = typeVariable.anchors;
                    if (anchors != null && anchors[0] instanceof LocalVariableBinding) { // FIXME(SH): more positions?
                        int pos = ((LocalVariableBinding) anchors[0]).resolvedPosition;
                        if (pos < AnchorMapping.this._arguments.length)
                            anchor = translateAnchor(scope, AnchorMapping.this._arguments[pos],
                                    (DependentTypeBinding) currentMethod.parameters[i], currentMethod);
                    }
                }
            }
            if ((anchor = validAnchor(anchor)) != null) {
                // downgrading allowed:
                return anchor.getRoleTypeBinding(paramDependentType, typeArguments, dimensions);
            }
            return paramDependentType;
        }
    });
}

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

License:Open Source License

public static MethodBinding ensureAccessor(Scope scope, ReferenceBinding baseType, boolean isStatic) {
    if (baseType.isRoleType())
        baseType = baseType.getRealClass();
    char[] selector = isStatic ? OT_ACCESS_STATIC : OT_ACCESS;
    MethodBinding[] methods = baseType.getMethods(selector);
    if (methods != null && methods.length == 1) {
        return methods[0];
    } else {/*from   ww  w  .  j ava  2s  .  co m*/
        int modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccSynthetic;
        if (isStatic)
            modifiers |= ClassFileConstants.AccStatic;
        MethodBinding method = new MethodBinding(modifiers, selector, scope.getJavaLangObject(),
                new TypeBinding[] { TypeBinding.INT, TypeBinding.INT,
                        scope.environment().createArrayType(scope.getJavaLangObject(), 1),
                        scope.getOrgObjectteamsITeam() },
                Binding.NO_EXCEPTIONS, baseType);
        baseType.addMethod(method);
        return method;
    }
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.RoleMigrationImplementor.java

License:Open Source License

/**
 * PHASE 2: Type checking for invocations of migrateToXXX().
 *
 * @param originalMethod method before type parameter substitution
 * @param arguments       actual argument types of the current invocation
 * @param substitutes    type variable bindings
 * @param scope/* w  w  w .  j  a  va2  s. c o m*/
 * @param invocationSite
 * @return null if not a migrate-method call, otherwise (a) a problem method binding (ProblemAlreadyReported) or (b) a valid method substitute
 */
public static MethodBinding getMigrateMethodSubstitute(MethodBinding originalMethod, TypeBinding[] arguments,
        TypeBinding[] substitutes, Scope scope, InvocationSite invocationSite) {
    if (!(invocationSite instanceof MessageSend))
        return null;
    MessageSend send = (MessageSend) invocationSite;
    if (!(send.actualReceiverType instanceof ReferenceBinding))
        return null;

    ReferenceBinding roleType = ((ReferenceBinding) send.actualReceiverType).getRealType();
    TypeBinding typeArgument = null;
    boolean haveReportedError = false;

    if (CharOperation.equals(originalMethod.selector, IOTConstants.MIGRATE_TO_TEAM)) {
        Expression sendArgument = send.arguments[0];
        ITeamAnchor anchorBinding = TeamAnchor.getTeamAnchor(sendArgument);
        if (anchorBinding == null) {
            scope.problemReporter().migrateToNonTeam(sendArgument);
            haveReportedError = true;
        } else {
            ReferenceBinding anchorType = (ReferenceBinding) anchorBinding.getResolvedType();
            if (TypeBinding.notEquals(anchorType.getRealClass(), roleType.enclosingType())) {
                scope.problemReporter().migrateToWrongTeam(sendArgument, anchorType, roleType);
                haveReportedError = true;
            }
        }
        if (!haveReportedError)
            typeArgument = RoleTypeCreator.getAnchoredType(scope, send, anchorBinding, roleType, null, 0); // FIXME(SH): type parameters
    } else if (CharOperation.equals(originalMethod.selector, IOTConstants.MIGRATE_TO_BASE)) {
        TypeBinding baseType = arguments[0];
        if (!baseType.isCompatibleWith(roleType.baseclass())) {
            scope.problemReporter().migrateToWrongBase(send.arguments[0], baseType, roleType,
                    roleType.baseclass());
            haveReportedError = true;
        }

        typeArgument = baseType;
    } else {
        return null;
    }
    if (haveReportedError)
        return new ProblemMethodBinding(originalMethod, originalMethod.selector, substitutes,
                ProblemReasons.ProblemAlreadyReported);
    // substitution was successful
    return new ParameterizedGenericMethodBinding(originalMethod, new TypeBinding[] { typeArgument },
            scope.environment());
}

From source file:org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.StandardElementGenerator.java

License:Open Source License

/**
 * Retreive (or create) a team level method used for casting an expression to a role.
 * After casting also check the containingInstance against the current team.
 * @param teamModel/* w  w  w .  java 2s .co  m*/
 * @param roleType
 * @param scope (used only for lookup of j.l.Object)
 * @param searchSuper  should super classes of teamClass be search, too?
 * @param sourceStart
 * @param sourceEnd
 * @return the method
 */
public static MethodBinding getCastMethod(TeamModel teamModel, ReferenceBinding roleType, Scope scope,
        int dimensions, boolean searchSuper, int sourceStart, int sourceEnd) {
    /*
     * protected <role> _OT$castTo$<role> (Object _OT$arg1) {
     *    if (_OT$arg1 == null) return null;
     *      __OT__<role> role = (__OT__<role>) _OT$arg1;
     *    if (role._OT$getTeam() != this)
     *         throw new RuntimeException();
     *    return role;
     * }
     *OR FOR ARRAY:
     * protected <role>[].. _OT$castTo$<role>$<dims> (Object[].. _OT$arg1) {
     *    if (_OT$arg1 == null) return null;
     *      <role>[].. role = (<role>[]..) _OT$arg1;
     *    if (role.length > 0 && ((__OT__<role>)role[0])._OT$getTeam() != this) // TODO(SH): extract through several dims
     *         throw new RuntimeException();
     *    return role;
     * }
     * NOTE(SH): it suffices to check team equivalence for one element, since at this point it
     *           must already be a role-array, which cannot mix roles from different teams ;-)
     */
    boolean shouldWeaken = (teamModel.getState() >= ITranslationStates.STATE_TYPES_ADJUSTED); // weakening for other methods already done?
    MethodBinding superMethod = null;

    roleType = roleType.getRealType();
    char[] methodName = CharOperation.concat(CAST_PREFIX, roleType.sourceName());
    if (dimensions > 0)
        methodName = CharOperation.concat(methodName, String.valueOf(dimensions).toCharArray(), '$');
    ReferenceBinding teamBinding = teamModel.getBinding();
    while (teamBinding != null) {
        MethodBinding[] methods = teamBinding.getMethods(methodName);
        if (methods != null && methods.length == 1) {
            if (TypeBinding.equalsEquals(methods[0].declaringClass, teamModel.getBinding()) || searchSuper)
                return methods[0];
            // go ahead and generate a new method, but use superMethod for weakening after generating:
            superMethod = methods[0];
            break;
        }
        if (!searchSuper && !shouldWeaken)
            break;
        teamBinding = teamBinding.superclass();
    }

    TypeDeclaration teamClass = teamModel.getAst();
    if (teamClass == null) {
        if (true) {// FIXME(SH): team has error?
            MethodBinding castMethod = new MethodBinding(AccPublic, methodName, roleType,
                    new TypeBinding[] { scope.getJavaLangObject() }, null, teamModel.getBinding());
            teamModel.getBinding().addMethod(castMethod);
            return castMethod;
        }
        throw new InternalCompilerError("Required cast method not found."); //$NON-NLS-1$
    }

    AstGenerator gen = new AstGenerator(sourceStart, sourceEnd);

    // --- method header ---
    int modifiers = 0;
    boolean clearPrivateModifier = false;
    if (roleType.isPublic()) {
        modifiers = AccPublic;
    } else {
        // this weird combination allows to return a non-public role and will
        // grant access across packages in the byte code.
        modifiers = AccProtected;
        clearPrivateModifier = true;
        // See also BinaryTypeBinding.resolveTypesFor(MethodBinding) where the Protected flag is restored.
    }
    // args
    char[] argName = OT_DOLLAR_ARG.toCharArray();

    // find the appropriate top-level-super-type:
    ReferenceBinding exprType = teamClass.scope.getJavaLangObject();
    //      if (!roleType.isStrictlyCompatibleWith(exprType)) {
    //         exprType = (ReferenceBinding)teamClass.scope.getType(ORG_OBJECTTEAMS_ICONFINED, 3);
    //         if (!roleType.isCompatibleWith(exprType))
    //            exprType = (ReferenceBinding)teamClass.scope.getType(
    //                  ORG_OBJECTTEAMS_TEAM_DOT_CONFINED,
    //                  4);
    //      }
    TypeReference exprTypeRef = gen.typeReference(exprType);

    MethodDeclaration castMethod = gen.method(teamClass.compilationResult(), modifiers,
            gen.createArrayTypeReference(roleType, dimensions), methodName,
            new Argument[] { gen.argument(argName, exprTypeRef) });
    // see org.eclipse.objectteams.otdt.tests.otjld.regression.ReportedBugs.testB11_sh15():
    // pre-set return type to prevent problems with resolving lateron
    TypeBinding returnType = dimensions == 0 ? roleType
            : scope.environment().createArrayType(roleType, dimensions);
    castMethod.returnType.resolvedType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(returnType, teamBinding);

    // <role> role = (<role>)_OT$arg;
    TypeReference arrayCastType = gen.createArrayTypeReference(roleType, dimensions);
    LocalDeclaration castedLocalVar = gen.localVariable(ROLE, arrayCastType,
            gen.castExpression(gen.singleNameReference(argName), arrayCastType, CastExpression.RAW));

    //STATEMENTS:
    // if (_OT$arg1 == null) return null;
    //AND
    //   if (role._OT$getTeam() != this)
    //      throw new RuntimeException();
    //  OR
    //   if (role.length > 0 && ((<roleClass>)role[0])._OT$getTeam() != this)
    //      throw new RuntimeException();

    Statement nullCheck = gen.ifStatement(gen.nullCheck(gen.singleNameReference(argName)),
            gen.returnStatement(gen.nullLiteral()));

    Expression teamCheckCondition;
    teamCheckCondition = genTeamCheck(gen, OperatorIds.NOT_EQUAL, gen.singleNameReference(ROLE),
            gen.thisReference(), dimensions);

    if (dimensions > 0)
        teamCheckCondition = gen
                .setPos(new AND_AND_Expression(
                        gen.equalExpression(gen.qualifiedNameReference(new char[][] { ROLE, LENGTH }),
                                gen.intLiteral(0), OperatorIds.GREATER),
                        teamCheckCondition, OperatorIds.AND_AND));

    // here we go:
    castMethod.setStatements(new Statement[] { nullCheck, castedLocalVar, gen.ifStatement(teamCheckCondition,
            gen.throwStatement(
                    gen.allocation(gen.qualifiedTypeReference(ROLE_CAST_EXCEPTION), new Expression[0]))),
            // return role;
            gen.returnStatement(gen.singleNameReference(ROLE)) });
    castMethod.isGenerated = true;
    AstEdit.addGeneratedMethod(teamClass, castMethod);
    if (clearPrivateModifier)
        castMethod.binding.tagBits = TagBits.ClearPrivateModifier;

    if (superMethod != null)
        CopyInheritance.weakenSignature(castMethod, superMethod);
    return castMethod.binding;
}