| /******************************************************************************* |
| * Copyright (c) 2000, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.jsdt.internal.compiler.ast; |
| |
| import org.eclipse.wst.jsdt.core.ast.IASTNode; |
| import org.eclipse.wst.jsdt.core.ast.ISingleNameReference; |
| import org.eclipse.wst.jsdt.internal.compiler.ASTVisitor; |
| import org.eclipse.wst.jsdt.internal.compiler.flow.FlowContext; |
| import org.eclipse.wst.jsdt.internal.compiler.flow.FlowInfo; |
| import org.eclipse.wst.jsdt.internal.compiler.impl.CompilerOptions; |
| import org.eclipse.wst.jsdt.internal.compiler.impl.Constant; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.Binding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.BlockScope; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.ClassScope; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.FieldBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.FunctionTypeBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.LocalVariableBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.MethodScope; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemFieldBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.ProblemReferenceBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.ReferenceBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.Scope; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.SourceTypeBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.TagBits; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.lookup.VariableBinding; |
| import org.eclipse.wst.jsdt.internal.compiler.problem.ProblemSeverities; |
| |
| public class SingleNameReference extends NameReference implements ISingleNameReference, OperatorIds { |
| |
| public static final int READ = 0; |
| public static final int WRITE = 1; |
| public char[] token; |
| // public FunctionBinding[] syntheticAccessors; // [0]=read accessor [1]=write accessor |
| // public TypeBinding genericCast; |
| |
| public SingleNameReference(char[] source, long pos) { |
| super(); |
| token = source; |
| sourceStart = (int) (pos >>> 32); |
| sourceEnd = (int) pos; |
| } |
| |
| public char[] getToken() { |
| return this.token; |
| } |
| public FlowInfo analyseAssignment(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, Assignment assignment, boolean isCompound) { |
| |
| boolean isReachable = (flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0; |
| // compound assignment extra work |
| if (isCompound) { // check the variable part is initialized if blank final |
| switch (bits & RestrictiveFlagMASK) { |
| case Binding.FIELD : // reading a field |
| FieldBinding fieldBinding; |
| if ((fieldBinding = (FieldBinding) binding).isBlankFinal() |
| && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { |
| if (!flowInfo.isDefinitelyAssigned(fieldBinding)) { |
| currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); |
| } |
| } |
| manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); |
| break; |
| case Binding.LOCAL : // reading a local variable |
| // check if assigning a final blank field |
| LocalVariableBinding localBinding; |
| if (!flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) { |
| currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); |
| // we could improve error msg here telling "cannot use compound assignment on final local variable" |
| } |
| if (isReachable) { |
| localBinding.useFlag = LocalVariableBinding.USED; |
| } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { |
| localBinding.useFlag = LocalVariableBinding.FAKE_USED; |
| } |
| } |
| } |
| if (assignment.expression != null) { |
| flowInfo = assignment.expression.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); |
| } |
| switch (bits & RestrictiveFlagMASK) { |
| case Binding.FIELD : // assigning to a field |
| manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); |
| |
| FieldBinding fieldBinding = (FieldBinding) binding; |
| ReferenceBinding declaringClass = fieldBinding.declaringClass; |
| // check if accessing enum static field in initializer |
| if (declaringClass.isEnum()) { |
| MethodScope methodScope = currentScope.methodScope(); |
| SourceTypeBinding sourceType = currentScope.enclosingSourceType(); |
| if (fieldBinding.isStatic() |
| && this.constant == Constant.NotAConstant |
| && !methodScope.isStatic |
| && (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body |
| && methodScope.isInsideInitializerOrConstructor()) { |
| currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this); |
| } |
| } |
| // check if assigning a final field |
| if (fieldBinding.isFinal()) { |
| // inside a context where allowed |
| if (!isCompound && fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { |
| if (flowInfo.isPotentiallyAssigned(fieldBinding)) { |
| currentScope.problemReporter().duplicateInitializationOfBlankFinalField(fieldBinding, this); |
| } else { |
| flowContext.recordSettingFinal(fieldBinding, this, flowInfo); |
| } |
| flowInfo.markAsDefinitelyAssigned(fieldBinding); |
| } else { |
| currentScope.problemReporter().cannotAssignToFinalField(fieldBinding, this); |
| } |
| } |
| break; |
| case Binding.LOCAL : // assigning to a local variable |
| LocalVariableBinding localBinding = (LocalVariableBinding) binding; |
| if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes |
| bits |= FirstAssignmentToLocal; |
| } else { |
| bits &= ~FirstAssignmentToLocal; |
| } |
| if (localBinding.isFinal()) { |
| if ((bits & DepthMASK) == 0) { |
| // tolerate assignment to final local in unreachable code (45674) |
| if ((isReachable && isCompound) || !localBinding.isBlankFinal()){ |
| currentScope.problemReporter().cannotAssignToFinalLocal(localBinding, this); |
| } else if (flowInfo.isPotentiallyAssigned(localBinding)) { |
| currentScope.problemReporter().duplicateInitializationOfFinalLocal(localBinding, this); |
| } else { |
| flowContext.recordSettingFinal(localBinding, this, flowInfo); |
| } |
| } else { |
| currentScope.problemReporter().cannotAssignToFinalOuterLocal(localBinding, this); |
| } |
| } |
| else /* avoid double diagnostic */ if ((localBinding.tagBits & TagBits.IsArgument) != 0) { |
| currentScope.problemReporter().parameterAssignment(localBinding, this); |
| } |
| flowInfo.markAsDefinitelyAssigned(localBinding); |
| } |
| manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); |
| return flowInfo; |
| } |
| public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
| return analyseCode(currentScope, flowContext, flowInfo, true); |
| } |
| public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo, boolean valueRequired) { |
| |
| switch (bits & RestrictiveFlagMASK) { |
| case Binding.FIELD : // reading a field |
| if (valueRequired) { |
| manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); |
| } |
| FieldBinding fieldBinding = (FieldBinding) binding; |
| ReferenceBinding declaringClass = fieldBinding.declaringClass; |
| // check if accessing enum static field in initializer |
| if (declaringClass.isEnum()) { |
| MethodScope methodScope = currentScope.methodScope(); |
| SourceTypeBinding sourceType = currentScope.enclosingSourceType(); |
| if (fieldBinding.isStatic() |
| && this.constant == Constant.NotAConstant |
| && !methodScope.isStatic |
| && (sourceType == declaringClass || sourceType.superclass == declaringClass) // enum constant body |
| && methodScope.isInsideInitializerOrConstructor()) { |
| currentScope.problemReporter().enumStaticFieldUsedDuringInitialization(fieldBinding, this); |
| } |
| } |
| // check if reading a final blank field |
| if (fieldBinding.isBlankFinal() && currentScope.allowBlankFinalFieldAssignment(fieldBinding)) { |
| if (!flowInfo.isDefinitelyAssigned(fieldBinding)) { |
| currentScope.problemReporter().uninitializedBlankFinalField(fieldBinding, this); |
| } |
| } |
| break; |
| case Binding.LOCAL : // reading a local variable |
| LocalVariableBinding localBinding= (LocalVariableBinding) binding; |
| |
| if (localBinding.isSameCompilationUnit(currentScope) && |
| !flowInfo.isDefinitelyAssigned(localBinding )) { |
| currentScope.problemReporter().uninitializedLocalVariable(localBinding, this); |
| } |
| if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { |
| localBinding.useFlag = LocalVariableBinding.USED; |
| } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { |
| localBinding.useFlag = LocalVariableBinding.FAKE_USED; |
| } |
| } |
| if (valueRequired) { |
| manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); |
| } |
| return flowInfo; |
| } |
| |
| public TypeBinding checkFieldAccess(BlockScope scope) { |
| |
| FieldBinding fieldBinding = (FieldBinding) binding; |
| |
| bits &= ~RestrictiveFlagMASK; // clear bits |
| bits |= Binding.FIELD; |
| MethodScope methodScope = scope.methodScope(); |
| boolean isStatic = fieldBinding.isStatic(); |
| if (!isStatic) { |
| // must check for the static status.... |
| if (methodScope!=null && methodScope.isStatic) { |
| // reference is ok if coming from compilation unit superclass |
| if (fieldBinding.declaringClass==null || !fieldBinding.declaringClass.equals(scope.compilationUnitScope().superBinding)) |
| { |
| scope.problemReporter().staticFieldAccessToNonStaticVariable(this, fieldBinding); |
| this.constant = Constant.NotAConstant; |
| return fieldBinding.type; |
| } |
| } |
| } |
| this.constant = fieldBinding.constant(); |
| |
| if (isFieldUseDeprecated(fieldBinding, scope, (this.bits & IsStrictlyAssigned) !=0)) |
| scope.problemReporter().deprecatedField(fieldBinding, this); |
| |
| // if ((this.bits & IsStrictlyAssigned) == 0 |
| // && methodScope.enclosingSourceType() == fieldBinding.original().declaringClass |
| // && methodScope.lastVisibleFieldID >= 0 |
| // && fieldBinding.id >= methodScope.lastVisibleFieldID |
| // && (!fieldBinding.isStatic() || methodScope.isStatic)) { |
| // scope.problemReporter().forwardReference(this, 0, methodScope.enclosingSourceType()); |
| // this.bits |= ASTNode.IgnoreNoEffectAssignCheck; |
| // } |
| return fieldBinding.type; |
| |
| } |
| |
| /** |
| * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#computeConversion(org.eclipse.wst.jsdt.internal.compiler.lookup.Scope, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding, org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding) |
| */ |
| public void computeConversion(Scope scope, TypeBinding runtimeTimeType, TypeBinding compileTimeType) { |
| // if (runtimeTimeType == null || compileTimeType == null) |
| // return; |
| // if ((bits & Binding.FIELD) != 0 && this.binding != null && this.binding.isValidBinding()) { |
| // // set the generic cast after the fact, once the type expectation is fully known (no need for strict cast) |
| // FieldBinding field = (FieldBinding) this.binding; |
| // FieldBinding originalBinding = field.original(); |
| // TypeBinding originalType = originalBinding.type; |
| // // extra cast needed if method return type is type variable |
| // if (originalBinding != field |
| // && originalType != field.type |
| // && runtimeTimeType.id != T_JavaLangObject |
| // && (originalType.tagBits & TagBits.HasTypeVariable) != 0) { |
| // TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) |
| // ? compileTimeType // unboxing: checkcast before conversion |
| // : runtimeTimeType; |
| // this.genericCast = originalType.genericCast(scope.boxing(targetType)); |
| // } |
| // } |
| // super.computeConversion(scope, runtimeTimeType, compileTimeType); |
| } |
| |
| /** |
| * @see org.eclipse.wst.jsdt.internal.compiler.lookup.InvocationSite#genericTypeArguments() |
| */ |
| public TypeBinding[] genericTypeArguments() { |
| return null; |
| } |
| |
| /** |
| * Returns the local variable referenced by this node. Can be a direct reference (SingleNameReference) |
| * or thru a cast expression etc... |
| */ |
| public LocalVariableBinding localVariableBinding() { |
| switch (bits & RestrictiveFlagMASK) { |
| case Binding.FIELD : // reading a field |
| break; |
| case Binding.LOCAL : // reading a local variable |
| return (LocalVariableBinding) this.binding; |
| } |
| return null; |
| } |
| |
| public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) { |
| |
| if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { |
| //If inlinable field, forget the access emulation, the code gen will directly target it |
| if (((bits & DepthMASK) == 0) || (constant != Constant.NotAConstant)) return; |
| |
| if ((bits & RestrictiveFlagMASK) == Binding.LOCAL) { |
| currentScope.emulateOuterAccess((LocalVariableBinding) binding); |
| } |
| } |
| } |
| public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo, boolean isReadAccess) { |
| |
| // if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) return; |
| // |
| // //If inlinable field, forget the access emulation, the code gen will directly target it |
| // if (constant != Constant.NotAConstant) |
| // return; |
| // |
| // if ((bits & Binding.FIELD) != 0) { |
| // FieldBinding fieldBinding = (FieldBinding) binding; |
| // FieldBinding codegenField = fieldBinding.original(); |
| // this.codegenBinding = codegenField; |
| // if (((bits & DepthMASK) != 0) |
| // && (codegenField.isPrivate() // private access |
| // || (codegenField.isProtected() // implicit protected access |
| // && codegenField.declaringClass.getPackage() != currentScope.enclosingSourceType().getPackage()))) { |
| // if (syntheticAccessors == null) |
| // syntheticAccessors = new FunctionBinding[2]; |
| // syntheticAccessors[isReadAccess ? READ : WRITE] = |
| // ((SourceTypeBinding)currentScope.enclosingSourceType(). |
| // enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT)).addSyntheticMethod(codegenField, isReadAccess); |
| // currentScope.problemReporter().needToEmulateFieldAccess(codegenField, this, isReadAccess); |
| // return; |
| // } |
| // // if the binding declaring class is not visible, need special action |
| // // for runtime compatibility on 1.2 VMs : change the declaring class of the binding |
| // // NOTE: from target 1.2 on, field's declaring class is touched if any different from receiver type |
| // // and not from Object or implicit static field access. |
| // if (fieldBinding.declaringClass != this.actualReceiverType |
| // && !this.actualReceiverType.isArrayType() |
| // && fieldBinding.declaringClass != null // array.length |
| // && fieldBinding.constant() == Constant.NotAConstant) { |
| // CompilerOptions options = currentScope.compilerOptions(); |
| // if ((options.targetJDK >= ClassFileConstants.JDK1_2 |
| // && (options.complianceLevel >= ClassFileConstants.JDK1_4 || !fieldBinding.isStatic()) |
| // && fieldBinding.declaringClass.id != T_JavaLangObject) // no change for Object fields |
| // || !fieldBinding.declaringClass.canBeSeenBy(currentScope)) { |
| // |
| // this.codegenBinding = |
| // currentScope.enclosingSourceType().getUpdatedFieldBinding( |
| // codegenField, |
| // (ReferenceBinding)this.actualReceiverType.erasure()); |
| // } |
| // } |
| // } |
| } |
| |
| public int nullStatus(FlowInfo flowInfo) { |
| if (this.constant != null && this.constant != Constant.NotAConstant) { |
| return FlowInfo.NON_NULL; // constant expression cannot be null |
| } |
| switch (bits & RestrictiveFlagMASK) { |
| case Binding.FIELD : // reading a field |
| return FlowInfo.UNKNOWN; |
| case Binding.LOCAL : // reading a local variable |
| LocalVariableBinding local = (LocalVariableBinding) this.binding; |
| if (local != null) { |
| if (flowInfo.isDefinitelyNull(local)) |
| return FlowInfo.NULL; |
| if (flowInfo.isDefinitelyNonNull(local)) |
| return FlowInfo.NON_NULL; |
| return FlowInfo.UNKNOWN; |
| } |
| } |
| return FlowInfo.NON_NULL; // never get there |
| } |
| |
| /** |
| * @see org.eclipse.wst.jsdt.internal.compiler.ast.Expression#postConversionType(Scope) |
| */ |
| public TypeBinding postConversionType(Scope scope) { |
| TypeBinding convertedType = this.resolvedType; |
| // if (this.genericCast != null) |
| // convertedType = this.genericCast; |
| int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4; |
| switch (runtimeType) { |
| case T_boolean : |
| convertedType = TypeBinding.BOOLEAN; |
| break; |
| case T_byte : |
| convertedType = TypeBinding.BYTE; |
| break; |
| case T_short : |
| convertedType = TypeBinding.SHORT; |
| break; |
| case T_char : |
| convertedType = TypeBinding.CHAR; |
| break; |
| case T_int : |
| convertedType = TypeBinding.INT; |
| break; |
| case T_float : |
| convertedType = TypeBinding.FLOAT; |
| break; |
| case T_long : |
| convertedType = TypeBinding.LONG; |
| break; |
| case T_double : |
| convertedType = TypeBinding.DOUBLE; |
| break; |
| default : |
| } |
| if ((this.implicitConversion & BOXING) != 0) { |
| convertedType = scope.environment().computeBoxingType(convertedType); |
| } |
| return convertedType; |
| } |
| |
| public StringBuffer printExpression(int indent, StringBuffer output){ |
| |
| return output.append(token); |
| } |
| public TypeBinding reportError(BlockScope scope) { |
| |
| //=====error cases======= |
| constant = Constant.NotAConstant; |
| if (binding instanceof ProblemFieldBinding) { |
| scope.problemReporter().invalidField(this, (FieldBinding) binding); |
| } else if (binding instanceof ProblemReferenceBinding) { |
| scope.problemReporter().invalidType(this, (TypeBinding) binding); |
| } else { |
| scope.problemReporter().unresolvableReference(this, binding); |
| } |
| return null; |
| } |
| |
| public TypeBinding resolveType(BlockScope scope) { |
| return resolveType(scope,false,null); |
| } |
| |
| public TypeBinding resolveType(BlockScope scope, boolean define, TypeBinding useType) { |
| |
| // for code gen, harm the restrictiveFlag |
| constant = Constant.NotAConstant; |
| |
| if (this.actualReceiverType != null) { |
| this.binding = scope.getField(this.actualReceiverType, token, this); |
| } else { |
| this.actualReceiverType = scope.enclosingSourceType(); |
| this.binding = scope.getBinding(token, (Binding.TYPE|Binding.METHOD | bits) & RestrictiveFlagMASK, this, true /*resolve*/); |
| } |
| if (define && this.binding instanceof ProblemBinding) |
| { |
| LocalDeclaration localDeclaration = new LocalDeclaration(this.token,this.sourceEnd,this.sourceEnd); |
| LocalVariableBinding localBinding=new LocalVariableBinding(localDeclaration,TypeBinding.UNKNOWN,0,false); |
| localBinding.setConstant(Constant.NotAConstant); |
| scope.compilationUnitScope().addLocalVariable(localBinding); |
| this.binding=localBinding; |
| } |
| // this.codegenBinding = this.binding; |
| if (this.binding.isValidBinding()) { |
| switch (bits & RestrictiveFlagMASK) { |
| case Binding.FIELD: |
| case Binding.LOCAL : // =========only variable============ |
| case Binding.VARIABLE : // =========only variable============ |
| case Binding.VARIABLE | Binding.TYPE : //====both variable and type============ |
| if (binding instanceof VariableBinding) { |
| VariableBinding variable = (VariableBinding) binding; |
| if (binding instanceof LocalVariableBinding) { |
| bits &= ~RestrictiveFlagMASK; // clear bits |
| bits |= Binding.LOCAL; |
| // if (!variable.isFinal() && (bits & DepthMASK) != 0) { |
| // scope.problemReporter().cannotReferToNonFinalOuterLocal((LocalVariableBinding)variable, this); |
| // } |
| TypeBinding fieldType = variable.type; |
| if (fieldType.isAnonymousType()) |
| bits |= Binding.TYPE; |
| if (useType!=null && !(useType.id==T_null ||useType.id==T_any)) |
| { |
| if (define) |
| { |
| fieldType=variable.type=useType; |
| if (useType.isFunctionType()) // add method binding if function |
| { |
| MethodBinding methodBinding = ((FunctionTypeBinding)useType).functionBinding.createNamedMethodBinding(this.token); |
| MethodScope methodScope = scope.enclosingMethodScope(); |
| if (methodScope!=null) |
| methodScope.addLocalMethod(methodBinding); |
| else |
| scope.compilationUnitScope().addLocalMethod(methodBinding); |
| } |
| } |
| else |
| { |
| if (fieldType==TypeBinding.UNKNOWN) |
| fieldType=variable.type=useType; |
| else if (!fieldType.isCompatibleWith(useType)) |
| fieldType=variable.type=TypeBinding.ANY; |
| } |
| } |
| if ((this.bits & IsStrictlyAssigned) == 0) { |
| constant = variable.constant(); |
| if (fieldType != null) |
| fieldType = fieldType.capture(scope, this.sourceEnd); // perform capture conversion if read access |
| } else { |
| constant = Constant.NotAConstant; |
| } |
| |
| return this.resolvedType = fieldType; |
| } |
| // a field |
| FieldBinding field = (FieldBinding) this.binding; |
| if (!field.isStatic() && scope.compilerOptions().getSeverity(CompilerOptions.UnqualifiedFieldAccess) != ProblemSeverities.Ignore) { |
| scope.problemReporter().unqualifiedFieldAccess(this, field); |
| } |
| // perform capture conversion if read access |
| TypeBinding fieldType = checkFieldAccess(scope); |
| if (fieldType.isAnonymousType()) |
| bits |= Binding.TYPE; |
| |
| return this.resolvedType = |
| (((this.bits & IsStrictlyAssigned) == 0) |
| ? fieldType.capture(scope, this.sourceEnd) |
| : fieldType); |
| } |
| |
| if (binding instanceof MethodBinding) |
| { |
| return ((MethodBinding)binding).functionTypeBinding; |
| } |
| else |
| { |
| // thus it was a type |
| bits &= ~RestrictiveFlagMASK; // clear bits |
| bits |= Binding.TYPE; |
| } |
| |
| case Binding.TYPE : //========only type============== |
| constant = Constant.NotAConstant; |
| //deprecated test |
| TypeBinding type = (TypeBinding)binding; |
| if (isTypeUseDeprecated(type, scope)) |
| scope.problemReporter().deprecatedType(type, this); |
| type = scope.environment().convertToRawType(type); |
| return this.resolvedType = type; |
| } |
| } |
| |
| // error scenarii |
| return this.resolvedType = this.reportError(scope); |
| } |
| |
| public void traverse(ASTVisitor visitor, BlockScope scope) { |
| visitor.visit(this, scope); |
| visitor.endVisit(this, scope); |
| } |
| |
| public void traverse(ASTVisitor visitor, ClassScope scope) { |
| visitor.visit(this, scope); |
| visitor.endVisit(this, scope); |
| } |
| |
| public String unboundReferenceErrorName(){ |
| |
| return new String(token); |
| } |
| |
| public TypeBinding resolveForAllocation(BlockScope scope, ASTNode location) |
| { |
| char[] memberName = this.token; |
| TypeBinding typeBinding=null; |
| this.binding= |
| scope.getBinding(memberName, (Binding.TYPE|Binding.METHOD | bits) & RestrictiveFlagMASK, this, true /*resolve*/); |
| if (binding instanceof TypeBinding) |
| typeBinding=(TypeBinding)binding; |
| else if (binding instanceof MethodBinding) |
| typeBinding=((MethodBinding)binding).returnType; |
| else if (binding!=null && !binding.isValidBinding()) |
| { |
| typeBinding=new ProblemReferenceBinding(memberName,null,binding.problemId()); |
| } |
| return typeBinding; |
| } |
| public int getASTType() { |
| return IASTNode.SINGLE_NAME_REFERENCE; |
| |
| } |
| } |