private void addFactoryMethod(EclipseNode singletonClass, TypeDeclaration astNode, TypeReference typeReference, TypeDeclaration innerClass, FieldDeclaration field) { MethodDeclaration factoryMethod = new MethodDeclaration(astNode.compilationResult); factoryMethod.modifiers = AccStatic | ClassFileConstants.AccPublic; factoryMethod.returnType = typeReference; factoryMethod.sourceStart = astNode.sourceStart; factoryMethod.sourceEnd = astNode.sourceEnd; factoryMethod.selector = "getInstance".toCharArray(); factoryMethod.bits = ECLIPSE_DO_NOT_TOUCH_FLAG; long pS = factoryMethod.sourceStart; long pE = factoryMethod.sourceEnd; long p = (long) pS << 32 | pE; FieldReference ref = new FieldReference(field.name, p); ref.receiver = new SingleNameReference(innerClass.name, p); ReturnStatement statement = new ReturnStatement(ref, astNode.sourceStart, astNode.sourceEnd); factoryMethod.statements = new Statement[]{statement}; EclipseHandlerUtil.injectMethod(singletonClass, factoryMethod); }
@Override public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { return analyseCode(currentScope, flowContext, flowInfo, true); }
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { this.generateCompoundAssignment( currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], expression, operator, assignmentImplicitConversion, valueRequired); }
} else { variableType = checkFieldAccess(scope); if (isTypeUseDeprecated(type, scope)) scope.problemReporter().deprecatedType(type, this); type = scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/); return this.resolvedType = reportError(scope);
if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == this.binding)) { variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.right, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); && (((operation.right.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) != TypeIds.T_JavaLangString)) { // exclude string concatenation which would occur backwards variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.left, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { generateReceiver(codeStream); fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion);
case Binding.FIELD : // reading a field if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.LOCAL: LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // check if compound assignment is the only usage of this local Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired); break; case Binding.FIELD: // check if compound assignment is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, (FieldBinding)this.binding, valueRequired); } this.generateCompoundAssignment( currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], expression, operator, assignmentImplicitConversion, valueRequired); }
codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { generateReceiver(codeStream); checkEffectiveFinality(localBinding, currentScope); switch (isUnboxing ? postConversionType(currentScope).id : this.resolvedType.id) { case T_long : case T_double :
if (isFieldUseDeprecated(fieldBinding, scope, this.bits)) scope.problemReporter().deprecatedField(fieldBinding, this);
reportOnlyUselesslyReadPrivateField(currentScope, fieldBinding, valueRequired); FieldBinding codegenField = fieldBinding.original(); if (codegenField.isStatic()) { codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); fieldStore(currentScope, codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, false);
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) { if (this.delegateThis == null) { super.manageSyntheticAccessIfNecessary(currentScope, flowInfo, isReadAccess); return; } if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return; //If inlinable field, forget the access emulation, the code gen will directly target it if (this.constant != Constant.NotAConstant) return; // if field from parameterized type got found, use the original field at codegen time if (this.binding instanceof ParameterizedFieldBinding) { ParameterizedFieldBinding parameterizedField = (ParameterizedFieldBinding) this.binding; FieldBinding codegenField = parameterizedField.originalField; // extra cast needed if field type was type variable if ((codegenField.type.tagBits & TagBits.HasTypeVariable) != 0) { this.genericCast = codegenField.type.genericCast(currentScope.boxing(parameterizedField.type)); // runtimeType could be base type in boxing case } } } /**
/** * Check and/or redirect the field access to the delegate receiver if any */ public TypeBinding checkFieldAccess(BlockScope scope) { if (this.delegateThis == null) { return super.checkFieldAccess(scope); } FieldBinding fieldBinding = (FieldBinding) this.binding; this.bits &= ~RestrictiveFlagMASK; // clear bits this.bits |= Binding.FIELD; if (!fieldBinding.isStatic()) { // must check for the static status.... if (this.evaluationContext.isStatic) { scope.problemReporter().staticFieldAccessToNonStaticVariable( this, fieldBinding); this.constant = Constant.NotAConstant; return null; } } this.constant = fieldBinding.constant(scope); if (isFieldUseDeprecated(fieldBinding, scope, this.bits)) { scope.problemReporter().deprecatedField(fieldBinding, this); } return fieldBinding.type; } public void generateAssignment(BlockScope currentScope, CodeStream codeStream, Assignment assignment, boolean valueRequired) {
codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); fieldStore(currentScope, codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, false);
} else { variableType = checkFieldAccess(scope); if (isTypeUseDeprecated(type, scope)) scope.problemReporter().deprecatedType(type, this); type = scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/); return this.resolvedType = reportError(scope);
if ((operation.left instanceof SingleNameReference) && ((variableReference = (SingleNameReference) operation.left).binding == this.binding)) { variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.right, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); && (((operation.right.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) != TypeIds.T_JavaLangString)) { // exclude string concatenation which would occur backwards variableReference.generateCompoundAssignment(currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], operation.left, operator, operation.implicitConversion, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion); codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { generateReceiver(codeStream); fieldStore(currentScope, codeStream, codegenBinding, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, valueRequired); if (valueRequired) { codeStream.generateImplicitConversion(assignment.implicitConversion);
case Binding.FIELD : // reading a field if (valueRequired || currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4) { manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=185682 switch (this.bits & ASTNode.RestrictiveFlagMASK) { case Binding.LOCAL: LocalVariableBinding localBinding = (LocalVariableBinding) this.binding; // check if compound assignment is the only usage of this local Reference.reportOnlyUselesslyReadLocal(currentScope, localBinding, valueRequired); break; case Binding.FIELD: // check if compound assignment is the only usage of a private field reportOnlyUselesslyReadPrivateField(currentScope, (FieldBinding)this.binding, valueRequired); } this.generateCompoundAssignment( currentScope, codeStream, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], expression, operator, assignmentImplicitConversion, valueRequired); }
codeStream.generateOuterAccess(emulationPath, this, targetType, currentScope); } else { generateReceiver(codeStream); checkEffectiveFinality(localBinding, currentScope); switch (isUnboxing ? postConversionType(currentScope).id : this.resolvedType.id) { case T_long : case T_double :
if (isFieldUseDeprecated(fieldBinding, scope, this.bits)) scope.problemReporter().deprecatedField(fieldBinding, this);
reportOnlyUselesslyReadPrivateField(currentScope, fieldBinding, valueRequired); FieldBinding codegenField = fieldBinding.original(); if (codegenField.isStatic()) { codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK); codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion); fieldStore(currentScope, codeStream, codegenField, this.syntheticAccessors == null ? null : this.syntheticAccessors[SingleNameReference.WRITE], this.actualReceiverType, true /*implicit this*/, false);