diff options
Diffstat (limited to 'bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/SingleNameReference.java')
-rw-r--r-- | bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/SingleNameReference.java | 293 |
1 files changed, 85 insertions, 208 deletions
diff --git a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/SingleNameReference.java b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/SingleNameReference.java index daf541a8..7d2a6b70 100644 --- a/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/SingleNameReference.java +++ b/bundles/org.eclipse.wst.jsdt.core/src/org/eclipse/wst/jsdt/internal/compiler/ast/SingleNameReference.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2013 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 @@ -13,6 +13,7 @@ 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.core.compiler.CharOperation; +import org.eclipse.wst.jsdt.core.infer.InferEngine; 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; @@ -21,25 +22,18 @@ 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.Scope; 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; 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) { this(source, (int) (pos >>> 32), (int) pos); @@ -62,21 +56,25 @@ public class SingleNameReference extends NameReference implements ISingleNameRef if (isCompound) { // check the variable part is initialized if blank final switch (bits & RestrictiveFlagMASK) { case Binding.FIELD : // reading a field - 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)) { + LocalVariableBinding localBinding = null; + if (this.binding instanceof LocalVariableBinding && + !flowInfo.isDefinitelyAssigned(localBinding = (LocalVariableBinding) binding)) { + if (localBinding.declaringScope instanceof MethodScope) { 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(localBinding != null) { + if (isReachable) { + localBinding.useFlag = LocalVariableBinding.USED; + } else if (localBinding.useFlag == LocalVariableBinding.UNUSED) { + localBinding.useFlag = LocalVariableBinding.FAKE_USED; + } } } } @@ -85,20 +83,20 @@ public class SingleNameReference extends NameReference implements ISingleNameRef } switch (bits & RestrictiveFlagMASK) { case Binding.FIELD : // assigning to a field - manageSyntheticAccessIfNecessary(currentScope, flowInfo, false /*write-access*/); - 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.tagBits & TagBits.IsArgument) != 0) { - currentScope.problemReporter().parameterAssignment(localBinding, this); + if(this.binding instanceof LocalVariableBinding) { + LocalVariableBinding localBinding = (LocalVariableBinding) binding; + if (!flowInfo.isDefinitelyAssigned(localBinding)){// for local variable debug attributes + bits |= FirstAssignmentToLocal; + } else { + bits &= ~FirstAssignmentToLocal; + } + if ((localBinding.tagBits & TagBits.IsArgument) != 0) { + currentScope.problemReporter().parameterAssignment(localBinding, this); + } + flowInfo.markAsDefinitelyAssigned(localBinding); } - flowInfo.markAsDefinitelyAssigned(localBinding); } manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo); return flowInfo; @@ -110,10 +108,6 @@ public class SingleNameReference extends NameReference implements ISingleNameRef switch (bits & RestrictiveFlagMASK) { case Binding.FIELD : // reading a field - if (valueRequired) { - manageSyntheticAccessIfNecessary(currentScope, flowInfo, true /*read-access*/); - } - break; case Binding.LOCAL : // reading a local variable case Binding.LOCAL | Binding.TYPE : @@ -170,44 +164,11 @@ public class SingleNameReference extends NameReference implements ISingleNameRef 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() { @@ -223,125 +184,47 @@ public class SingleNameReference extends NameReference implements ISingleNameRef case Binding.FIELD : // reading a field break; case Binding.LOCAL : // reading a local variable - return (LocalVariableBinding) this.binding; + if(this.binding instanceof LocalVariableBinding) { + 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); - } + //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 && this.binding instanceof LocalVariableBinding) { + 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_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 : + public int nullStatus(FlowInfo flowInfo) { + if (this.constant != null && this.constant != Constant.NotAConstant) { + return FlowInfo.NON_NULL; // constant expression cannot be null } - if ((this.implicitConversion & BOXING) != 0) { - convertedType = scope.environment().computeBoxingType(convertedType); + switch (bits & RestrictiveFlagMASK) { + case Binding.FIELD : // reading a field + return FlowInfo.UNKNOWN; + case Binding.LOCAL : // reading a local variable + if(this.binding instanceof LocalVariableBinding) { + 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 convertedType; + return FlowInfo.NON_NULL; // never get there } public StringBuffer printExpression(int indent, StringBuffer output){ @@ -367,19 +250,26 @@ public int nullStatus(FlowInfo flowInfo) { } public TypeBinding resolveType(BlockScope scope, boolean define, TypeBinding useType) { - // for code gen, harm the restrictiveFlag constant = Constant.NotAConstant; this.binding=findBinding(scope); - if (define && this.binding instanceof ProblemBinding) - { - LocalDeclaration localDeclaration = new LocalDeclaration(this.token,this.sourceEnd,this.sourceEnd); + + //if define and the found binding is not valid or is a method then declare a local variable + if (define && (!this.binding.isValidBinding() || this.binding.kind() == Binding.METHOD)) { + LocalDeclaration localDeclaration = new LocalDeclaration(this.token,this.sourceStart,this.sourceEnd); LocalVariableBinding localBinding=new LocalVariableBinding(localDeclaration,TypeBinding.UNKNOWN,0,false); scope.compilationUnitScope().addLocalVariable(localBinding); this.binding=localBinding; } -// this.codegenBinding = this.binding; + + /* if we could not find a binding try finding one for the anonymous global + * type that MAYBE associated with this single name reference */ + if(binding == null || !binding.isValidBinding()) { + char[] typeName = InferEngine.createAnonymousGlobalTypeName(this.token); + this.binding = scope.getBinding(typeName, (Binding.TYPE | bits) & RestrictiveFlagMASK, this, true); + } + if (this.binding.isValidBinding()) { switch (bits & RestrictiveFlagMASK) { case Binding.FIELD: @@ -392,32 +282,13 @@ public int nullStatus(FlowInfo flowInfo) { 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() && !fieldType.isObjectLiteralType()) { -// LocalDeclaration declaration = ((LocalVariableBinding)binding).declaration; -// if(declaration != null && !(declaration.getInitialization() instanceof AllocationExpression) && -// ! (declaration.getInitialization() instanceof Literal)) { -// bits |= Binding.TYPE; -// } -// } if (useType!=null && !(useType.id==T_null ||useType.id==T_any || useType.id==T_undefined)) { 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 { @@ -454,11 +325,25 @@ public int nullStatus(FlowInfo flowInfo) { case Binding.TYPE : //========only type============== constant = Constant.NotAConstant; - //deprecated test - TypeBinding type = (TypeBinding)binding; - if (isTypeUseDeprecated(type, scope)) - scope.problemReporter().deprecatedType(type, this); - return this.resolvedType = type; + TypeBinding type = null; + switch (binding.kind()) { + case Binding.VARIABLE : + type = ((VariableBinding) binding).type; + break; + case Binding.METHOD : + type = ((MethodBinding) binding).returnType; + break; + case Binding.TYPE : + type = (TypeBinding) binding; + break; + } + + if(type != null) { + if (isTypeUseDeprecated(type, scope)) { + scope.problemReporter().deprecatedType(type, this); + } + return this.resolvedType = type; + } } } @@ -467,15 +352,7 @@ public int nullStatus(FlowInfo flowInfo) { } public Binding findBinding(BlockScope scope) { - if (this.actualReceiverType != null) { - Binding binding = scope.getField(this.actualReceiverType, token, this); - if(!(binding instanceof ProblemFieldBinding)) - return binding; - - } else { - this.actualReceiverType = scope.enclosingSourceType(); - } - return scope.getBinding(token, (Binding.TYPE|Binding.METHOD | bits) & RestrictiveFlagMASK, this, true /*resolve*/); + return scope.getBinding(token, (Binding.TYPE | Binding.METHOD | bits) & RestrictiveFlagMASK, this, true /*resolve*/); } public void traverse(ASTVisitor visitor, BlockScope scope) { |