1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.internal.compiler.ASTVisitor; 14 import org.eclipse.jdt.internal.compiler.impl.*; 15 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 16 import org.eclipse.jdt.internal.compiler.codegen.*; 17 import org.eclipse.jdt.internal.compiler.flow.*; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 public class LocalDeclaration extends AbstractVariableDeclaration { 21 22 public LocalVariableBinding binding; 23 24 public LocalDeclaration( 25 char[] name, 26 int sourceStart, 27 int sourceEnd) { 28 29 this.name = name; 30 this.sourceStart = sourceStart; 31 this.sourceEnd = sourceEnd; 32 this.declarationEnd = sourceEnd; 33 } 34 35 public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { 36 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0) { 38 bits |= ASTNode.IsLocalDeclarationReachable; } 40 if (this.initialization == null) { 41 return flowInfo; 42 } 43 int nullStatus = this.initialization.nullStatus(flowInfo); 44 flowInfo = 45 this.initialization 46 .analyseCode(currentScope, flowContext, flowInfo) 47 .unconditionalInits(); 48 if (!flowInfo.isDefinitelyAssigned(this.binding)){ this.bits |= FirstAssignmentToLocal; 50 } else { 51 this.bits &= ~FirstAssignmentToLocal; } 53 flowInfo.markAsDefinitelyAssigned(binding); 54 if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) { 55 switch(nullStatus) { 56 case FlowInfo.NULL : 57 flowInfo.markAsDefinitelyNull(this.binding); 58 break; 59 case FlowInfo.NON_NULL : 60 flowInfo.markAsDefinitelyNonNull(this.binding); 61 break; 62 default: 63 flowInfo.markAsDefinitelyUnknown(this.binding); 64 } 65 } 68 return flowInfo; 69 } 70 71 public void checkModifiers() { 72 73 if (((modifiers & ExtraCompilerModifiers.AccJustFlag) & ~ClassFileConstants.AccFinal) != 0) 75 79 modifiers = (modifiers & ~ExtraCompilerModifiers.AccAlternateModifierProblem) | ExtraCompilerModifiers.AccModifierProblem; 80 } 81 82 86 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 87 88 if (binding.resolvedPosition != -1) { 90 codeStream.addVisibleLocalVariable(binding); 91 } 92 if ((bits & IsReachable) == 0) { 93 return; 94 } 95 int pc = codeStream.position; 96 97 generateInit: { 99 if (this.initialization == null) 100 break generateInit; 101 if (binding.resolvedPosition < 0) { 103 if (initialization.constant != Constant.NotAConstant) 104 break generateInit; 105 initialization.generateCode(currentScope, codeStream, false); 107 break generateInit; 108 } 109 initialization.generateCode(currentScope, codeStream, true); 110 if (binding.type.isArrayType() 112 && (initialization.resolvedType == TypeBinding.NULL || ((initialization instanceof CastExpression) && (((CastExpression)initialization).innermostCastedExpression().resolvedType == TypeBinding.NULL)))){ 115 codeStream.checkcast(binding.type); 116 } 117 codeStream.store(binding, false); 118 if ((this.bits & ASTNode.FirstAssignmentToLocal) != 0) { 119 122 binding.recordInitializationStartPC(codeStream.position); 123 } 124 } 125 codeStream.recordPositionsFrom(pc, this.sourceStart); 126 } 127 128 131 public int getKind() { 132 return LOCAL_VARIABLE; 133 } 134 135 public void resolve(BlockScope scope) { 136 137 TypeBinding variableType = type.resolveType(scope, true ); 139 140 checkModifiers(); 141 if (variableType != null) { 142 if (variableType == TypeBinding.VOID) { 143 scope.problemReporter().variableTypeCannotBeVoid(this); 144 return; 145 } 146 if (variableType.isArrayType() && ((ArrayBinding) variableType).leafComponentType == TypeBinding.VOID) { 147 scope.problemReporter().variableTypeCannotBeVoidArray(this); 148 return; 149 } 150 } 151 152 Binding existingVariable = scope.getBinding(name, Binding.VARIABLE, this, false ); 153 if (existingVariable != null && existingVariable.isValidBinding()){ 154 if (existingVariable instanceof LocalVariableBinding && this.hiddenVariableDepth == 0) { 155 scope.problemReporter().redefineLocal(this); 156 } else { 157 scope.problemReporter().localVariableHiding(this, existingVariable, false); 158 } 159 } 160 161 if ((modifiers & ClassFileConstants.AccFinal)!= 0 && this.initialization == null) { 162 modifiers |= ExtraCompilerModifiers.AccBlankFinal; 163 } 164 this.binding = new LocalVariableBinding(this, variableType, modifiers, false); 165 scope.addLocalVariable(binding); 166 this.binding.setConstant(Constant.NotAConstant); 167 170 if (variableType == null) { 171 if (initialization != null) 172 initialization.resolveType(scope); return; 174 } 175 176 if (initialization != null) { 178 if (initialization instanceof ArrayInitializer) { 179 TypeBinding initializationType = initialization.resolveTypeExpecting(scope, variableType); 180 if (initializationType != null) { 181 ((ArrayInitializer) initialization).binding = (ArrayBinding) initializationType; 182 initialization.computeConversion(scope, variableType, initializationType); 183 } 184 } else { 185 this.initialization.setExpectedType(variableType); 186 TypeBinding initializationType = this.initialization.resolveType(scope); 187 if (initializationType != null) { 188 if (variableType != initializationType) scope.compilationUnitScope().recordTypeConversion(variableType, initializationType); 190 if (initialization.isConstantValueOfTypeAssignableToType(initializationType, variableType) 191 || (variableType.isBaseType() && BaseTypeBinding.isWidening(variableType.id, initializationType.id)) 192 || initializationType.isCompatibleWith(variableType)) { 193 this.initialization.computeConversion(scope, variableType, initializationType); 194 if (initializationType.needsUncheckedConversion(variableType)) { 195 scope.problemReporter().unsafeTypeConversion(this.initialization, initializationType, variableType); 196 } 197 if (this.initialization instanceof CastExpression 198 && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) { 199 CastExpression.checkNeedForAssignedCast(scope, variableType, (CastExpression) this.initialization); 200 } 201 } else if (scope.isBoxingCompatibleWith(initializationType, variableType) 202 || (initializationType.isBaseType() && scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5 && !variableType.isBaseType() 205 && initialization.isConstantValueOfTypeAssignableToType(initializationType, scope.environment().computeBoxingType(variableType)))) { 206 this.initialization.computeConversion(scope, variableType, initializationType); 207 if (this.initialization instanceof CastExpression 208 && (this.initialization.bits & ASTNode.UnnecessaryCast) == 0) { 209 CastExpression.checkNeedForAssignedCast(scope, variableType, (CastExpression) this.initialization); 210 } 211 } else { 212 scope.problemReporter().typeMismatchError(initializationType, variableType, this.initialization); 213 } 214 } 215 } 216 if (this.binding == Assignment.getDirectBinding(this.initialization)) { 218 scope.problemReporter().assignmentHasNoEffect(this, this.name); 219 } 220 binding.setConstant( 224 binding.isFinal() 225 ? initialization.constant.castTo((variableType.id << 4) + initialization.constant.typeID()) 226 : Constant.NotAConstant); 227 } 228 resolveAnnotations(scope, this.annotations, this.binding); 230 } 231 232 public void traverse(ASTVisitor visitor, BlockScope scope) { 233 234 if (visitor.visit(this, scope)) { 235 if (this.annotations != null) { 236 int annotationsLength = this.annotations.length; 237 for (int i = 0; i < annotationsLength; i++) 238 this.annotations[i].traverse(visitor, scope); 239 } 240 type.traverse(visitor, scope); 241 if (initialization != null) 242 initialization.traverse(visitor, scope); 243 } 244 visitor.endVisit(this, scope); 245 } 246 } 247 | Popular Tags |