List of usage examples for org.eclipse.jdt.internal.compiler.lookup Scope environment
public final LookupEnvironment environment()
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; }