Lines 13-25
Link Here
|
13 |
|
13 |
|
14 |
import org.eclipse.jdt.core.compiler.CharOperation; |
14 |
import org.eclipse.jdt.core.compiler.CharOperation; |
15 |
import org.eclipse.jdt.internal.compiler.ASTVisitor; |
15 |
import org.eclipse.jdt.internal.compiler.ASTVisitor; |
16 |
import org.eclipse.jdt.internal.compiler.flow.*; |
16 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
|
|
17 |
import org.eclipse.jdt.internal.compiler.codegen.CodeStream; |
18 |
import org.eclipse.jdt.internal.compiler.flow.FlowContext; |
19 |
import org.eclipse.jdt.internal.compiler.flow.FlowInfo; |
17 |
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
20 |
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
18 |
import org.eclipse.jdt.internal.compiler.impl.Constant; |
21 |
import org.eclipse.jdt.internal.compiler.impl.Constant; |
19 |
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; |
22 |
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; |
20 |
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
23 |
import org.eclipse.jdt.internal.compiler.lookup.Binding; |
21 |
import org.eclipse.jdt.internal.compiler.codegen.*; |
24 |
import org.eclipse.jdt.internal.compiler.lookup.BlockScope; |
22 |
import org.eclipse.jdt.internal.compiler.lookup.*; |
25 |
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers; |
|
|
26 |
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite; |
27 |
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; |
28 |
import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding; |
29 |
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons; |
30 |
import org.eclipse.jdt.internal.compiler.lookup.RawTypeBinding; |
31 |
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; |
32 |
import org.eclipse.jdt.internal.compiler.lookup.Scope; |
33 |
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; |
34 |
import org.eclipse.jdt.internal.compiler.lookup.TagBits; |
35 |
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; |
36 |
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; |
37 |
import org.eclipse.jdt.internal.compiler.lookup.TypeIds; |
23 |
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; |
38 |
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; |
24 |
|
39 |
|
25 |
public class MessageSend extends Expression implements InvocationSite { |
40 |
public class MessageSend extends Expression implements InvocationSite { |
Lines 42-61
Link Here
|
42 |
|
57 |
|
43 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
58 |
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) { |
44 |
|
59 |
|
45 |
boolean nonStatic = !binding.isStatic(); |
60 |
boolean nonStatic = !this.binding.isStatic(); |
46 |
flowInfo = receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits(); |
61 |
flowInfo = this.receiver.analyseCode(currentScope, flowContext, flowInfo, nonStatic).unconditionalInits(); |
47 |
if (nonStatic) { |
62 |
if (nonStatic) { |
48 |
receiver.checkNPE(currentScope, flowContext, flowInfo); |
63 |
this.receiver.checkNPE(currentScope, flowContext, flowInfo); |
49 |
} |
64 |
} |
50 |
|
65 |
|
51 |
if (arguments != null) { |
66 |
if (this.arguments != null) { |
52 |
int length = arguments.length; |
67 |
int length = this.arguments.length; |
53 |
for (int i = 0; i < length; i++) { |
68 |
for (int i = 0; i < length; i++) { |
54 |
flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); |
69 |
flowInfo = this.arguments[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits(); |
55 |
} |
70 |
} |
56 |
} |
71 |
} |
57 |
ReferenceBinding[] thrownExceptions; |
72 |
ReferenceBinding[] thrownExceptions; |
58 |
if ((thrownExceptions = binding.thrownExceptions) != Binding.NO_EXCEPTIONS) { |
73 |
if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) { |
59 |
// must verify that exceptions potentially thrown by this expression are caught in the method |
74 |
// must verify that exceptions potentially thrown by this expression are caught in the method |
60 |
flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo.copy(), currentScope); |
75 |
flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo.copy(), currentScope); |
61 |
// TODO (maxime) the copy above is needed because of a side effect into |
76 |
// TODO (maxime) the copy above is needed because of a side effect into |
Lines 78-94
Link Here
|
78 |
// extra cast needed if method return type is type variable |
93 |
// extra cast needed if method return type is type variable |
79 |
if (originalBinding != this.binding |
94 |
if (originalBinding != this.binding |
80 |
&& originalType != this.binding.returnType |
95 |
&& originalType != this.binding.returnType |
81 |
&& runtimeTimeType.id != T_JavaLangObject |
96 |
&& runtimeTimeType.id != TypeIds.T_JavaLangObject |
82 |
&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) { |
97 |
&& (originalType.tagBits & TagBits.HasTypeVariable) != 0) { |
83 |
TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) |
98 |
TypeBinding targetType = (!compileTimeType.isBaseType() && runtimeTimeType.isBaseType()) |
84 |
? compileTimeType // unboxing: checkcast before conversion |
99 |
? compileTimeType // unboxing: checkcast before conversion |
85 |
: runtimeTimeType; |
100 |
: runtimeTimeType; |
86 |
this.valueCast = originalType.genericCast(targetType); |
101 |
this.valueCast = originalType.genericCast(targetType); |
87 |
} else if (this.actualReceiverType.isArrayType() |
102 |
} else if (this.actualReceiverType.isArrayType() |
88 |
&& runtimeTimeType.id != T_JavaLangObject |
103 |
&& runtimeTimeType.id != TypeIds.T_JavaLangObject |
89 |
&& this.binding.parameters == Binding.NO_PARAMETERS |
104 |
&& this.binding.parameters == Binding.NO_PARAMETERS |
90 |
&& scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5 |
105 |
&& scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5 |
91 |
&& CharOperation.equals(this.binding.selector, CLONE)) { |
106 |
&& CharOperation.equals(this.binding.selector, TypeConstants.CLONE)) { |
92 |
// from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast |
107 |
// from 1.5 compliant mode on, array#clone() resolves to array type, but codegen to #clone()Object - thus require extra inserted cast |
93 |
this.valueCast = runtimeTimeType; |
108 |
this.valueCast = runtimeTimeType; |
94 |
} |
109 |
} |
Lines 110-137
Link Here
|
110 |
// generate receiver/enclosing instance access |
125 |
// generate receiver/enclosing instance access |
111 |
boolean isStatic = this.codegenBinding.isStatic(); |
126 |
boolean isStatic = this.codegenBinding.isStatic(); |
112 |
if (isStatic) { |
127 |
if (isStatic) { |
113 |
receiver.generateCode(currentScope, codeStream, false); |
128 |
this.receiver.generateCode(currentScope, codeStream, false); |
114 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
129 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
115 |
} else if ((bits & DepthMASK) != 0 && receiver.isImplicitThis()) { // outer access ? |
130 |
} else if ((this.bits & ASTNode.DepthMASK) != 0 && this.receiver.isImplicitThis()) { // outer access ? |
116 |
// outer method can be reached through emulation if implicit access |
131 |
// outer method can be reached through emulation if implicit access |
117 |
ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT); |
132 |
ReferenceBinding targetType = currentScope.enclosingSourceType().enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); |
118 |
Object[] path = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); |
133 |
Object[] path = currentScope.getEmulationPath(targetType, true /*only exact match*/, false/*consider enclosing arg*/); |
119 |
codeStream.generateOuterAccess(path, this, targetType, currentScope); |
134 |
codeStream.generateOuterAccess(path, this, targetType, currentScope); |
120 |
} else { |
135 |
} else { |
121 |
receiver.generateCode(currentScope, codeStream, true); |
136 |
this.receiver.generateCode(currentScope, codeStream, true); |
122 |
if (this.receiverGenericCast != null) |
137 |
if (this.receiverGenericCast != null) |
123 |
codeStream.checkcast(this.receiverGenericCast); |
138 |
codeStream.checkcast(this.receiverGenericCast); |
124 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
139 |
codeStream.recordPositionsFrom(pc, this.sourceStart); |
125 |
|
140 |
|
126 |
} |
141 |
} |
127 |
// generate arguments |
142 |
// generate arguments |
128 |
generateArguments(binding, arguments, currentScope, codeStream); |
143 |
generateArguments(this.binding, this.arguments, currentScope, codeStream); |
129 |
// actual message invocation |
144 |
// actual message invocation |
130 |
if (syntheticAccessor == null){ |
145 |
if (this.syntheticAccessor == null){ |
131 |
if (isStatic){ |
146 |
if (isStatic){ |
132 |
codeStream.invokestatic(this.codegenBinding); |
147 |
codeStream.invokestatic(this.codegenBinding); |
133 |
} else { |
148 |
} else { |
134 |
if( (receiver.isSuper()) || this.codegenBinding.isPrivate()){ |
149 |
if( (this.receiver.isSuper()) || this.codegenBinding.isPrivate()){ |
135 |
codeStream.invokespecial(this.codegenBinding); |
150 |
codeStream.invokespecial(this.codegenBinding); |
136 |
} else { |
151 |
} else { |
137 |
if (this.codegenBinding.declaringClass.isInterface()) { // interface or annotation type |
152 |
if (this.codegenBinding.declaringClass.isInterface()) { // interface or annotation type |
Lines 142-158
Link Here
|
142 |
} |
157 |
} |
143 |
} |
158 |
} |
144 |
} else { |
159 |
} else { |
145 |
codeStream.invokestatic(syntheticAccessor); |
160 |
codeStream.invokestatic(this.syntheticAccessor); |
146 |
} |
161 |
} |
147 |
// required cast must occur even if no value is required |
162 |
// required cast must occur even if no value is required |
148 |
if (this.valueCast != null) codeStream.checkcast(this.valueCast); |
163 |
if (this.valueCast != null) codeStream.checkcast(this.valueCast); |
149 |
if (valueRequired){ |
164 |
if (valueRequired){ |
150 |
// implicit conversion if necessary |
165 |
// implicit conversion if necessary |
151 |
codeStream.generateImplicitConversion(implicitConversion); |
166 |
codeStream.generateImplicitConversion(this.implicitConversion); |
152 |
} else { |
167 |
} else { |
153 |
boolean isUnboxing = (implicitConversion & TypeIds.UNBOXING) != 0; |
168 |
boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0; |
154 |
// conversion only generated if unboxing |
169 |
// conversion only generated if unboxing |
155 |
if (isUnboxing) codeStream.generateImplicitConversion(implicitConversion); |
170 |
if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion); |
156 |
switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.returnType.id) { |
171 |
switch (isUnboxing ? postConversionType(currentScope).id : this.codegenBinding.returnType.id) { |
157 |
case T_long : |
172 |
case T_long : |
158 |
case T_double : |
173 |
case T_double : |
Lines 175-184
Link Here
|
175 |
} |
190 |
} |
176 |
|
191 |
|
177 |
public boolean isSuperAccess() { |
192 |
public boolean isSuperAccess() { |
178 |
return receiver.isSuper(); |
193 |
return this.receiver.isSuper(); |
179 |
} |
194 |
} |
180 |
public boolean isTypeAccess() { |
195 |
public boolean isTypeAccess() { |
181 |
return receiver != null && receiver.isTypeReference(); |
196 |
return this.receiver != null && this.receiver.isTypeReference(); |
182 |
} |
197 |
} |
183 |
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){ |
198 |
public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo){ |
184 |
|
199 |
|
Lines 191-218
Link Here
|
191 |
// depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy) |
206 |
// depth is set for both implicit and explicit access (see MethodBinding#canBeSeenBy) |
192 |
if (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass){ |
207 |
if (currentScope.enclosingSourceType() != this.codegenBinding.declaringClass){ |
193 |
|
208 |
|
194 |
syntheticAccessor = ((SourceTypeBinding)this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess()); |
209 |
this.syntheticAccessor = ((SourceTypeBinding)this.codegenBinding.declaringClass).addSyntheticMethod(this.codegenBinding, isSuperAccess()); |
195 |
currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); |
210 |
currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); |
196 |
return; |
211 |
return; |
197 |
} |
212 |
} |
198 |
|
213 |
|
199 |
} else if (receiver instanceof QualifiedSuperReference){ // qualified super |
214 |
} else if (this.receiver instanceof QualifiedSuperReference){ // qualified super |
200 |
|
215 |
|
201 |
// qualified super need emulation always |
216 |
// qualified super need emulation always |
202 |
SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)receiver).currentCompatibleType); |
217 |
SourceTypeBinding destinationType = (SourceTypeBinding)(((QualifiedSuperReference)this.receiver).currentCompatibleType); |
203 |
syntheticAccessor = destinationType.addSyntheticMethod(this.codegenBinding, isSuperAccess()); |
218 |
this.syntheticAccessor = destinationType.addSyntheticMethod(this.codegenBinding, isSuperAccess()); |
204 |
currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); |
219 |
currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); |
205 |
return; |
220 |
return; |
206 |
|
221 |
|
207 |
} else if (binding.isProtected()){ |
222 |
} else if (this.binding.isProtected()){ |
208 |
|
223 |
|
209 |
SourceTypeBinding enclosingSourceType; |
224 |
SourceTypeBinding enclosingSourceType; |
210 |
if (((bits & DepthMASK) != 0) |
225 |
if (((this.bits & ASTNode.DepthMASK) != 0) |
211 |
&& this.codegenBinding.declaringClass.getPackage() |
226 |
&& this.codegenBinding.declaringClass.getPackage() |
212 |
!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()){ |
227 |
!= (enclosingSourceType = currentScope.enclosingSourceType()).getPackage()){ |
213 |
|
228 |
|
214 |
SourceTypeBinding currentCompatibleType = (SourceTypeBinding)enclosingSourceType.enclosingTypeAt((bits & DepthMASK) >> DepthSHIFT); |
229 |
SourceTypeBinding currentCompatibleType = (SourceTypeBinding)enclosingSourceType.enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT); |
215 |
syntheticAccessor = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isSuperAccess()); |
230 |
this.syntheticAccessor = currentCompatibleType.addSyntheticMethod(this.codegenBinding, isSuperAccess()); |
216 |
currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); |
231 |
currentScope.problemReporter().needToEmulateMethodAccess(this.codegenBinding, this); |
217 |
return; |
232 |
return; |
218 |
} |
233 |
} |
Lines 227-234
Link Here
|
227 |
&& !this.actualReceiverType.isArrayType()) { |
242 |
&& !this.actualReceiverType.isArrayType()) { |
228 |
CompilerOptions options = currentScope.compilerOptions(); |
243 |
CompilerOptions options = currentScope.compilerOptions(); |
229 |
if ((options.targetJDK >= ClassFileConstants.JDK1_2 |
244 |
if ((options.targetJDK >= ClassFileConstants.JDK1_2 |
230 |
&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(receiver.isImplicitThis() && this.codegenBinding.isStatic())) |
245 |
&& (options.complianceLevel >= ClassFileConstants.JDK1_4 || !(this.receiver.isImplicitThis() && this.codegenBinding.isStatic())) |
231 |
&& this.binding.declaringClass.id != T_JavaLangObject) // no change for Object methods |
246 |
&& this.binding.declaringClass.id != TypeIds.T_JavaLangObject) // no change for Object methods |
232 |
|| !this.binding.declaringClass.canBeSeenBy(currentScope)) { |
247 |
|| !this.binding.declaringClass.canBeSeenBy(currentScope)) { |
233 |
|
248 |
|
234 |
this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding( |
249 |
this.codegenBinding = currentScope.enclosingSourceType().getUpdatedMethodBinding( |
Lines 249-255
Link Here
|
249 |
TypeBinding convertedType = this.resolvedType; |
264 |
TypeBinding convertedType = this.resolvedType; |
250 |
if (this.valueCast != null) |
265 |
if (this.valueCast != null) |
251 |
convertedType = this.valueCast; |
266 |
convertedType = this.valueCast; |
252 |
int runtimeType = (this.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4; |
267 |
int runtimeType = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4; |
253 |
switch (runtimeType) { |
268 |
switch (runtimeType) { |
254 |
case T_boolean : |
269 |
case T_boolean : |
255 |
convertedType = TypeBinding.BOOLEAN; |
270 |
convertedType = TypeBinding.BOOLEAN; |
Lines 277-283
Link Here
|
277 |
break; |
292 |
break; |
278 |
default : |
293 |
default : |
279 |
} |
294 |
} |
280 |
if ((this.implicitConversion & BOXING) != 0) { |
295 |
if ((this.implicitConversion & TypeIds.BOXING) != 0) { |
281 |
convertedType = scope.environment().computeBoxingType(convertedType); |
296 |
convertedType = scope.environment().computeBoxingType(convertedType); |
282 |
} |
297 |
} |
283 |
return convertedType; |
298 |
return convertedType; |
Lines 285-306
Link Here
|
285 |
|
300 |
|
286 |
public StringBuffer printExpression(int indent, StringBuffer output){ |
301 |
public StringBuffer printExpression(int indent, StringBuffer output){ |
287 |
|
302 |
|
288 |
if (!receiver.isImplicitThis()) receiver.printExpression(0, output).append('.'); |
303 |
if (!this.receiver.isImplicitThis()) this.receiver.printExpression(0, output).append('.'); |
289 |
if (this.typeArguments != null) { |
304 |
if (this.typeArguments != null) { |
290 |
output.append('<'); |
305 |
output.append('<'); |
291 |
int max = typeArguments.length - 1; |
306 |
int max = this.typeArguments.length - 1; |
292 |
for (int j = 0; j < max; j++) { |
307 |
for (int j = 0; j < max; j++) { |
293 |
typeArguments[j].print(0, output); |
308 |
this.typeArguments[j].print(0, output); |
294 |
output.append(", ");//$NON-NLS-1$ |
309 |
output.append(", ");//$NON-NLS-1$ |
295 |
} |
310 |
} |
296 |
typeArguments[max].print(0, output); |
311 |
this.typeArguments[max].print(0, output); |
297 |
output.append('>'); |
312 |
output.append('>'); |
298 |
} |
313 |
} |
299 |
output.append(selector).append('(') ; |
314 |
output.append(this.selector).append('(') ; |
300 |
if (arguments != null) { |
315 |
if (this.arguments != null) { |
301 |
for (int i = 0; i < arguments.length ; i ++) { |
316 |
for (int i = 0; i < this.arguments.length ; i ++) { |
302 |
if (i > 0) output.append(", "); //$NON-NLS-1$ |
317 |
if (i > 0) output.append(", "); //$NON-NLS-1$ |
303 |
arguments[i].printExpression(0, output); |
318 |
this.arguments[i].printExpression(0, output); |
304 |
} |
319 |
} |
305 |
} |
320 |
} |
306 |
return output.append(')'); |
321 |
return output.append(')'); |
Lines 310-323
Link Here
|
310 |
// Answer the signature return type |
325 |
// Answer the signature return type |
311 |
// Base type promotion |
326 |
// Base type promotion |
312 |
|
327 |
|
313 |
constant = Constant.NotAConstant; |
328 |
this.constant = Constant.NotAConstant; |
314 |
boolean receiverCast = false, argsContainCast = false; |
329 |
boolean receiverCast = false, argsContainCast = false; |
315 |
if (this.receiver instanceof CastExpression) { |
330 |
if (this.receiver instanceof CastExpression) { |
316 |
this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on |
331 |
this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on |
317 |
receiverCast = true; |
332 |
receiverCast = true; |
318 |
} |
333 |
} |
319 |
this.actualReceiverType = receiver.resolveType(scope); |
334 |
this.actualReceiverType = this.receiver.resolveType(scope); |
320 |
boolean receiverIsType = receiver instanceof NameReference && (((NameReference) receiver).bits & Binding.TYPE) != 0; |
335 |
boolean receiverIsType = this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0; |
321 |
if (receiverCast && this.actualReceiverType != null) { |
336 |
if (receiverCast && this.actualReceiverType != null) { |
322 |
// due to change of declaring class with receiver type, only identity cast should be notified |
337 |
// due to change of declaring class with receiver type, only identity cast should be notified |
323 |
if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { |
338 |
if (((CastExpression)this.receiver).expression.resolvedType == this.actualReceiverType) { |
Lines 344-357
Link Here
|
344 |
} |
359 |
} |
345 |
// will check for null after args are resolved |
360 |
// will check for null after args are resolved |
346 |
TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; |
361 |
TypeBinding[] argumentTypes = Binding.NO_PARAMETERS; |
347 |
if (arguments != null) { |
362 |
if (this.arguments != null) { |
348 |
boolean argHasError = false; // typeChecks all arguments |
363 |
boolean argHasError = false; // typeChecks all arguments |
349 |
int length = arguments.length; |
364 |
int length = this.arguments.length; |
350 |
argumentTypes = new TypeBinding[length]; |
365 |
argumentTypes = new TypeBinding[length]; |
351 |
for (int i = 0; i < length; i++){ |
366 |
for (int i = 0; i < length; i++){ |
352 |
Expression argument = arguments[i]; |
367 |
Expression argument = this.arguments[i]; |
353 |
if (argument instanceof CastExpression) { |
368 |
if (argument instanceof CastExpression) { |
354 |
argument.bits |= DisableUnnecessaryCastCheck; // will check later on |
369 |
argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on |
355 |
argsContainCast = true; |
370 |
argsContainCast = true; |
356 |
} |
371 |
} |
357 |
if ((argumentTypes[i] = argument.resolveType(scope)) == null){ |
372 |
if ((argumentTypes[i] = argument.resolveType(scope)) == null){ |
Lines 359-381
Link Here
|
359 |
} |
374 |
} |
360 |
} |
375 |
} |
361 |
if (argHasError) { |
376 |
if (argHasError) { |
362 |
if (actualReceiverType instanceof ReferenceBinding) { |
377 |
if (this.actualReceiverType instanceof ReferenceBinding) { |
363 |
// record a best guess, for clients who need hint about possible method match |
378 |
// record a best guess, for clients who need hint about possible method match |
364 |
TypeBinding[] pseudoArgs = new TypeBinding[length]; |
379 |
TypeBinding[] pseudoArgs = new TypeBinding[length]; |
365 |
for (int i = length; --i >= 0;) |
380 |
for (int i = length; --i >= 0;) |
366 |
pseudoArgs[i] = argumentTypes[i] == null ? actualReceiverType : argumentTypes[i]; // replace args with errors with receiver |
381 |
pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type |
367 |
this.binding = |
382 |
this.binding = |
368 |
receiver.isImplicitThis() |
383 |
this.receiver.isImplicitThis() |
369 |
? scope.getImplicitMethod(selector, pseudoArgs, this) |
384 |
? scope.getImplicitMethod(this.selector, pseudoArgs, this) |
370 |
: scope.findMethod((ReferenceBinding) actualReceiverType, selector, pseudoArgs, this); |
385 |
: scope.findMethod((ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this); |
371 |
if (binding != null && !binding.isValidBinding()) { |
386 |
if (this.binding != null && !this.binding.isValidBinding()) { |
372 |
MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch; |
387 |
MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; |
373 |
// record the closest match, for clients who may still need hint about possible method match |
388 |
// record the closest match, for clients who may still need hint about possible method match |
374 |
if (closestMatch != null) { |
389 |
if (closestMatch != null) { |
|
|
390 |
if (closestMatch.typeVariables != Binding.NO_TYPE_VARIABLES) { // generic method |
391 |
// shouldn't return generic method outside its context, rather convert it to raw method (175409) |
392 |
closestMatch = scope.environment().createParameterizedGenericMethod(closestMatch, (RawTypeBinding)null); |
393 |
} |
375 |
this.binding = closestMatch; |
394 |
this.binding = closestMatch; |
376 |
if ((closestMatch.isPrivate() || closestMatch.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatch)) { |
395 |
MethodBinding closestMatchOriginal = closestMatch.original(); |
|
|
396 |
if ((closestMatchOriginal.isPrivate() || closestMatchOriginal.declaringClass.isLocalType()) && !scope.isDefinedInMethod(closestMatchOriginal)) { |
377 |
// ignore cases where method is used from within inside itself (e.g. direct recursions) |
397 |
// ignore cases where method is used from within inside itself (e.g. direct recursions) |
378 |
closestMatch.original().modifiers |= ExtraCompilerModifiers.AccLocallyUsed; |
398 |
closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed; |
379 |
} |
399 |
} |
380 |
} |
400 |
} |
381 |
} |
401 |
} |
Lines 392-411
Link Here
|
392 |
return null; |
412 |
return null; |
393 |
} |
413 |
} |
394 |
this.binding = |
414 |
this.binding = |
395 |
receiver.isImplicitThis() |
415 |
this.receiver.isImplicitThis() |
396 |
? scope.getImplicitMethod(selector, argumentTypes, this) |
416 |
? scope.getImplicitMethod(this.selector, argumentTypes, this) |
397 |
: scope.getMethod(this.actualReceiverType, selector, argumentTypes, this); |
417 |
: scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this); |
398 |
if (!binding.isValidBinding()) { |
418 |
if (!this.binding.isValidBinding()) { |
399 |
if (binding.declaringClass == null) { |
419 |
if (this.binding.declaringClass == null) { |
400 |
if (this.actualReceiverType instanceof ReferenceBinding) { |
420 |
if (this.actualReceiverType instanceof ReferenceBinding) { |
401 |
binding.declaringClass = (ReferenceBinding) this.actualReceiverType; |
421 |
this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType; |
402 |
} else { |
422 |
} else { |
403 |
scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); |
423 |
scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes); |
404 |
return null; |
424 |
return null; |
405 |
} |
425 |
} |
406 |
} |
426 |
} |
407 |
scope.problemReporter().invalidMethod(this, binding); |
427 |
scope.problemReporter().invalidMethod(this, this.binding); |
408 |
MethodBinding closestMatch = ((ProblemMethodBinding)binding).closestMatch; |
428 |
MethodBinding closestMatch = ((ProblemMethodBinding)this.binding).closestMatch; |
409 |
switch (this.binding.problemId()) { |
429 |
switch (this.binding.problemId()) { |
410 |
case ProblemReasons.Ambiguous : |
430 |
case ProblemReasons.Ambiguous : |
411 |
break; // no resilience on ambiguous |
431 |
break; // no resilience on ambiguous |
Lines 429-445
Link Here
|
429 |
return this.resolvedType; |
449 |
return this.resolvedType; |
430 |
} |
450 |
} |
431 |
final CompilerOptions compilerOptions = scope.compilerOptions(); |
451 |
final CompilerOptions compilerOptions = scope.compilerOptions(); |
432 |
if (!binding.isStatic()) { |
452 |
if (!this.binding.isStatic()) { |
433 |
// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type |
453 |
// the "receiver" must not be a type, in other words, a NameReference that the TC has bound to a Type |
434 |
if (receiverIsType) { |
454 |
if (receiverIsType) { |
435 |
scope.problemReporter().mustUseAStaticMethod(this, binding); |
455 |
scope.problemReporter().mustUseAStaticMethod(this, this.binding); |
436 |
if (this.actualReceiverType.isRawType() |
456 |
if (this.actualReceiverType.isRawType() |
437 |
&& (this.receiver.bits & IgnoreRawTypeCheck) == 0 |
457 |
&& (this.receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0 |
438 |
&& compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) { |
458 |
&& compilerOptions.getSeverity(CompilerOptions.RawTypeReference) != ProblemSeverities.Ignore) { |
439 |
scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType); |
459 |
scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType); |
440 |
} |
460 |
} |
441 |
} else { |
461 |
} else { |
442 |
receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); |
462 |
this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType); |
443 |
// compute generic cast if necessary |
463 |
// compute generic cast if necessary |
444 |
TypeBinding receiverErasure = this.actualReceiverType.erasure(); |
464 |
TypeBinding receiverErasure = this.actualReceiverType.erasure(); |
445 |
if (receiverErasure instanceof ReferenceBinding) { |
465 |
if (receiverErasure instanceof ReferenceBinding) { |
Lines 450-486
Link Here
|
450 |
} |
470 |
} |
451 |
} else { |
471 |
} else { |
452 |
// static message invoked through receiver? legal but unoptimal (optional warning). |
472 |
// static message invoked through receiver? legal but unoptimal (optional warning). |
453 |
if (!(receiver.isImplicitThis() || receiver.isSuper() || receiverIsType)) { |
473 |
if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || receiverIsType)) { |
454 |
scope.problemReporter().nonStaticAccessToStaticMethod(this, binding); |
474 |
scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding); |
455 |
} |
475 |
} |
456 |
if (!receiver.isImplicitThis() && binding.declaringClass != actualReceiverType) { |
476 |
if (!this.receiver.isImplicitThis() && this.binding.declaringClass != this.actualReceiverType) { |
457 |
scope.problemReporter().indirectAccessToStaticMethod(this, binding); |
477 |
scope.problemReporter().indirectAccessToStaticMethod(this, this.binding); |
458 |
} |
478 |
} |
459 |
} |
479 |
} |
460 |
checkInvocationArguments(scope, this.receiver, actualReceiverType, binding, this.arguments, argumentTypes, argsContainCast, this); |
480 |
checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this); |
461 |
|
481 |
|
462 |
//-------message send that are known to fail at compile time----------- |
482 |
//-------message send that are known to fail at compile time----------- |
463 |
if (binding.isAbstract()) { |
483 |
if (this.binding.isAbstract()) { |
464 |
if (receiver.isSuper()) { |
484 |
if (this.receiver.isSuper()) { |
465 |
scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, binding); |
485 |
scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding); |
466 |
} |
486 |
} |
467 |
// abstract private methods cannot occur nor abstract static............ |
487 |
// abstract private methods cannot occur nor abstract static............ |
468 |
} |
488 |
} |
469 |
if (isMethodUseDeprecated(binding, scope, true)) |
489 |
if (isMethodUseDeprecated(this.binding, scope, true)) |
470 |
scope.problemReporter().deprecatedMethod(binding, this); |
490 |
scope.problemReporter().deprecatedMethod(this.binding, this); |
471 |
|
491 |
|
472 |
// from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object) |
492 |
// from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object) |
473 |
if (actualReceiverType.isArrayType() |
493 |
if (this.actualReceiverType.isArrayType() |
474 |
&& this.binding.parameters == Binding.NO_PARAMETERS |
494 |
&& this.binding.parameters == Binding.NO_PARAMETERS |
475 |
&& compilerOptions.complianceLevel >= ClassFileConstants.JDK1_5 |
495 |
&& compilerOptions.complianceLevel >= ClassFileConstants.JDK1_5 |
476 |
&& CharOperation.equals(this.binding.selector, CLONE)) { |
496 |
&& CharOperation.equals(this.binding.selector, TypeConstants.CLONE)) { |
477 |
this.resolvedType = actualReceiverType; |
497 |
this.resolvedType = this.actualReceiverType; |
478 |
} else { |
498 |
} else { |
479 |
TypeBinding returnType = this.binding.returnType; |
499 |
TypeBinding returnType = this.binding.returnType; |
480 |
if (returnType != null) returnType = returnType.capture(scope, this.sourceEnd); |
500 |
if (returnType != null) returnType = returnType.capture(scope, this.sourceEnd); |
481 |
this.resolvedType = returnType; |
501 |
this.resolvedType = returnType; |
482 |
} |
502 |
} |
483 |
if (receiver.isSuper() && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) { |
503 |
if (this.receiver.isSuper() && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation) != ProblemSeverities.Ignore) { |
484 |
final ReferenceContext referenceContext = scope.methodScope().referenceContext; |
504 |
final ReferenceContext referenceContext = scope.methodScope().referenceContext; |
485 |
if (referenceContext instanceof AbstractMethodDeclaration) { |
505 |
if (referenceContext instanceof AbstractMethodDeclaration) { |
486 |
final AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) referenceContext; |
506 |
final AbstractMethodDeclaration abstractMethodDeclaration = (AbstractMethodDeclaration) referenceContext; |
Lines 500-508
Link Here
|
500 |
this.actualReceiverType = receiverType; |
520 |
this.actualReceiverType = receiverType; |
501 |
} |
521 |
} |
502 |
public void setDepth(int depth) { |
522 |
public void setDepth(int depth) { |
503 |
bits &= ~DepthMASK; // flush previous depth if any |
523 |
this.bits &= ~ASTNode.DepthMASK; // flush previous depth if any |
504 |
if (depth > 0) { |
524 |
if (depth > 0) { |
505 |
bits |= (depth & 0xFF) << DepthSHIFT; // encoded on 8 bits |
525 |
this.bits |= (depth & 0xFF) << ASTNode.DepthSHIFT; // encoded on 8 bits |
506 |
} |
526 |
} |
507 |
} |
527 |
} |
508 |
|
528 |
|
Lines 518-533
Link Here
|
518 |
|
538 |
|
519 |
public void traverse(ASTVisitor visitor, BlockScope blockScope) { |
539 |
public void traverse(ASTVisitor visitor, BlockScope blockScope) { |
520 |
if (visitor.visit(this, blockScope)) { |
540 |
if (visitor.visit(this, blockScope)) { |
521 |
receiver.traverse(visitor, blockScope); |
541 |
this.receiver.traverse(visitor, blockScope); |
522 |
if (this.typeArguments != null) { |
542 |
if (this.typeArguments != null) { |
523 |
for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) { |
543 |
for (int i = 0, typeArgumentsLength = this.typeArguments.length; i < typeArgumentsLength; i++) { |
524 |
this.typeArguments[i].traverse(visitor, blockScope); |
544 |
this.typeArguments[i].traverse(visitor, blockScope); |
525 |
} |
545 |
} |
526 |
} |
546 |
} |
527 |
if (arguments != null) { |
547 |
if (this.arguments != null) { |
528 |
int argumentsLength = arguments.length; |
548 |
int argumentsLength = this.arguments.length; |
529 |
for (int i = 0; i < argumentsLength; i++) |
549 |
for (int i = 0; i < argumentsLength; i++) |
530 |
arguments[i].traverse(visitor, blockScope); |
550 |
this.arguments[i].traverse(visitor, blockScope); |
531 |
} |
551 |
} |
532 |
} |
552 |
} |
533 |
visitor.endVisit(this, blockScope); |
553 |
visitor.endVisit(this, blockScope); |