Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2014-11-11 20:35:54 +0000
committerStephan Herrmann2014-11-11 20:35:54 +0000
commit4194d1760530eb281a099ab365ea7dcb0dfadf22 (patch)
treebf9e6ead15f6b3e81738eef1ebb0f77c8b86d66e /org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal
parent5cb0427a4624e351329b5f2b51a3d36b82b7d595 (diff)
downloadorg.eclipse.objectteams-4194d1760530eb281a099ab365ea7dcb0dfadf22.tar.gz
org.eclipse.objectteams-4194d1760530eb281a099ab365ea7dcb0dfadf22.tar.xz
org.eclipse.objectteams-4194d1760530eb281a099ab365ea7dcb0dfadf22.zip
(right before bug 437444)
Diffstat (limited to 'org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal')
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java67
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java41
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java46
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java35
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java62
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java37
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java58
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java391
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java20
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java30
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java50
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java15
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java25
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java37
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/CommitRollbackParser.java23
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java28
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java57
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java15
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties1
43 files changed, 755 insertions, 425 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 1449ff1b1..362aeeadb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -565,6 +565,11 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
return false;
}
+ public boolean isQualifiedSuper() {
+
+ return false;
+ }
+
public boolean isThis() {
return false;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index fa9b241f7..e378b439f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -110,6 +110,8 @@ public class AllocationExpression extends Expression implements Invocation {
// hold on to this context from invocation applicability inference until invocation type inference (per method candidate):
private SimpleLookupTable/*<PMB,IC18>*/ inferenceContexts;
protected InnerInferenceHelper innerInferenceHelper;
+ public TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
+ public boolean argumentsHaveErrors;
/** Record to keep state between different parts of resolution. */
ResolutionState suspendedResolutionState;
@@ -119,7 +121,6 @@ public class AllocationExpression extends Expression implements Invocation {
boolean diamondNeedsDeferring;
boolean argsContainCast;
boolean cannotInferDiamond; // request the an error be reported in due time
- TypeBinding[] argumentTypes;
boolean hasReportedError;
ResolutionState(BlockScope scope, boolean isDiamond, boolean diamonNeedsDeferring,
@@ -129,7 +130,6 @@ public class AllocationExpression extends Expression implements Invocation {
this.isDiamond = isDiamond;
this.diamondNeedsDeferring = diamonNeedsDeferring;
this.argsContainCast = argsContainCast;
- this.argumentTypes = argumentTypes;
}
}
@@ -167,7 +167,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.arguments[i], flowInfo, flowContext, false);
}
this.arguments[i].checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
- }
+ }
analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
}
@@ -468,14 +468,14 @@ public TypeBinding resolveType(BlockScope scope) {
// resolve type arguments (for generic constructor call)
if (this.typeArguments != null) {
int length = this.typeArguments.length;
- boolean argHasError = sourceLevel < ClassFileConstants.JDK1_5;
+ this.argumentsHaveErrors = sourceLevel < ClassFileConstants.JDK1_5;
this.genericTypeArguments = new TypeBinding[length];
for (int i = 0; i < length; i++) {
TypeReference typeReference = this.typeArguments[i];
if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) {
- argHasError = true;
+ this.argumentsHaveErrors = true;
}
- if (argHasError && typeReference instanceof Wildcard) {
+ if (this.argumentsHaveErrors && typeReference instanceof Wildcard) {
scope.problemReporter().illegalUsageOfWildcard(typeReference);
}
}
@@ -483,7 +483,7 @@ public TypeBinding resolveType(BlockScope scope) {
scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments);
return null;
}
- if (argHasError) {
+ if (this.argumentsHaveErrors) {
if (this.arguments != null) { // still attempt to resolve arguments
for (int i = 0, max = this.arguments.length; i < max; i++) {
this.arguments[i].resolveType(scope);
@@ -495,11 +495,10 @@ public TypeBinding resolveType(BlockScope scope) {
// buffering the arguments' types
boolean argsContainCast = false;
- TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
if (this.arguments != null) {
- boolean argHasError = false;
+ this.argumentsHaveErrors = false;
int length = this.arguments.length;
- argumentTypes = new TypeBinding[length];
+ this.argumentTypes = new TypeBinding[length];
for (int i = 0; i < length; i++) {
Expression argument = this.arguments[i];
if (argument instanceof CastExpression) {
@@ -509,25 +508,25 @@ public TypeBinding resolveType(BlockScope scope) {
argument.setExpressionContext(INVOCATION_CONTEXT);
//{ObjectTeams: generated arguments can be pre-resolved indeed:
if (argument.resolvedType != null && argument.isGenerated()) {
- argumentTypes[i] = argument.resolvedType;
- if (argumentTypes[i] == null)
- argHasError = true;
+ this.argumentTypes[i] = argument.resolvedType;
+ if (this.argumentTypes[i] == null)
+ this.argumentsHaveErrors = true;
} else {
// orig:
if (this.arguments[i].resolvedType != null)
scope.problemReporter().genericInferenceError("Argument was unexpectedly found resolved", this); //$NON-NLS-1$
- if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
- argHasError = true;
+ if ((this.argumentTypes[i] = argument.resolveType(scope)) == null) {
+ this.argumentsHaveErrors = true;
}
// :giro
}
// SH}
- if (sourceLevel >= ClassFileConstants.JDK1_8 && argument.isPolyExpression()) {
+ if (sourceLevel >= ClassFileConstants.JDK1_8 && (argument.isPolyExpression() || ((argument instanceof Invocation) && ((Invocation) argument).usesInference()))) {
if (this.innerInferenceHelper == null)
this.innerInferenceHelper = new InnerInferenceHelper();
}
}
- if (argHasError) {
+ if (this.argumentsHaveErrors) {
/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case.
No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do
not return the partially resolved type.
@@ -539,7 +538,7 @@ public TypeBinding resolveType(BlockScope scope) {
// record a best guess, for clients who need hint about possible constructor match
TypeBinding[] pseudoArgs = new TypeBinding[length];
for (int i = length; --i >= 0;) {
- pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
+ pseudoArgs[i] = this.argumentTypes[i] == null ? TypeBinding.NULL : this.argumentTypes[i]; // replace args with errors with null type
}
this.binding = scope.findMethod((ReferenceBinding) this.resolvedType, TypeConstants.INIT, pseudoArgs, this, false);
if (this.binding != null && !this.binding.isValidBinding()) {
@@ -571,7 +570,7 @@ public TypeBinding resolveType(BlockScope scope) {
scope.problemReporter().cannotInstantiate(this.type, this.resolvedType);
return this.resolvedType;
}
- ResolutionState state = new ResolutionState(scope, isDiamond, diamondNeedsDeferring, argsContainCast, argumentTypes);
+ ResolutionState state = new ResolutionState(scope, isDiamond, diamondNeedsDeferring, argsContainCast, this.argumentTypes);
if (diamondNeedsDeferring) {
this.suspendedResolutionState = state; // resolving to be continued later (via binding(TypeBinding targetType)).
return new PolyTypeBinding(this);
@@ -587,7 +586,7 @@ boolean resolvePart2(ResolutionState state) {
// TODO: all information persisted during this method may need to be stored per targetType?
if (state.isDiamond) {
ReferenceBinding genericType = ((ParameterizedTypeBinding) this.resolvedType).genericType();
- TypeBinding [] inferredTypes = inferElidedTypes((ParameterizedTypeBinding) this.resolvedType, this.resolvedType.enclosingType(), state.argumentTypes, state.scope);
+ TypeBinding [] inferredTypes = inferElidedTypes((ParameterizedTypeBinding) this.resolvedType, this.resolvedType.enclosingType(), this.argumentTypes, state.scope);
if (inferredTypes == null) {
if (!state.diamondNeedsDeferring) {
state.scope.problemReporter().cannotInferElidedTypes(this);
@@ -608,7 +607,7 @@ boolean resolvePart2(ResolutionState state) {
// ensure allocation type has methods:
Dependencies.ensureBindingState(receiverType, ITranslationStates.STATE_LENV_DONE_FIELDS_AND_METHODS);
// SH}
- this.binding = findConstructorBinding(state.scope, this, receiverType, state.argumentTypes);
+ this.binding = findConstructorBinding(state.scope, this, receiverType, this.argumentTypes);
//:giro
} finally {
AnchorMapping.removeCurrentMapping(anchorMapping);
@@ -625,7 +624,7 @@ TypeBinding resolvePart3(ResolutionState state) {
if (state.cannotInferDiamond) {
state.scope.problemReporter().cannotInferElidedTypes(this);
return this.resolvedType = null;
- }
+ }
ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
if (!this.binding.isValidBinding()) {
//{ObjectTeams: baseclass decapsulation?
@@ -664,20 +663,20 @@ TypeBinding resolvePart3(ResolutionState state) {
}
if (isMethodUseDeprecated(this.binding, state.scope, true)) {
state.scope.problemReporter().deprecatedMethod(this.binding, this);
- }
- if (checkInvocationArguments(state.scope, null, allocationType, this.binding, this.arguments, state.argumentTypes, state.argsContainCast, this)) {
+ }
+ if (checkInvocationArguments(state.scope, null, allocationType, this.binding, this.arguments, this.argumentTypes, state.argsContainCast, this)) {
this.bits |= ASTNode.Unchecked;
}
if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
state.scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments);
}
if (!state.isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) {
- checkTypeArgumentRedundancy((ParameterizedTypeBinding) this.resolvedType, this.resolvedType.enclosingType(), state.argumentTypes, state.scope);
+ checkTypeArgumentRedundancy((ParameterizedTypeBinding) this.resolvedType, this.resolvedType.enclosingType(), this.argumentTypes, state.scope);
}
CompilerOptions compilerOptions = state.scope.compilerOptions();
if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
new ImplicitNullAnnotationVerifier(state.scope.environment(), compilerOptions.inheritNullAnnotations)
- .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, state.scope);
+ .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, state.scope);
}
recordExceptionsForEnclosingLambda(state.scope, this.binding.thrownExceptions);
//{ObjectTeams: may need to wrap the resolved type
@@ -732,13 +731,13 @@ void checkIllegalNullAnnotation(BlockScope scope, TypeBinding allocationType) {
}
}
-public TypeBinding[] inferElidedTypes(ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) {
+public TypeBinding[] inferElidedTypes(ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTyps, final BlockScope scope) {
/* Given the allocation type and the arguments to the constructor, see if we can synthesize a generic static factory
method that would, given the argument types and the invocation site, manufacture a parameterized object of type allocationType.
If we are successful then by design and construction, the parameterization of the return type of the factory method is identical
to the types elided in the <>.
*/
- MethodBinding factory = scope.getStaticFactory(allocationType, enclosingType, argumentTypes, this);
+ MethodBinding factory = scope.getStaticFactory(allocationType, enclosingType, argumentTyps, this);
if (factory instanceof ParameterizedGenericMethodBinding && factory.isValidBinding()) {
ParameterizedGenericMethodBinding genericFactory = (ParameterizedGenericMethodBinding) factory;
this.inferredReturnType = genericFactory.inferredReturnType;
@@ -748,9 +747,9 @@ public TypeBinding[] inferElidedTypes(ParameterizedTypeBinding allocationType, R
// refresh argumentTypes from updated bindings in arguments:
// (this shouldn't be strictly necessary, as FunctionExpression.isCompatibleWith() should give the same result,
// but it's probably be a good idea to avoid the necessity to call isCompatibleWith() in the first place).
- for (int i = 0; i < argumentTypes.length; i++) {
- if (argumentTypes[i] instanceof PolyTypeBinding)
- argumentTypes[i] = this.arguments[i].resolvedType;
+ for (int i = 0; i < argumentTyps.length; i++) {
+ if (argumentTyps[i] instanceof PolyTypeBinding)
+ argumentTyps[i] = this.arguments[i].resolvedType;
}
}
return ((ParameterizedTypeBinding)factory.returnType).arguments;
@@ -758,12 +757,12 @@ public TypeBinding[] inferElidedTypes(ParameterizedTypeBinding allocationType, R
return null;
}
-public void checkTypeArgumentRedundancy(ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) {
+public void checkTypeArgumentRedundancy(ParameterizedTypeBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTyps, final BlockScope scope) {
if ((scope.problemReporter().computeSeverity(IProblem.RedundantSpecificationOfTypeArguments) == ProblemSeverities.Ignore) || scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return;
if (allocationType.arguments == null) return; // raw binding
if (this.genericTypeArguments != null) return; // diamond can't occur with explicit type args for constructor
if (this.type == null) return;
- if (argumentTypes == Binding.NO_PARAMETERS && this.typeExpected instanceof ParameterizedTypeBinding) {
+ if (argumentTyps == Binding.NO_PARAMETERS && this.typeExpected instanceof ParameterizedTypeBinding) {
ParameterizedTypeBinding expected = (ParameterizedTypeBinding) this.typeExpected;
if (expected.arguments != null && allocationType.arguments.length == expected.arguments.length) {
// check the case when no ctor takes no params and inference uses the expected type directly
@@ -785,7 +784,7 @@ public void checkTypeArgumentRedundancy(ParameterizedTypeBinding allocationType,
// checking for redundant type parameters must fake a diamond,
// so we infer the same results as we would get with a diamond in source code:
this.type.bits |= IsDiamond;
- inferredTypes = inferElidedTypes(allocationType, enclosingType, argumentTypes, scope);
+ inferredTypes = inferElidedTypes(allocationType, enclosingType, argumentTyps, scope);
} finally {
// reset effects of inference
this.type.bits = previousBits;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index 54b6c6661..bcb140544 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -228,7 +228,7 @@ public TypeBinding resolveType(BlockScope scope) {
this.expression.setExpressionContext(ASSIGNMENT_CONTEXT);
this.expression.setExpectedType(lhsType); // needed in case of generic method invocation
if (lhsType != null) {
- this.resolvedType = lhsType.capture(scope, this.sourceEnd);
+ this.resolvedType = lhsType.capture(scope, this.lhs.sourceEnd); // make it unique, `this' shares source end with 'this.expression'.
}
LocalVariableBinding localVariableBinding = this.lhs.localVariableBinding();
if (localVariableBinding != null && (localVariableBinding.isCatchParameter() || localVariableBinding.isParameter())) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index df65187ff..3a5783171 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -39,12 +39,7 @@ public class Block extends Statement {
public int explicitDeclarations;
// the number of explicit declaration , used to create scope
public BlockScope scope;
- public boolean lambdaBody;
-public Block(int explicitDeclarations, boolean lambdaBody) {
- this.explicitDeclarations = explicitDeclarations;
- this.lambdaBody = lambdaBody;
-}
public Block(int explicitDeclarations) {
this.explicitDeclarations = explicitDeclarations;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index 55efa4eb8..c5f85a88a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -374,8 +374,9 @@ private static void checkAlternateBinding(BlockScope scope, Expression receiver,
public int sourceEnd() { return 0; }
public TypeBinding invocationTargetType() { return invocationSite.invocationTargetType(); }
public boolean receiverIsImplicitThis() { return invocationSite.receiverIsImplicitThis();}
- public InferenceContext18 freshInferenceContext(Scope someScope) { return null; /* suppress inference */ }
+ public InferenceContext18 freshInferenceContext(Scope someScope) { return invocationSite.freshInferenceContext(someScope); }
public ExpressionContext getExpressionContext() { return invocationSite.getExpressionContext(); }
+ public boolean isQualifiedSuper() { return invocationSite.isQualifiedSuper(); }
};
MethodBinding bindingIfNoCast;
if (binding.isConstructor()) {
@@ -421,7 +422,8 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
castType = ((WeakenedTypeBinding)castType).getStrongType();
// SH}
if (TypeBinding.equalsEquals(match, castType)) {
- if (!isNarrowing && TypeBinding.equalsEquals(match, this.resolvedType.leafComponentType())) { // do not tag as unnecessary when recursing through upper bounds
+ if (!isNarrowing && TypeBinding.equalsEquals(match, this.resolvedType.leafComponentType()) // do not tag as unnecessary when recursing through upper bounds
+ && !(expressionType.isParameterizedType() && expressionType.isProvablyDistinct(castType))) {
tagAsUnnecessaryCast(scope, castType);
}
return true;
@@ -736,7 +738,7 @@ public TypeBinding resolveType(BlockScope scope) {
this.bits |= ASTNode.DisableUnnecessaryCastCheck; // disable further secondary diagnosis
}
}
- this.resolvedType = castType.capture(scope, this.sourceEnd);
+ this.resolvedType = castType.capture(scope, this.type.sourceEnd); // make it unique, a cast expression shares source end with the expression.
if (exprContainCast) {
checkNeedForCastCast(scope, this);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
index f5b3c1d7a..a7552681d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ExplicitConstructorCall.java
@@ -509,7 +509,7 @@ public class ExplicitConstructorCall extends Statement implements Invocation {
argumentTypes[i] = argument.resolvedType;
}
// SH}
- if (sourceLevel >= ClassFileConstants.JDK1_8 && argument.isPolyExpression()) {
+ if (sourceLevel >= ClassFileConstants.JDK1_8 && (argument.isPolyExpression() || ((argument instanceof Invocation) && ((Invocation) argument).usesInference()))) {
if (this.innerInferenceHelper == null)
this.innerInferenceHelper = new InnerInferenceHelper();
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index affb2effb..67fb64226 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -542,6 +542,11 @@ public boolean isSuperAccess() {
return this.receiver.isSuper();
}
+@Override
+public boolean isQualifiedSuper() {
+ return this.receiver.isQualifiedSuper();
+}
+
public boolean isTypeAccess() {
return this.receiver != null && this.receiver.isTypeReference();
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
index 005fcc8c9..903f4443b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocAllocationExpression.java
@@ -4,7 +4,6 @@
* 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
- * $Id: JavadocAllocationExpression.java 19873 2009-04-13 16:51:05Z stephan $
*
* Contributors:
* IBM Corporation - initial API and implementation
@@ -53,26 +52,26 @@ public class JavadocAllocationExpression extends AllocationExpression {
}
// buffering the arguments' types
- TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
+ this.argumentTypes = Binding.NO_PARAMETERS;
boolean hasTypeVarArgs = false;
if (this.arguments != null) {
- boolean argHasError = false;
+ this.argumentsHaveErrors = false;
int length = this.arguments.length;
- argumentTypes = new TypeBinding[length];
+ this.argumentTypes = new TypeBinding[length];
for (int i = 0; i < length; i++) {
Expression argument = this.arguments[i];
if (scope.kind == Scope.CLASS_SCOPE) {
- argumentTypes[i] = argument.resolveType((ClassScope)scope);
+ this.argumentTypes[i] = argument.resolveType((ClassScope)scope);
} else {
- argumentTypes[i] = argument.resolveType((BlockScope)scope);
+ this.argumentTypes[i] = argument.resolveType((BlockScope)scope);
}
- if (argumentTypes[i] == null) {
- argHasError = true;
+ if (this.argumentTypes[i] == null) {
+ this.argumentsHaveErrors = true;
} else if (!hasTypeVarArgs) {
- hasTypeVarArgs = argumentTypes[i].isTypeVariable();
+ hasTypeVarArgs = this.argumentTypes[i].isTypeVariable();
}
}
- if (argHasError) {
+ if (this.argumentsHaveErrors) {
return null;
}
}
@@ -88,13 +87,13 @@ public class JavadocAllocationExpression extends AllocationExpression {
}
ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
- this.binding = scope.getConstructor(allocationType, argumentTypes, this);
+ this.binding = scope.getConstructor(allocationType, this.argumentTypes, this);
if (!this.binding.isValidBinding()) {
ReferenceBinding enclosingTypeBinding = allocationType;
MethodBinding contructorBinding = this.binding;
while (!contructorBinding.isValidBinding() && (enclosingTypeBinding.isMemberType() || enclosingTypeBinding.isLocalType())) {
enclosingTypeBinding = enclosingTypeBinding.enclosingType();
- contructorBinding = scope.getConstructor(enclosingTypeBinding, argumentTypes, this);
+ contructorBinding = scope.getConstructor(enclosingTypeBinding, this.argumentTypes, this);
}
if (contructorBinding.isValidBinding()) {
this.binding = contructorBinding;
@@ -103,7 +102,7 @@ public class JavadocAllocationExpression extends AllocationExpression {
if (!this.binding.isValidBinding()) {
// First try to search a method instead
//{ObjectTeams: don't use beautified name.
- MethodBinding methodBinding = scope.getMethod(this.resolvedType, this.resolvedType.internalName(), argumentTypes, this);
+ MethodBinding methodBinding = scope.getMethod(this.resolvedType, this.resolvedType.internalName(), this.argumentTypes, this);
// SH}
if (methodBinding.isValidBinding()) {
this.binding = methodBinding;
@@ -115,22 +114,22 @@ public class JavadocAllocationExpression extends AllocationExpression {
}
return this.resolvedType;
} else if (this.binding.isVarargs()) {
- int length = argumentTypes.length;
- if (!(this.binding.parameters.length == length && argumentTypes[length-1].isArrayType())) {
- MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, argumentTypes, ProblemReasons.NotFound);
+ int length = this.argumentTypes.length;
+ if (!(this.binding.parameters.length == length && this.argumentTypes[length-1].isArrayType())) {
+ MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, this.argumentTypes, ProblemReasons.NotFound);
scope.problemReporter().javadocInvalidConstructor(this, problem, scope.getDeclarationModifiers());
}
} else if (hasTypeVarArgs) {
- MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, argumentTypes, ProblemReasons.NotFound);
+ MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, this.argumentTypes, ProblemReasons.NotFound);
scope.problemReporter().javadocInvalidConstructor(this, problem, scope.getDeclarationModifiers());
} else if (this.binding instanceof ParameterizedMethodBinding) {
ParameterizedMethodBinding paramMethodBinding = (ParameterizedMethodBinding) this.binding;
if (paramMethodBinding.hasSubstitutedParameters()) {
- int length = argumentTypes.length;
+ int length = this.argumentTypes.length;
for (int i=0; i<length; i++) {
- if (TypeBinding.notEquals(paramMethodBinding.parameters[i], argumentTypes[i]) &&
- TypeBinding.notEquals(paramMethodBinding.parameters[i].erasure(), argumentTypes[i].erasure())) {
- MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, argumentTypes, ProblemReasons.NotFound);
+ if (TypeBinding.notEquals(paramMethodBinding.parameters[i], this.argumentTypes[i]) &&
+ TypeBinding.notEquals(paramMethodBinding.parameters[i].erasure(), this.argumentTypes[i].erasure())) {
+ MethodBinding problem = new ProblemMethodBinding(this.binding, this.binding.selector, this.argumentTypes, ProblemReasons.NotFound);
scope.problemReporter().javadocInvalidConstructor(this, problem, scope.getDeclarationModifiers());
break;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
index ef5ed425e..ec65a8edc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocMessageSend.java
@@ -4,7 +4,6 @@
* 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
- * $Id: JavadocMessageSend.java 23405 2010-02-03 17:02:18Z stephan $
*
* Contributors:
* IBM Corporation - initial API and implementation
@@ -61,26 +60,25 @@ public class JavadocMessageSend extends MessageSend {
// will check for null after args are resolved
- TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
boolean hasArgsTypeVar = false;
if (this.arguments != null) {
- boolean argHasError = false; // typeChecks all arguments
+ this.argumentsHaveErrors = false; // typeChecks all arguments
int length = this.arguments.length;
- argumentTypes = new TypeBinding[length];
+ this.argumentTypes = new TypeBinding[length];
for (int i = 0; i < length; i++){
Expression argument = this.arguments[i];
if (scope.kind == Scope.CLASS_SCOPE) {
- argumentTypes[i] = argument.resolveType((ClassScope)scope);
+ this.argumentTypes[i] = argument.resolveType((ClassScope)scope);
} else {
- argumentTypes[i] = argument.resolveType((BlockScope)scope);
+ this.argumentTypes[i] = argument.resolveType((BlockScope)scope);
}
- if (argumentTypes[i] == null) {
- argHasError = true;
+ if (this.argumentTypes[i] == null) {
+ this.argumentsHaveErrors = true;
} else if (!hasArgsTypeVar) {
- hasArgsTypeVar = argumentTypes[i].isTypeVariable();
+ hasArgsTypeVar = this.argumentTypes[i].isTypeVariable();
}
}
- if (argHasError) {
+ if (this.argumentsHaveErrors) {
return null;
}
}
@@ -97,15 +95,15 @@ public class JavadocMessageSend extends MessageSend {
// base type cannot receive any message
if (this.actualReceiverType.isBaseType()) {
- scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, argumentTypes, scope.getDeclarationModifiers());
+ scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, this.argumentTypes, scope.getDeclarationModifiers());
return null;
}
// {ObjectTeams:
AnchorMapping anchorMapping = null;
try {
- anchorMapping = beforeMethodLookup(argumentTypes, scope);
+ anchorMapping = beforeMethodLookup(this.argumentTypes, scope);
// jwl}
- this.binding = scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this);
+ this.binding = scope.getMethod(this.actualReceiverType, this.selector, this.argumentTypes, this);
// {ObjectTeams:
} finally {
// added by haebor according to MessageSend.resolveType(BlockScope)
@@ -120,7 +118,7 @@ public class JavadocMessageSend extends MessageSend {
MethodBinding methodBinding = this.binding;
while (!methodBinding.isValidBinding() && (enclosingTypeBinding.isMemberType() || enclosingTypeBinding.isLocalType())) {
enclosingTypeBinding = enclosingTypeBinding.enclosingType();
- methodBinding = scope.getMethod(enclosingTypeBinding, this.selector, argumentTypes, this);
+ methodBinding = scope.getMethod(enclosingTypeBinding, this.selector, this.argumentTypes, this);
}
if (methodBinding.isValidBinding()) {
this.binding = methodBinding;
@@ -129,12 +127,12 @@ public class JavadocMessageSend extends MessageSend {
enclosingTypeBinding = this.actualReceiverType;
MethodBinding contructorBinding = this.binding;
if (!contructorBinding.isValidBinding() && CharOperation.equals(this.selector, enclosingTypeBinding.shortReadableName())) {
- contructorBinding = scope.getConstructor((ReferenceBinding)enclosingTypeBinding, argumentTypes, this);
+ contructorBinding = scope.getConstructor((ReferenceBinding)enclosingTypeBinding, this.argumentTypes, this);
}
while (!contructorBinding.isValidBinding() && (enclosingTypeBinding.isMemberType() || enclosingTypeBinding.isLocalType())) {
enclosingTypeBinding = enclosingTypeBinding.enclosingType();
if (CharOperation.equals(this.selector, enclosingTypeBinding.shortReadableName())) {
- contructorBinding = scope.getConstructor((ReferenceBinding)enclosingTypeBinding, argumentTypes, this);
+ contructorBinding = scope.getConstructor((ReferenceBinding)enclosingTypeBinding, this.argumentTypes, this);
}
}
if (contructorBinding.isValidBinding()) {
@@ -164,7 +162,7 @@ public class JavadocMessageSend extends MessageSend {
if (this.actualReceiverType instanceof ReferenceBinding) {
this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
} else {
- scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, argumentTypes, scope.getDeclarationModifiers());
+ scope.problemReporter().javadocErrorNoMethodFor(this, this.actualReceiverType, this.argumentTypes, scope.getDeclarationModifiers());
return null;
}
}
@@ -176,19 +174,19 @@ public class JavadocMessageSend extends MessageSend {
}
return this.resolvedType = this.binding == null ? null : this.binding.returnType;
} else if (hasArgsTypeVar) {
- MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, argumentTypes, ProblemReasons.NotFound);
+ MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, this.argumentTypes, ProblemReasons.NotFound);
scope.problemReporter().javadocInvalidMethod(this, problem, scope.getDeclarationModifiers());
} else if (this.binding.isVarargs()) {
- int length = argumentTypes.length;
- if (!(this.binding.parameters.length == length && argumentTypes[length-1].isArrayType())) {
- MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, argumentTypes, ProblemReasons.NotFound);
+ int length = this.argumentTypes.length;
+ if (!(this.binding.parameters.length == length && this.argumentTypes[length-1].isArrayType())) {
+ MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, this.argumentTypes, ProblemReasons.NotFound);
scope.problemReporter().javadocInvalidMethod(this, problem, scope.getDeclarationModifiers());
}
} else {
- int length = argumentTypes.length;
+ int length = this.argumentTypes.length;
for (int i=0; i<length; i++) {
- if (TypeBinding.notEquals(this.binding.parameters[i].erasure(), argumentTypes[i].erasure())) {
- MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, argumentTypes, ProblemReasons.NotFound);
+ if (TypeBinding.notEquals(this.binding.parameters[i].erasure(), this.argumentTypes[i].erasure())) {
+ MethodBinding problem = new ProblemMethodBinding(this.binding, this.selector, this.argumentTypes, ProblemReasons.NotFound);
scope.problemReporter().javadocInvalidMethod(this, problem, scope.getDeclarationModifiers());
break;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
index a23c17fc0..a7dd51aa5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
@@ -107,6 +107,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
private boolean shapeAnalysisComplete = false;
boolean returnsValue;
public boolean isSerializable;
+ private boolean requiresGenericSignature;
boolean returnsVoid;
public LambdaExpression original = this;
public SyntheticArgumentBinding[] outerLocalVariables = NO_SYNTHETIC_ARGUMENTS;
@@ -119,15 +120,20 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
private Set thrownExceptions;
public char[] text; // source representation of the lambda.
private static final SyntheticArgumentBinding [] NO_SYNTHETIC_ARGUMENTS = new SyntheticArgumentBinding[0];
- private static final Block NO_BODY = new Block(0, true);
+ private static final Block NO_BODY = new Block(0);
- public LambdaExpression(CompilationResult compilationResult, boolean assistNode) {
+ public LambdaExpression(CompilationResult compilationResult, boolean assistNode, boolean requiresGenericSignature) {
super(compilationResult);
this.assistNode = assistNode;
+ this.requiresGenericSignature = requiresGenericSignature;
setArguments(NO_ARGUMENTS);
setBody(NO_BODY);
}
-
+
+ public LambdaExpression(CompilationResult compilationResult, boolean assistNode) {
+ this(compilationResult, assistNode, false);
+ }
+
public void setArguments(Argument [] arguments) {
this.arguments = arguments != null ? arguments : ASTNode.NO_ARGUMENTS;
this.argumentTypes = new TypeBinding[arguments != null ? arguments.length : 0];
@@ -172,6 +178,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
this.binding.modifiers |= ClassFileConstants.AccStatic;
}
SourceTypeBinding sourceType = currentScope.enclosingSourceType();
+ boolean firstSpill = !(this.binding instanceof SyntheticMethodBinding);
this.binding = sourceType.addSyntheticMethod(this);
int pc = codeStream.position;
StringBuffer signature = new StringBuffer();
@@ -182,7 +189,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
}
for (int i = 0, length = this.outerLocalVariables == null ? 0 : this.outerLocalVariables.length; i < length; i++) {
SyntheticArgumentBinding syntheticArgument = this.outerLocalVariables[i];
- if (this.shouldCaptureInstance) {
+ if (this.shouldCaptureInstance && firstSpill) { // finally block handling results in extra spills, avoid side effect.
syntheticArgument.resolvedPosition++;
}
signature.append(syntheticArgument.type.signature());
@@ -336,7 +343,11 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
this.resolvedType = null; // continue to type check.
}
}
-
+ if (this.requiresGenericSignature) {
+ TypeBinding leafType = parameterType.leafComponentType();
+ if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
+ this.binding.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
+ }
newParameters[i] = argument.bind(this.scope, parameterType, false);
if (argument.annotations != null) {
this.binding.tagBits |= TagBits.HasParameterAnnotations;
@@ -372,6 +383,8 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
if ((exception.tagBits & TagBits.HasMissingType) != 0) {
this.binding.tagBits |= TagBits.HasMissingType;
}
+ if (this.requiresGenericSignature)
+ this.binding.modifiers |= (exception.modifiers & ExtraCompilerModifiers.AccGenericSignature);
}
TypeBinding returnType = this.binding.returnType;
@@ -379,6 +392,11 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
if ((returnType.tagBits & TagBits.HasMissingType) != 0) {
this.binding.tagBits |= TagBits.HasMissingType;
}
+ if (this.requiresGenericSignature) {
+ TypeBinding leafType = returnType.leafComponentType();
+ if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
+ this.binding.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
+ }
} // TODO (stephan): else? (can that happen?)
if (haveDescriptor && !buggyArguments && blockScope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
@@ -414,6 +432,9 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
this.scope.problemReporter().missingTypeInLambda(this, this.binding);
}
+ if (this.shouldCaptureInstance && this.scope.isConstructorCall) {
+ this.scope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this);
+ }
return this.resolvedType;
}
@@ -733,12 +754,14 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
if (this.body instanceof Block) {
if (this.returnsVoid) {
this.shapeAnalysisComplete = true;
+ break shapeAnalysis;
}
} else {
- final Expression expressionBody = (Expression) this.body;
+ final Expression expressionBody = (Expression) copy.body;
this.voidCompatible = this.assistNode ? true : expressionBody.statementExpression();
this.valueCompatible = expressionBody.resolvedType != TypeBinding.VOID;
this.shapeAnalysisComplete = true;
+ break shapeAnalysis;
}
// Do not proceed with data/control flow analysis if resolve encountered errors.
if (this.hasIgnoredMandatoryErrors || enclosingScopesHaveErrors()) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index d363c0dcf..75db50709 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -193,6 +193,11 @@ public class MessageSend extends Expression implements Invocation {
// hold on to this context from invocation applicability inference until invocation type inference (per method candidate):
private SimpleLookupTable/*<PGMB,InferenceContext18>*/ inferenceContexts;
protected InnerInferenceHelper innerInferenceHelper;
+ private boolean receiverIsType;
+ protected boolean argsContainCast;
+ public TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
+ public boolean argumentsHaveErrors;
+
//{ObjectTeams:
private boolean isDecapsulation = false;
@@ -802,7 +807,7 @@ public TypeBinding resolveType(BlockScope scope) {
this.constant = Constant.NotAConstant;
long sourceLevel = scope.compilerOptions().sourceLevel;
- boolean receiverCast = false, argsContainCast = false;
+ boolean receiverCast = false;
if (this.receiver instanceof CastExpression) {
this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
receiverCast = true;
@@ -818,10 +823,10 @@ public TypeBinding resolveType(BlockScope scope) {
// :giro
}
/*orig:
- boolean receiverIsType = this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0;
+ this.receiverIsType = this.receiver instanceof NameReference && (((NameReference) this.receiver).bits & Binding.TYPE) != 0;
*/
// don't only expect NameReference, BaseReference can be static, too.
- boolean receiverIsType = ( (this.receiver instanceof NameReference)
+ this.receiverIsType = ( (this.receiver instanceof NameReference)
|| (this.receiver instanceof BaseReference))
&& (this.receiver.bits & Binding.TYPE) != 0
|| (this.receiver instanceof TypeReference); // happens in generated AST
@@ -835,18 +840,18 @@ public TypeBinding resolveType(BlockScope scope) {
// resolve type arguments (for generic constructor call)
if (this.typeArguments != null) {
int length = this.typeArguments.length;
- boolean argHasError = sourceLevel < ClassFileConstants.JDK1_5; // typeChecks all arguments
+ this.argumentsHaveErrors = sourceLevel < ClassFileConstants.JDK1_5; // typeChecks all arguments
this.genericTypeArguments = new TypeBinding[length];
for (int i = 0; i < length; i++) {
TypeReference typeReference = this.typeArguments[i];
if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) {
- argHasError = true;
+ this.argumentsHaveErrors = true;
}
- if (argHasError && typeReference instanceof Wildcard) {
+ if (this.argumentsHaveErrors && typeReference instanceof Wildcard) {
scope.problemReporter().illegalUsageOfWildcard(typeReference);
}
}
- if (argHasError) {
+ if (this.argumentsHaveErrors) {
if (this.arguments != null) { // still attempt to resolve arguments
for (int i = 0, max = this.arguments.length; i < max; i++) {
this.arguments[i].resolveType(scope);
@@ -856,11 +861,10 @@ public TypeBinding resolveType(BlockScope scope) {
}
}
// will check for null after args are resolved
- TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
if (this.arguments != null) {
- boolean argHasError = false; // typeChecks all arguments
+ this.argumentsHaveErrors = false; // typeChecks all arguments
int length = this.arguments.length;
- argumentTypes = new TypeBinding[length];
+ this.argumentTypes = new TypeBinding[length];
for (int i = 0; i < length; i++){
Expression argument = this.arguments[i];
//{ObjectTeams: keep pre-resolved binding inside generated code:
@@ -870,16 +874,16 @@ public TypeBinding resolveType(BlockScope scope) {
scope.problemReporter().genericInferenceError("Argument was unexpectedly found resolved", this); //$NON-NLS-1$
if (argument instanceof CastExpression) {
argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
- argsContainCast = true;
+ this.argsContainCast = true;
}
argument.setExpressionContext(INVOCATION_CONTEXT);
//{ObjectTeams: arguments might already be resolved, see e.g. CastExpression.createRoleCheck
if (argument.resolvedType != null) {
- argumentTypes[i] = argument.resolvedType;
+ this.argumentTypes[i] = argument.resolvedType;
} else {
// orig:
- if ((argumentTypes[i] = argument.resolveType(scope)) == null){
- argHasError = true;
+ if ((this.argumentTypes[i] = argument.resolveType(scope)) == null){
+ this.argumentsHaveErrors = true;
}
// :giro
}
@@ -892,12 +896,12 @@ public TypeBinding resolveType(BlockScope scope) {
}
}
}
- if (argHasError) {
+ if (this.argumentsHaveErrors) {
if (this.actualReceiverType instanceof ReferenceBinding) {
// record a best guess, for clients who need hint about possible method match
TypeBinding[] pseudoArgs = new TypeBinding[length];
for (int i = length; --i >= 0;)
- pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
+ pseudoArgs[i] = this.argumentTypes[i] == null ? TypeBinding.NULL : this.argumentTypes[i]; // replace args with errors with null type
this.binding =
this.receiver.isImplicitThis()
? scope.getImplicitMethod(this.selector, pseudoArgs, this)
@@ -933,7 +937,7 @@ public TypeBinding resolveType(BlockScope scope) {
}
// base type cannot receive any message
if (this.actualReceiverType.isBaseType()) {
- scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
+ scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, this.argumentTypes);
return null;
}
//{ObjectTeams: revert receiver weakening & setup anchorMapping:
@@ -974,7 +978,7 @@ public TypeBinding resolveType(BlockScope scope) {
this.selector=IOTConstants._OT_GETBASE;
// orig:
- findMethodBinding(scope, argumentTypes);
+ findMethodBinding(scope);
// :giro
if (this.binding == null)
@@ -1043,7 +1047,7 @@ public TypeBinding resolveType(BlockScope scope) {
if (this.actualReceiverType instanceof ReferenceBinding) {
this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
} else {
- scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
+ scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, this.argumentTypes);
return null;
}
}
@@ -1161,7 +1165,7 @@ public TypeBinding resolveType(BlockScope scope) {
}
if (!this.binding.isStatic()) {
// the "receiver" must not be a type
- if (receiverIsType) {
+ if (this.receiverIsType) {
scope.problemReporter().mustUseAStaticMethod(this, this.binding);
if (this.actualReceiverType.isRawType()
&& (this.receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0
@@ -1180,14 +1184,14 @@ public TypeBinding resolveType(BlockScope scope) {
}
} else {
// static message invoked through receiver? legal but unoptimal (optional warning).
- if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || receiverIsType)) {
+ if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || this.receiverIsType)) {
scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding);
}
if (!this.receiver.isImplicitThis() && TypeBinding.notEquals(this.binding.declaringClass, this.actualReceiverType)) {
scope.problemReporter().indirectAccessToStaticMethod(this, this.binding);
}
}
- if (checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) {
+ if (checkInvocationArguments(scope, this.receiver, this.actualReceiverType, this.binding, this.arguments, this.argumentTypes, this.argsContainCast, this)) {
this.bits |= ASTNode.Unchecked;
}
@@ -1277,7 +1281,7 @@ public TypeBinding resolveType(BlockScope scope) {
}
if (this.receiver.isSuper() && this.actualReceiverType.isInterface()) {
// 15.12.3 (Java 8)
- scope.checkAppropriateMethodAgainstSupers(this.selector, this.binding, argumentTypes, this);
+ scope.checkAppropriateMethodAgainstSupers(this.selector, this.binding, this.argumentTypes, this);
}
if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
scope.problemReporter().unnecessaryTypeArgumentsForMethodInvocation(this.binding, this.genericTypeArguments, this.typeArguments);
@@ -1293,11 +1297,11 @@ public TypeBinding resolveType(BlockScope scope) {
* after applicability checking (18.5.1) to include more information into the final
* invocation type inference (18.5.2).
*/
-protected void findMethodBinding(BlockScope scope, TypeBinding[] argumentTypes) {
+protected void findMethodBinding(BlockScope scope) {
this.binding = this.receiver.isImplicitThis()
- ? scope.getImplicitMethod(this.selector, argumentTypes, this)
- : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this);
- resolvePolyExpressionArguments(this, this.binding, argumentTypes, scope);
+ ? scope.getImplicitMethod(this.selector, this.argumentTypes, this)
+ : scope.getMethod(this.actualReceiverType, this.selector, this.argumentTypes, this);
+ resolvePolyExpressionArguments(this, this.binding, this.argumentTypes, scope);
/* There are embedded assumptions in the JLS8 type inference scheme that a successful solution of the type equations results in an
applicable method. This appears to be a tenuous assumption, at least one not made by the JLS7 engine or the reference compiler and
@@ -1673,4 +1677,8 @@ public InnerInferenceHelper innerInferenceHelper() {
public InferenceContext18 freshInferenceContext(Scope scope) {
return new InferenceContext18(scope, this.arguments, this);
}
+@Override
+public boolean isQualifiedSuper() {
+ return this.receiver.isQualifiedSuper();
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index 9e7c2a074..bc0a6d7f6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -18,9 +18,6 @@
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
* bug 388996 - [compiler][resource] Incorrect 'potential resource leak'
* bug 395977 - [compiler][resource] Resource leak warning behavior possibly incorrect for anonymous inner class
- * Bug 416267 - NPE in QualifiedAllocationExpression.resolveType
- * Andy Clement - Contributions for
- * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
@@ -458,14 +455,14 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0;
if (this.typeArguments != null) {
int length = this.typeArguments.length;
- boolean argHasError = sourceLevel < ClassFileConstants.JDK1_5;
+ this.argumentsHaveErrors = sourceLevel < ClassFileConstants.JDK1_5;
this.genericTypeArguments = new TypeBinding[length];
for (int i = 0; i < length; i++) {
TypeReference typeReference = this.typeArguments[i];
if ((this.genericTypeArguments[i] = typeReference.resolveType(scope, true /* check bounds*/)) == null) {
- argHasError = true;
+ this.argumentsHaveErrors = true;
}
- if (argHasError && typeReference instanceof Wildcard) {
+ if (this.argumentsHaveErrors && typeReference instanceof Wildcard) {
scope.problemReporter().illegalUsageOfWildcard(typeReference);
}
}
@@ -473,7 +470,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments);
return null;
}
- if (argHasError) {
+ if (this.argumentsHaveErrors) {
if (this.arguments != null) { // still attempt to resolve arguments
for (int i = 0, max = this.arguments.length; i < max; i++) {
this.arguments[i].resolveType(scope);
@@ -484,10 +481,10 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
}
// will check for null after args are resolved
- TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
+ this.argumentTypes = Binding.NO_PARAMETERS;
if (this.arguments != null) {
int length = this.arguments.length;
- argumentTypes = new TypeBinding[length];
+ this.argumentTypes = new TypeBinding[length];
for (int i = 0; i < length; i++) {
Expression argument = this.arguments[i];
if (argument instanceof CastExpression) {
@@ -495,10 +492,10 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
argsContainCast = true;
}
argument.setExpressionContext(INVOCATION_CONTEXT);
- if ((argumentTypes[i] = argument.resolveType(scope)) == null){
+ if ((this.argumentTypes[i] = argument.resolveType(scope)) == null){
hasError = true;
}
- if (sourceLevel >= ClassFileConstants.JDK1_8 && argument.isPolyExpression()) {
+ if (sourceLevel >= ClassFileConstants.JDK1_8 && (argument.isPolyExpression() || (argument instanceof Invocation && ((Invocation)argument).usesInference()))) {
if (this.innerInferenceHelper == null)
this.innerInferenceHelper = new InnerInferenceHelper();
}
@@ -525,7 +522,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
int length = this.arguments == null ? 0 : this.arguments.length;
TypeBinding[] pseudoArgs = new TypeBinding[length];
for (int i = length; --i >= 0;) {
- pseudoArgs[i] = argumentTypes[i] == null ? TypeBinding.NULL : argumentTypes[i]; // replace args with errors with null type
+ pseudoArgs[i] = this.argumentTypes[i] == null ? TypeBinding.NULL : this.argumentTypes[i]; // replace args with errors with null type
}
this.binding = scope.findMethod(referenceReceiver, TypeConstants.INIT, pseudoArgs, this, false);
if (this.binding != null && !this.binding.isValidBinding()) {
@@ -561,7 +558,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
return this.resolvedType = receiverType;
}
if (isDiamond) {
- TypeBinding [] inferredTypes = inferElidedTypes((ParameterizedTypeBinding) receiverType, receiverType.enclosingType(), argumentTypes, scope);
+ TypeBinding [] inferredTypes = inferElidedTypes((ParameterizedTypeBinding) receiverType, receiverType.enclosingType(), this.argumentTypes, scope);
if (inferredTypes == null) {
scope.problemReporter().cannotInferElidedTypes(this);
return this.resolvedType = null;
@@ -578,7 +575,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
null, this.arguments, scope);
try {
// orig:
- this.binding = findConstructorBinding(scope, this, allocationType, argumentTypes);
+ this.binding = findConstructorBinding(scope, this, allocationType, this.argumentTypes);
// :giro
} finally {
AnchorMapping.removeCurrentMapping(anchorMapping);
@@ -589,7 +586,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
if (isMethodUseDeprecated(this.binding, scope, true)) {
scope.problemReporter().deprecatedMethod(this.binding, this);
}
- if (checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, argumentTypes, argsContainCast, this)) {
+ if (checkInvocationArguments(scope, null, allocationType, this.binding, this.arguments, this.argumentTypes, argsContainCast, this)) {
this.bits |= ASTNode.Unchecked;
}
if (this.typeArguments != null && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
@@ -614,8 +611,8 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
}
} else {
// orig:
- scope.problemReporter().invalidConstructor(this, this.binding);
- return this.resolvedType = receiverType;
+ scope.problemReporter().invalidConstructor(this, this.binding);
+ return this.resolvedType = receiverType;
// :giro
}
// SH}
@@ -624,7 +621,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
scope.problemReporter().missingTypeInConstructor(this, this.binding);
}
if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments()) {
- checkTypeArgumentRedundancy((ParameterizedTypeBinding)receiverType, receiverType.enclosingType(), argumentTypes , scope);
+ checkTypeArgumentRedundancy((ParameterizedTypeBinding)receiverType, receiverType.enclosingType(), this.argumentTypes , scope);
}
// The enclosing instance must be compatible with the innermost enclosing type
ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
@@ -670,7 +667,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) {
return null; // stop secondary errors
}
- MethodBinding inheritedBinding = findConstructorBinding(scope, this, anonymousSuperclass, argumentTypes);
+ MethodBinding inheritedBinding = findConstructorBinding(scope, this, anonymousSuperclass, this.argumentTypes);
if (!inheritedBinding.isValidBinding()) {
if (inheritedBinding.declaringClass == null) {
@@ -698,7 +695,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType);
}
if (this.arguments != null) {
- if (checkInvocationArguments(scope, null, anonymousSuperclass, inheritedBinding, this.arguments, argumentTypes, argsContainCast, this)) {
+ if (checkInvocationArguments(scope, null, anonymousSuperclass, inheritedBinding, this.arguments, this.argumentTypes, argsContainCast, this)) {
this.bits |= ASTNode.Unchecked;
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
index 46472760c..43761941a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedSuperReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -27,6 +27,10 @@ public boolean isSuper() {
return true;
}
+public boolean isQualifiedSuper() {
+ return true;
+}
+
public boolean isThis() {
return false;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index 310c53d91..e9465f353 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -56,10 +56,12 @@ import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.InferenceContext18;
import org.eclipse.jdt.internal.compiler.lookup.IntersectionCastTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -116,7 +118,7 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
int argc = this.descriptor.parameters.length;
- LambdaExpression implicitLambda = new LambdaExpression(this.compilationResult, false);
+ LambdaExpression implicitLambda = new LambdaExpression(this.compilationResult, false, (this.binding.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0);
Argument [] arguments = new Argument[argc];
for (int i = 0; i < argc; i++)
arguments[i] = new Argument(("arg" + i).toCharArray(), 0, null, 0, true); //$NON-NLS-1$
@@ -409,10 +411,7 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
return this.resolvedType = null; // nope, no useful type found
// Convert parameters into argument expressions for look up.
- TypeBinding[] descriptorParameters = this.descriptor != null && this.descriptor.parameters != null && this.descriptor.parameters.length > 0 ?
- new TypeBinding[this.descriptor.parameters.length] : Binding.NO_PARAMETERS;
- for (int i = 0, length = descriptorParameters.length; i < length; i++)
- descriptorParameters[i] = this.descriptor.parameters[i].capture(scope, this.sourceEnd);
+ TypeBinding[] descriptorParameters = descriptorParametersAsArgumentExpressions();
if (lhsType.isBaseType()) {
scope.problemReporter().errorNoMethodFor(this.lhs, lhsType, this.selector, descriptorParameters);
@@ -440,8 +439,19 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
// handle the special case of array construction first.
this.receiverType = lhsType;
+
+ this.haveReceiver = true;
+ if (this.lhs instanceof NameReference) {
+ if ((this.lhs.bits & ASTNode.RestrictiveFlagMASK) == Binding.TYPE) {
+ this.haveReceiver = false;
+ }
+ } else if (this.lhs instanceof TypeReference) {
+ this.haveReceiver = false;
+ }
+
if (!this.haveReceiver && !this.lhs.isSuper() && !this.isArrayConstructorReference())
this.receiverType = lhsType.capture(scope, this.sourceEnd);
+
final int parametersLength = descriptorParameters.length;
if (isConstructorReference() && lhsType.isArrayType()) {
final TypeBinding leafComponentType = lhsType.leafComponentType();
@@ -457,18 +467,15 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
scope.problemReporter().constructedArrayIncompatible(this, lhsType, this.descriptor.returnType);
return this.resolvedType = null;
}
+
+ if (this.typeArguments != null) {
+ scope.problemReporter().invalidTypeArguments(this.typeArguments);
+ return this.resolvedType = null;
+ }
+
this.binding = this.exactMethodBinding = scope.getExactConstructor(lhsType, this);
return this.resolvedType;
}
-
- this.haveReceiver = true;
- if (this.lhs instanceof NameReference) {
- if ((this.lhs.bits & ASTNode.RestrictiveFlagMASK) == Binding.TYPE) {
- this.haveReceiver = false;
- }
- } else if (this.lhs instanceof TypeReference) {
- this.haveReceiver = false;
- }
/* For Reference expressions unlike other call sites, we always have a receiver _type_ since LHS of :: cannot be empty.
LHS's resolved type == actual receiver type. All code below only when a valid descriptor is available.
@@ -666,6 +673,25 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
return this.resolvedType; // Phew !
}
+ private TypeBinding[] descriptorParametersAsArgumentExpressions() {
+
+ if (this.descriptor == null || this.descriptor.parameters == null || this.descriptor.parameters.length == 0)
+ return Binding.NO_PARAMETERS;
+
+ /* 15.13.1, " ... method reference is treated as if it were an invocation with argument expressions of types P1, ..., Pn;"
+ This implies/requires wildcard capture. This creates interesting complications, we can't just take the descriptor parameters
+ and apply captures - where a single wildcard type got "fanned out" and propagated into multiple locations through type variable
+ substitutions, we will end up creating distinct captures defeating the very idea of capture. We need to first capture and then
+ fan out. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=432759.
+ */
+ if (this.expectedType.isParameterizedType()) {
+ ParameterizedTypeBinding type = (ParameterizedTypeBinding) this.expectedType;
+ MethodBinding method = type.getSingleAbstractMethod(this.enclosingScope, true, this.sourceEnd);
+ return method.parameters;
+ }
+ return this.descriptor.parameters;
+ }
+
/** During inference: Try to find an applicable method binding without causing undesired side-effects. */
public MethodBinding findCompileTimeMethodTargeting(TypeBinding targetType, Scope scope) {
MethodBinding targetMethod = internalResolveTentatively(targetType, scope);
@@ -681,6 +707,7 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
MethodBinding previousBinding = this.binding;
MethodBinding previousDescriptor = this.descriptor;
TypeBinding previousResolvedType = this.resolvedType;
+ TypeBinding previousExpectedType = this.expectedType;
try {
setExpressionContext(INVOCATION_CONTEXT);
setExpectedType(targetType);
@@ -695,7 +722,7 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
this.descriptor = previousDescriptor;
this.resolvedType = previousResolvedType;
setExpressionContext(previousContext);
- this.expectedType = null; // don't call setExpectedType(null), would NPE
+ this.expectedType = previousExpectedType;
this.trialResolution = false;
}
}
@@ -823,7 +850,6 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
return this.resolvedType.isCompatibleWith(left, scope);
}
// 15.13.2
- left = left.uncapture(this.enclosingScope);
final MethodBinding sam = left.getSingleAbstractMethod(this.enclosingScope, true);
if (sam == null || !sam.isValidBinding())
return false;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
index b6ef490d1..a0386ff99 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
@@ -65,6 +65,12 @@ public class SingleTypeReference extends TypeReference {
if (typeVariable.declaringElement instanceof SourceTypeBinding) {
scope.tagAsAccessingEnclosingInstanceStateOf((ReferenceBinding) typeVariable.declaringElement, true /* type variable access */);
}
+ } else if (this.resolvedType instanceof LocalTypeBinding) {
+ LocalTypeBinding localType = (LocalTypeBinding) this.resolvedType;
+ MethodScope methodScope = scope.methodScope();
+ if (methodScope != null && !methodScope.isStatic) {
+ methodScope.tagAsAccessingEnclosingInstanceStateOf(localType, false /* ! type variable access */);
+ }
}
if (scope.kind == Scope.CLASS_SCOPE && this.resolvedType.isValidBinding())
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java
index 19994fa35..86ad2be17 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 432977 - [1.8][null] Incorrect 'type is not visible' compiler error
+ * Bug 446434 - [1.8][null] Enable interned captures also when analysing null type annotations
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -379,6 +380,10 @@ public class AnnotatableTypeSystem extends TypeSystem {
TypeBinding annotatedType = type.clone(enclosingType);
annotatedType.id = nakedType.id;
annotatedType.setTypeAnnotations(annotations, this.isAnnotationBasedNullAnalysisEnabled);
+ if (this.isAnnotationBasedNullAnalysisEnabled && (annotatedType.tagBits & TagBits.AnnotationNullMASK) == 0) {
+ // propagate nullness unless overridden in 'annotations':
+ annotatedType.tagBits |= type.tagBits & TagBits.AnnotationNullMASK;
+ }
TypeBinding keyType;
switch (type.kind()) {
case Binding.ARRAY_TYPE:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index af46df150..60750c2eb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -149,11 +149,8 @@ public final void addLocalType(TypeDeclaration localType) {
MethodScope methodScope = methodScope();
while (methodScope != null && methodScope.referenceContext instanceof LambdaExpression) {
LambdaExpression lambda = (LambdaExpression) methodScope.referenceContext;
- if (!lambda.scope.isStatic) {
+ if (!lambda.scope.isStatic && !lambda.scope.isConstructorCall) {
lambda.shouldCaptureInstance = true;
- if (lambda.scope.isConstructorCall) {
- lambda.scope.problemReporter().noSuchEnclosingInstance(enclosingSourceType(), lambda, true);
- }
}
methodScope = methodScope.enclosingMethodScope();
}
@@ -1199,6 +1196,11 @@ public String toString(int tab) {
private List trackingVariables; // can be null if no resources are tracked
/** Used only during analyseCode and only for checking if a resource was closed in a finallyBlock. */
public FlowInfo finallyInfo;
+public boolean shouldConsultShadowOriginal;
+
+public boolean shouldConsultShadowOriginal() {
+ return this.shouldConsultShadowOriginal;
+}
/**
* Register a tracking variable and compute its id.
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
index c438ac56d..5290623a7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
@@ -46,20 +46,17 @@ class BoundSet {
// empty, the sets are lazily initialized
}
/** Add a type bound to the appropriate set. */
- public void addBound(TypeBound bound) {
+ public boolean addBound(TypeBound bound) {
switch (bound.relation) {
case ReductionResult.SUPERTYPE:
if (this.superBounds == null) this.superBounds = new HashSet<TypeBound>();
- this.superBounds.add(bound);
- break;
+ return this.superBounds.add(bound);
case ReductionResult.SAME:
if (this.sameBounds == null) this.sameBounds = new HashSet<TypeBound>();
- this.sameBounds.add(bound);
- break;
+ return this.sameBounds.add(bound);
case ReductionResult.SUBTYPE:
if (this.subBounds == null) this.subBounds = new HashSet<TypeBound>();
- this.subBounds.add(bound);
- break;
+ return this.subBounds.add(bound);
default:
throw new IllegalArgumentException("Unexpected bound relation in : " + bound); //$NON-NLS-1$
}
@@ -277,16 +274,16 @@ class BoundSet {
}
public void setInstantiation(TypeBinding type, InferenceVariable variable, LookupEnvironment environment) {
if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
- long oldBits = ((this.instantiation != null) ? this.instantiation.tagBits : variable.tagBits)
- & TagBits.AnnotationNullMASK;
- long requestedBits = type.tagBits & TagBits.AnnotationNullMASK;
- long newBits = (oldBits == TagBits.AnnotationNonNull) ? oldBits : requestedBits; // need to preserve @NonNull
- if (this.instantiation != null && oldBits == newBits) {
- return; // no update needed
+ long variableBits = variable.tagBits & TagBits.AnnotationNullMASK;
+ long allBits = type.tagBits | variableBits;
+ if (this.instantiation != null)
+ allBits |= this.instantiation.tagBits;
+ allBits &= TagBits.AnnotationNullMASK;
+ if (allBits == TagBits.AnnotationNullMASK) { // contradiction
+ allBits = variableBits;
}
- if (requestedBits != newBits) {
- // adjust 'type' to fit the newBits
- AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(newBits);
+ if (allBits != (type.tagBits & TagBits.AnnotationNullMASK)) {
+ AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(allBits);
if (annot != null)
type = environment.createAnnotatedType(type.withoutToplevelNullAnnotation(), annot);
}
@@ -305,9 +302,11 @@ class BoundSet {
/** 18.1.3 bullet 5: throws α */
Set<InferenceVariable> inThrows = new HashSet<InferenceVariable>();
- // avoid attempts to incorporate the same pair of type bounds more than once:
- Set<TypeBound> incorporatedBounds = new HashSet<TypeBound>();
-
+ private TypeBound [] incorporatedBounds = new TypeBound[0];
+ private TypeBound [] unincorporatedBounds = new TypeBound [1024];
+ private int unincorporatedBoundsCount = 0;
+ private TypeBound [] mostRecentBounds = new TypeBound[4]; // for quick & dirty duplicate elimination.
+
public BoundSet() {}
// pre: typeParameters != null, variables[i].typeParameter == typeParameters[i]
@@ -353,30 +352,65 @@ class BoundSet {
}
copy.inThrows.addAll(this.inThrows);
copy.captures.putAll(this.captures);
+ System.arraycopy(this.incorporatedBounds, 0, copy.incorporatedBounds = new TypeBound[this.incorporatedBounds.length], 0, this.incorporatedBounds.length);
+ System.arraycopy(this.unincorporatedBounds, 0, copy.unincorporatedBounds = new TypeBound[this.unincorporatedBounds.length], 0, this.unincorporatedBounds.length);
+ copy.unincorporatedBoundsCount = this.unincorporatedBoundsCount;
return copy;
}
public void addBound(TypeBound bound, LookupEnvironment environment) {
+
+ if (bound.relation == ReductionResult.SUBTYPE && bound.right.id == TypeIds.T_JavaLangObject)
+ return;
+ if (bound.left == bound.right) //$IDENTITY-COMPARISON$
+ return;
+ for (int recent = 0; recent < 4; recent++) {
+ if (bound.equals(this.mostRecentBounds[recent])) {
+ if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ TypeBound existing = this.mostRecentBounds[recent];
+ long boundNullBits = bound.right.tagBits & TagBits.AnnotationNullMASK;
+ long existingNullBits = existing.right.tagBits & TagBits.AnnotationNullMASK;
+ if (boundNullBits != existingNullBits) {
+ if (existingNullBits == 0)
+ existing.right = bound.right;
+ else if (boundNullBits != 0) // combine bits from both sources, even if this creates a contradiction
+ existing.right = environment.createAnnotatedType(existing.right, environment.nullAnnotationsFromTagBits(boundNullBits));
+ }
+ }
+ return;
+ }
+ }
+
+ this.mostRecentBounds[3] = this.mostRecentBounds[2];
+ this.mostRecentBounds[2] = this.mostRecentBounds[1];
+ this.mostRecentBounds[1] = this.mostRecentBounds[0];
+ this.mostRecentBounds[0] = bound;
+
InferenceVariable variable = bound.left.prototype();
ThreeSets three = this.boundsPerVariable.get(variable);
if (three == null)
this.boundsPerVariable.put(variable, (three = new ThreeSets()));
- three.addBound(bound);
- // check if this makes the inference variable instantiated:
- TypeBinding typeBinding = bound.right;
- if (bound.relation == ReductionResult.SAME && typeBinding.isProperType(true))
- three.setInstantiation(typeBinding, variable, environment);
- if (bound.right instanceof InferenceVariable) {
- // for a dependency between two IVs make a note about the inverse bound.
- // this should be needed to determine IV dependencies independent of direction.
- // TODO: so far no test could be identified which actually needs it ...
- InferenceVariable rightIV = (InferenceVariable) bound.right.prototype();
- three = this.boundsPerVariable.get(rightIV);
- if (three == null)
- this.boundsPerVariable.put(rightIV, (three = new ThreeSets()));
- if (three.inverseBounds == null)
- three.inverseBounds = new HashMap<InferenceVariable,TypeBound>();
- three.inverseBounds.put(rightIV, bound);
+ if (three.addBound(bound)) {
+ int unincorporatedBoundsLength = this.unincorporatedBounds.length;
+ if (this.unincorporatedBoundsCount >= unincorporatedBoundsLength)
+ System.arraycopy(this.unincorporatedBounds, 0, this.unincorporatedBounds = new TypeBound[unincorporatedBoundsLength * 2], 0, unincorporatedBoundsLength);
+ this.unincorporatedBounds[this.unincorporatedBoundsCount ++] = bound;
+ // check if this makes the inference variable instantiated:
+ TypeBinding typeBinding = bound.right;
+ if (bound.relation == ReductionResult.SAME && typeBinding.isProperType(true))
+ three.setInstantiation(typeBinding, variable, environment);
+ if (bound.right instanceof InferenceVariable) {
+ // for a dependency between two IVs make a note about the inverse bound.
+ // this should be needed to determine IV dependencies independent of direction.
+ // TODO: so far no test could be identified which actually needs it ...
+ InferenceVariable rightIV = (InferenceVariable) bound.right.prototype();
+ three = this.boundsPerVariable.get(rightIV);
+ if (three == null)
+ this.boundsPerVariable.put(rightIV, (three = new ThreeSets()));
+ if (three.inverseBounds == null)
+ three.inverseBounds = new HashMap<InferenceVariable,TypeBound>();
+ three.inverseBounds.put(rightIV, bound);
+ }
}
}
@@ -416,7 +450,39 @@ class BoundSet {
}
return num;
}
+
+ // Driver for the real workhorse - Implements generational incorporation a la generational garbage collector.
+ boolean incorporate(InferenceContext18 context) throws InferenceFailureException {
+
+ if (this.unincorporatedBoundsCount == 0 && this.captures.size() == 0)
+ return true;
+
+ do {
+ TypeBound [] freshBounds;
+ System.arraycopy(this.unincorporatedBounds, 0, freshBounds = new TypeBound[this.unincorporatedBoundsCount], 0, this.unincorporatedBoundsCount);
+ this.unincorporatedBoundsCount = 0;
+
+ // Pairwise bidirectional compare all bounds from previous generation with the fresh set.
+ if (!incorporate(context, this.incorporatedBounds, freshBounds))
+ return false;
+ // Pairwise bidirectional compare all fresh bounds.
+ if (!incorporate(context, freshBounds, freshBounds))
+ return false;
+ this.captures.clear();
+
+ // Merge the bounds into one incorporated generation.
+ final int incorporatedLength = this.incorporatedBounds.length;
+ final int unincorporatedLength = freshBounds.length;
+ TypeBound [] aggregate = new TypeBound[incorporatedLength + unincorporatedLength];
+ System.arraycopy(this.incorporatedBounds, 0, aggregate, 0, incorporatedLength);
+ System.arraycopy(freshBounds, 0, aggregate, incorporatedLength, unincorporatedLength);
+ this.incorporatedBounds = aggregate;
+
+ } while (this.unincorporatedBoundsCount > 0);
+
+ return true;
+ }
/**
* <b>JLS 18.3:</b> Try to infer new constraints from pairs of existing type bounds.
* Each new constraint is first reduced and checked for TRUE or FALSE, which will
@@ -425,24 +491,23 @@ class BoundSet {
* @return false if any constraint resolved to false, true otherwise
* @throws InferenceFailureException a compile error has been detected during inference
*/
- boolean incorporate(InferenceContext18 context) throws InferenceFailureException {
- boolean hasUpdate;
- do {
- hasUpdate = false;
- // using a flattened copy also allows us to insert more bounds during the process
- // without disturbing the current round of incorporation:
- TypeBound[] bounds = flatten();
- int boundsCount = bounds.length;
- if (boundsCount < 2)
- return true;
- // check each pair:
- for (int i = 0; i < boundsCount; i++) {
- TypeBound boundI = bounds[i];
- for (int j = i+1; j < boundsCount; j++) {
- TypeBound boundJ = bounds[j];
- if (this.incorporatedBounds.contains(boundI) && this.incorporatedBounds.contains(boundJ))
- continue;
+ boolean incorporate(InferenceContext18 context, TypeBound [] first, TypeBound [] next) throws InferenceFailureException {
+ boolean analyzeNull = context.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled;
+ ConstraintTypeFormula [] mostRecentFormulas = new ConstraintTypeFormula[4]; // poor man's cache to toss out duplicates, in pathological cases there are a good quarter million of them.
+ // check each pair, in each way.
+ for (int i = 0, iLength = first.length; i < iLength; i++) {
+ TypeBound boundI = first[i];
+ for (int j = 0, jLength = next.length; j < jLength; j++) {
+ TypeBound boundJ = next[j];
+ int iteration = 1;
+ do {
ConstraintTypeFormula newConstraint = null;
+ boolean deriveTypeArgumentConstraints = false;
+ if (iteration == 2) {
+ TypeBound boundX = boundI;
+ boundI = boundJ;
+ boundJ = boundX;
+ }
switch (boundI.relation) {
case ReductionResult.SAME:
switch (boundJ.relation) {
@@ -465,6 +530,7 @@ class BoundSet {
break;
case ReductionResult.SUBTYPE:
newConstraint = combineEqualSupers(boundI, boundJ);
+ deriveTypeArgumentConstraints = TypeBinding.equalsEquals(boundI.left, boundJ.left);
break;
}
break;
@@ -482,123 +548,139 @@ class BoundSet {
}
}
if (newConstraint != null) {
+ if (newConstraint.left == newConstraint.right) { //$IDENTITY-COMPARISON$
+ newConstraint = null;
+ } else if (newConstraint.equalsEquals(mostRecentFormulas[0]) || newConstraint.equalsEquals(mostRecentFormulas[1]) ||
+ newConstraint.equalsEquals(mostRecentFormulas[2]) || newConstraint.equalsEquals(mostRecentFormulas[3])) {
+ newConstraint = null;
+ }
+ }
+ if (newConstraint != null) {
+ // bubble formulas around the cache.
+ mostRecentFormulas[3] = mostRecentFormulas[2];
+ mostRecentFormulas[2] = mostRecentFormulas[1];
+ mostRecentFormulas[1] = mostRecentFormulas[0];
+ mostRecentFormulas[0] = newConstraint;
+
if (!reduceOneConstraint(context, newConstraint))
return false;
- // TODO here and below: better checking if constraint really added to the boundset (optimization)?
- hasUpdate = true;
- // not per JLS: if the new constraint relates types where at least one has a null annotations,
- // record all null tagBits as hints for the final inference solution.
- long nullHints = (newConstraint.left.tagBits | newConstraint.right.tagBits) & TagBits.AnnotationNullMASK;
- boundI.nullHints |= nullHints;
- boundJ.nullHints |= nullHints;
+
+ if (analyzeNull) {
+ // not per JLS: if the new constraint relates types where at least one has a null annotations,
+ // record all null tagBits as hints for the final inference solution.
+ long nullHints = (newConstraint.left.tagBits | newConstraint.right.tagBits) & TagBits.AnnotationNullMASK;
+ boundI.nullHints |= nullHints;
+ boundJ.nullHints |= nullHints;
+ }
}
- ConstraintFormula[] typeArgumentConstraints = deriveTypeArgumentConstraints(boundI, boundJ);
+ ConstraintFormula[] typeArgumentConstraints = deriveTypeArgumentConstraints ? deriveTypeArgumentConstraints(boundI, boundJ) : null;
if (typeArgumentConstraints != null) {
- for (int k = 0; k < typeArgumentConstraints.length; k++) {
+ for (int k = 0, length = typeArgumentConstraints.length; k < length; k++) {
if (!reduceOneConstraint(context, typeArgumentConstraints[k]))
return false;
- hasUpdate = true;
}
}
- }
- this.incorporatedBounds.add(boundI);
- }
- /* TODO: are we sure this will always terminate? Cf. e.g. (Discussion in 18.3):
- *
- * "The assertion that incorporation reaches a fixed point oversimplifies the matter slightly. ..."
- */
- Iterator<Entry<ParameterizedTypeBinding, ParameterizedTypeBinding>> captIter = this.captures.entrySet().iterator();
- while (captIter.hasNext()) {
- hasUpdate = true;
- Entry<ParameterizedTypeBinding, ParameterizedTypeBinding> capt = captIter.next();
- ParameterizedTypeBinding gAlpha = capt.getKey();
- ParameterizedTypeBinding gA = capt.getValue();
- ReferenceBinding g = (ReferenceBinding) gA.original();
- final TypeVariableBinding[] parameters = g.typeVariables();
- // construct theta = [P1:=alpha1,...]
- final InferenceVariable[] alphas = new InferenceVariable[gAlpha.arguments.length];
- System.arraycopy(gAlpha.arguments, 0, alphas, 0, alphas.length);
- InferenceSubstitution theta = new InferenceSubstitution(context.environment, alphas) {
- @Override
- protected TypeBinding getP(int i) {
- return parameters[i];
+ if (iteration == 2) {
+ TypeBound boundX = boundI;
+ boundI = boundJ;
+ boundJ = boundX;
}
- };
- for (int i = 0; i < parameters.length; i++) {
- // A set of bounds on α1, ..., αn, constructed from the declared bounds of P1, ..., Pn as described in 18.1.3, is immediately implied.
- TypeVariableBinding pi = parameters[i];
- InferenceVariable alpha = (InferenceVariable) gAlpha.arguments[i];
- addBounds(pi.getTypeBounds(alpha, theta), context.environment);
-
- TypeBinding ai = gA.arguments[i];
- if (ai instanceof WildcardBinding) {
- WildcardBinding wildcardBinding = (WildcardBinding)ai;
- TypeBinding t = wildcardBinding.bound;
- ThreeSets three = this.boundsPerVariable.get(alpha.prototype());
- if (three != null) {
- Iterator<TypeBound> it;
- if (three.sameBounds != null) {
- // α = R implies false
- it = three.sameBounds.iterator();
- while (it.hasNext()) {
- TypeBound bound = it.next();
- if (!(bound.right instanceof InferenceVariable))
- return false;
- }
+ } while (first != next && ++iteration <= 2);
+ }
+ }
+ /* TODO: are we sure this will always terminate? Cf. e.g. (Discussion in 18.3):
+ *
+ * "The assertion that incorporation reaches a fixed point oversimplifies the matter slightly. ..."
+ */
+ Iterator<Entry<ParameterizedTypeBinding, ParameterizedTypeBinding>> captIter = this.captures.entrySet().iterator();
+ while (captIter.hasNext()) {
+ Entry<ParameterizedTypeBinding, ParameterizedTypeBinding> capt = captIter.next();
+ ParameterizedTypeBinding gAlpha = capt.getKey();
+ ParameterizedTypeBinding gA = capt.getValue();
+ ReferenceBinding g = (ReferenceBinding) gA.original();
+ final TypeVariableBinding[] parameters = g.typeVariables();
+ // construct theta = [P1:=alpha1,...]
+ final InferenceVariable[] alphas = new InferenceVariable[gAlpha.arguments.length];
+ System.arraycopy(gAlpha.arguments, 0, alphas, 0, alphas.length);
+ InferenceSubstitution theta = new InferenceSubstitution(context.environment, alphas) {
+ @Override
+ protected TypeBinding getP(int i) {
+ return parameters[i];
+ }
+ };
+ for (int i = 0, length = parameters.length; i < length; i++) {
+ // A set of bounds on α1, ..., αn, constructed from the declared bounds of P1, ..., Pn as described in 18.1.3, is immediately implied.
+ TypeVariableBinding pi = parameters[i];
+ InferenceVariable alpha = (InferenceVariable) gAlpha.arguments[i];
+ addBounds(pi.getTypeBounds(alpha, theta), context.environment);
+
+ TypeBinding ai = gA.arguments[i];
+ if (ai instanceof WildcardBinding) {
+ WildcardBinding wildcardBinding = (WildcardBinding)ai;
+ TypeBinding t = wildcardBinding.bound;
+ ThreeSets three = this.boundsPerVariable.get(alpha.prototype());
+ if (three != null) {
+ Iterator<TypeBound> it;
+ if (three.sameBounds != null) {
+ // α = R implies false
+ it = three.sameBounds.iterator();
+ while (it.hasNext()) {
+ TypeBound bound = it.next();
+ if (!(bound.right instanceof InferenceVariable))
+ return false;
}
- if (three.subBounds != null && pi.firstBound != null) {
- // If Bi is Object, α <: R implies ⟨T <: R⟩ (extends wildcard)
- // α <: R implies ⟨θ Bi <: R⟩ (else)
- it = three.subBounds.iterator();
- while (it.hasNext()) {
- TypeBound bound = it.next();
- if (!(bound.right instanceof InferenceVariable)) {
- TypeBinding r = bound.right;
- TypeBinding bi1 = pi.firstBound;
- ReferenceBinding[] otherBounds = pi.superInterfaces;
- TypeBinding bi;
- if (otherBounds == Binding.NO_SUPERINTERFACES) {
- bi = bi1;
- } else {
- int n = otherBounds.length+1;
- ReferenceBinding[] allBounds = new ReferenceBinding[n];
- allBounds[0] = (ReferenceBinding) bi1; // TODO is this safe?
- System.arraycopy(otherBounds, 0, allBounds, 1, n-1);
- bi = new IntersectionCastTypeBinding(allBounds, context.environment);
- }
- addTypeBoundsFromWildcardBound(context, theta, wildcardBinding.boundKind, t, r, bi);
-// if (otherBounds != null) {
-// for (int j = 0; j < otherBounds.length; j++) {
-// TypeBinding tj = otherBounds[j];
-// if (TypeBinding.notEquals(tj, t))
-// addTypeBoundsFromWildcardBound(context, wildcardBinding, tj, r, bij);
-// }
-// }
+ }
+ if (three.subBounds != null && pi.firstBound != null) {
+ // If Bi is Object, α <: R implies ⟨T <: R⟩ (extends wildcard)
+ // α <: R implies ⟨θ Bi <: R⟩ (else)
+ it = three.subBounds.iterator();
+ while (it.hasNext()) {
+ TypeBound bound = it.next();
+ if (!(bound.right instanceof InferenceVariable)) {
+ TypeBinding r = bound.right;
+ TypeBinding bi1 = pi.firstBound;
+ ReferenceBinding[] otherBounds = pi.superInterfaces;
+ TypeBinding bi;
+ if (otherBounds == Binding.NO_SUPERINTERFACES) {
+ bi = bi1;
+ } else {
+ int n = otherBounds.length+1;
+ ReferenceBinding[] allBounds = new ReferenceBinding[n];
+ allBounds[0] = (ReferenceBinding) bi1; // TODO is this safe?
+ System.arraycopy(otherBounds, 0, allBounds, 1, n-1);
+ bi = new IntersectionCastTypeBinding(allBounds, context.environment);
}
+ addTypeBoundsFromWildcardBound(context, theta, wildcardBinding.boundKind, t, r, bi);
+ // if (otherBounds != null) {
+ // for (int j = 0; j < otherBounds.length; j++) {
+ // TypeBinding tj = otherBounds[j];
+ // if (TypeBinding.notEquals(tj, t))
+ // addTypeBoundsFromWildcardBound(context, wildcardBinding, tj, r, bij);
+ // }
+ // }
}
}
- if (three.superBounds != null) {
- // R <: α implies ⟨R <: T⟩ (super wildcard)
- // R <: α implies false (else)
- it = three.superBounds.iterator();
- while (it.hasNext()) {
- TypeBound bound = it.next();
- if (!(bound.right instanceof InferenceVariable)) {
- if (wildcardBinding.boundKind == Wildcard.SUPER)
- reduceOneConstraint(context, ConstraintTypeFormula.create(bound.right, t, ReductionResult.SUBTYPE));
- else
- return false;
- }
+ }
+ if (three.superBounds != null) {
+ // R <: α implies ⟨R <: T⟩ (super wildcard)
+ // R <: α implies false (else)
+ it = three.superBounds.iterator();
+ while (it.hasNext()) {
+ TypeBound bound = it.next();
+ if (!(bound.right instanceof InferenceVariable)) {
+ if (wildcardBinding.boundKind == Wildcard.SUPER)
+ reduceOneConstraint(context, ConstraintTypeFormula.create(bound.right, t, ReductionResult.SUBTYPE));
+ else
+ return false;
}
}
}
- } else {
- addBound(new TypeBound(alpha, ai, ReductionResult.SAME), context.environment);
}
+ } else {
+ addBound(new TypeBound(alpha, ai, ReductionResult.SAME), context.environment);
}
}
- this.captures.clear();
- } while (hasUpdate);
+ }
return true;
}
@@ -711,10 +793,7 @@ class BoundSet {
* there exists a supertype (4.10) of S of the form G<S1, ..., Sn> and a supertype of T of the form G<T1, ..., Tn>,
* then for all i, 1 ≤ i ≤ n, if Si and Ti are types (not wildcards), the constraint ⟨Si = Ti⟩ is implied.
*/
- if (boundS.relation != ReductionResult.SUBTYPE || boundT.relation != ReductionResult.SUBTYPE)
- return null;
- if (TypeBinding.notEquals(boundS.left, boundT.left))
- return null;
+ // callers must ensure both relations are <: and both lefts are equal
TypeBinding[] supers = superTypesWithCommonGenericType(boundS.right, boundT.right);
if (supers != null)
return typeArgumentEqualityConstraints(supers[0], supers[1], boundS.isSoft || boundT.isSoft);
@@ -898,6 +977,8 @@ class BoundSet {
if (targetType.isBaseType()) return false;
if (InferenceContext18.parameterizedWithWildcard(targetType) != null) return false;
ThreeSets ts = this.boundsPerVariable.get(alpha.prototype());
+ if (ts == null)
+ return false;
if (ts.sameBounds != null) {
Iterator<TypeBound> bounds = ts.sameBounds.iterator();
while (bounds.hasNext()) {
@@ -939,6 +1020,8 @@ class BoundSet {
if (!targetType.isParameterizedType()) return false;
TypeBinding g = targetType.original();
ThreeSets ts = this.boundsPerVariable.get(alpha.prototype());
+ if (ts == null)
+ return false;
Iterator<TypeBound> boundIterator;
if (ts.sameBounds != null) {
boundIterator = ts.sameBounds.iterator();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
index 43331f717..f35a24ca5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
@@ -32,6 +32,7 @@ public class CaptureBinding extends TypeVariableBinding {
/* information to compute unique binding key */
public ReferenceBinding sourceType;
public int position;
+ public ASTNode cud; // to facilitate recaptures.
public CaptureBinding(WildcardBinding wildcard, ReferenceBinding sourceType, int position, int captureID) {
super(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX, null, 0, wildcard.environment);
@@ -57,6 +58,11 @@ public class CaptureBinding extends TypeVariableBinding {
}
}
+ public CaptureBinding(WildcardBinding wildcard, ReferenceBinding sourceType, int position, ASTNode cud, int captureID) {
+ this(wildcard, sourceType, position, captureID);
+ this.cud = cud;
+ }
+
// for subclass CaptureBinding18
protected CaptureBinding(ReferenceBinding sourceType, char[] sourceName, int position, int captureID, LookupEnvironment environment) {
super(sourceName, null, 0, environment);
@@ -358,6 +364,20 @@ public class CaptureBinding extends TypeVariableBinding {
}
@Override
+//{ObjectTeams: cross the OT package, make protected:
+ protected
+// SH}
+ TypeBinding substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType) {
+ TypeBinding newWildcard = this.wildcard.substituteInferenceVariable(var, substituteType);
+ if (newWildcard != this.wildcard) { //$IDENTITY-COMPARISON$
+ CaptureBinding newCapture = new CaptureBinding((WildcardBinding) newWildcard, this.sourceType, this.position, this.cud, this.captureID);
+ newCapture.id = this.id; // there is no need really to add this to the derived types, just equate the type system ids and the capture ids.
+ return newCapture;
+ }
+ return this;
+ }
+
+ @Override
public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNullAnnotations) {
super.setTypeAnnotations(annotations, evalNullAnnotations);
if (annotations != Binding.NO_ANNOTATIONS && this.wildcard != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java
index a79226ff5..9fe42d1aa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java
@@ -20,12 +20,24 @@ public class CaptureBinding18 extends CaptureBinding {
TypeBinding[] upperBounds;
private char[] originalName;
+ private CaptureBinding18 prototype;
public CaptureBinding18(ReferenceBinding contextType, char[] sourceName, char[] originalName, int position, int captureID, LookupEnvironment environment) {
super(contextType, sourceName, position, captureID, environment);
this.originalName = originalName;
+ this.prototype = this;
}
+ private CaptureBinding18(CaptureBinding18 prototype) {
+ this(prototype.sourceType, CharOperation.append(prototype.sourceName, '\''), prototype.originalName, prototype.position, prototype.captureID, prototype.environment);
+ this.upperBounds = prototype.upperBounds;
+ this.firstBound = prototype.firstBound;
+ this.lowerBound = prototype.lowerBound;
+ this.superInterfaces = prototype.superInterfaces;
+ this.superclass = prototype.superclass;
+ this.prototype = prototype.prototype;
+ }
+
public boolean setUpperBounds(TypeBinding[] upperBounds, ReferenceBinding javaLangObject) {
this.upperBounds = upperBounds;
if (upperBounds.length > 0)
@@ -59,7 +71,7 @@ public class CaptureBinding18 extends CaptureBinding {
}
public TypeBinding clone(TypeBinding enclosingType) {
- return new CaptureBinding18(this.sourceType, CharOperation.append(this.sourceName, '\''), this.originalName, this.position, this.captureID, this.environment);
+ return new CaptureBinding18(this);
}
public MethodBinding[] getMethods(char[] selector) {
@@ -258,7 +270,7 @@ public class CaptureBinding18 extends CaptureBinding {
if (this.genericTypeSignature == null) {
char[] boundSignature;
try {
- if (this.recursionLevel++ > 0 || this.firstBound == null) {
+ if (this.prototype.recursionLevel++ > 0 || this.firstBound == null) {
boundSignature = TypeConstants.WILDCARD_STAR;
} else if (this.upperBounds != null) {
boundSignature = CharOperation.concat(TypeConstants.WILDCARD_PLUS, this.firstBound.genericTypeSignature());
@@ -269,7 +281,7 @@ public class CaptureBinding18 extends CaptureBinding {
}
this.genericTypeSignature = CharOperation.concat(TypeConstants.WILDCARD_CAPTURE, boundSignature);
} finally {
- this.recursionLevel--;
+ this.prototype.recursionLevel--;
}
}
return this.genericTypeSignature;
@@ -277,9 +289,9 @@ public class CaptureBinding18 extends CaptureBinding {
public char[] readableName() {
if (this.lowerBound == null && this.firstBound != null) {
- if (this.recursionLevel < 2) {
+ if (this.prototype.recursionLevel < 2) {
try {
- this.recursionLevel ++;
+ this.prototype.recursionLevel ++;
if (this.upperBounds != null && this.upperBounds.length > 1) {
StringBuffer sb = new StringBuffer();
sb.append(this.upperBounds[0].readableName());
@@ -292,7 +304,7 @@ public class CaptureBinding18 extends CaptureBinding {
}
return this.firstBound.readableName();
} finally {
- this.recursionLevel--;
+ this.prototype.recursionLevel--;
}
} else {
return this.originalName;
@@ -303,9 +315,9 @@ public class CaptureBinding18 extends CaptureBinding {
public char[] shortReadableName() {
if (this.lowerBound == null && this.firstBound != null) {
- if (this.recursionLevel < 2) {
+ if (this.prototype.recursionLevel < 2) {
try {
- this.recursionLevel++;
+ this.prototype.recursionLevel++;
if (this.upperBounds != null && this.upperBounds.length > 1) {
StringBuffer sb = new StringBuffer();
sb.append(this.upperBounds[0].shortReadableName());
@@ -318,7 +330,7 @@ public class CaptureBinding18 extends CaptureBinding {
}
return this.firstBound.shortReadableName();
} finally {
- this.recursionLevel--;
+ this.prototype.recursionLevel--;
}
} else {
return this.originalName;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index 288079483..7e2c401ed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -1120,6 +1120,8 @@ public String toString() {
return "--- CompilationUnit Scope : " + new String(this.referenceContext.getFileName()); //$NON-NLS-1$
}
private ReferenceBinding typeToRecord(TypeBinding type) {
+ if (type == null)
+ return null;
while (type.isArrayType())
type = ((ArrayBinding) type).leafComponentType();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
index 0d06e452c..ca3cc0fe7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
@@ -371,6 +371,11 @@ class ConstraintTypeFormula extends ConstraintFormula {
return true;
}
+ public boolean equalsEquals (ConstraintTypeFormula that) {
+ return (that != null && this.relation == that.relation && this.isSoft == that.isSoft &&
+ TypeBinding.equalsEquals(this.left, that.left) && TypeBinding.equalsEquals(this.right, that.right));
+ }
+
public boolean applySubstitution(BoundSet solutionSet, InferenceVariable[] variables) {
super.applySubstitution(solutionSet, variables);
for (int i=0; i<variables.length; i++) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
index 356768613..0527f279d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InvocationSite.java
@@ -20,6 +20,7 @@ public interface InvocationSite {
TypeBinding[] genericTypeArguments();
boolean isSuperAccess();
+ boolean isQualifiedSuper();
boolean isTypeAccess();
// in case the receiver type does not match the actual receiver type
// e.g. pkg.Type.C (receiver type of C is type of source context,
@@ -53,5 +54,7 @@ public interface InvocationSite {
public boolean receiverIsImplicitThis() { return false; }
public InferenceContext18 freshInferenceContext(Scope scope) { return null; }
public ExpressionContext getExpressionContext() { return ExpressionContext.VANILLA_CONTEXT; }
+ @Override
+ public boolean isQualifiedSuper() { return false; }
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
index 1e0414e6b..a729c6e89 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
@@ -103,6 +103,11 @@ public void addInnerEmulationDependent(BlockScope dependentScope, boolean wasEnc
// System.out.println("Adding dependency: "+ new String(scope.enclosingType().readableName()) + " --> " + new String(this.readableName()));
}
+@Override
+public MethodBinding enclosingMethod() {
+ return this.enclosingMethod;
+}
+
/*
* Returns the anonymous original super type (in some error cases, superclass may get substituted with Object)
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 12aa5e4c6..9a6cef111 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -40,6 +40,7 @@ import java.util.Set;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFilePool;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
@@ -1251,6 +1252,10 @@ public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, Ty
return this.typeSystem.getWildcard(genericType, rank, bound, otherBounds, boundKind);
}
+public CaptureBinding createCapturedWildcard(WildcardBinding wildcard, ReferenceBinding contextType, int position, ASTNode cud, int id) {
+ return this.typeSystem.getCapturedWildcard(wildcard, contextType, position, cud, id);
+}
+
public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, AnnotationBinding [] annotations) {
return this.typeSystem.getWildcard(genericType, rank, bound, otherBounds, boundKind, annotations);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index 24bb80b9f..35727fec4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -515,6 +515,14 @@ public FieldBinding findField(TypeBinding receiverType, char[] fieldName, Invoca
return null;
if (!field.isValidBinding())
return field; // answer the error field
+
+ if (receiverType.isInterface() && invocationSite.isQualifiedSuper())
+ return new ProblemFieldBinding(
+ field, // closest match
+ field.declaringClass,
+ fieldName,
+ ProblemReasons.NoProperEnclosingInstance);
+
if (field.isStatic())
return field; // static fields are always accessible
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index b12541b14..587f5866a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -4,7 +4,7 @@
* 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
* Fraunhofer FIRST - extended API and implementation
@@ -37,6 +37,7 @@
* Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
* Bug 438179 - [1.8][null] 'Contradictory null annotations' error on type variable with explicit null-annotation.
* Bug 441693 - [1.8][null] Bogus warning for type argument annotated with @NonNull
+ * Bug 446434 - [1.8][null] Enable interned captures also when analysing null type annotations
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -161,11 +162,12 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
public boolean canBeInstantiated() {
return ((this.tagBits & TagBits.HasDirectWildcard) == 0) && super.canBeInstantiated(); // cannot instantiate param type with wildcard arguments
}
+
/**
* Perform capture conversion for a parameterized type with wildcard arguments
* @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#capture(Scope,int)
*/
- public TypeBinding capture(Scope scope, int position) {
+ public ParameterizedTypeBinding capture(Scope scope, int position) {
if ((this.tagBits & TagBits.HasDirectWildcard) == 0)
return this;
@@ -177,14 +179,21 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
ReferenceBinding contextType = scope.enclosingSourceType();
if (contextType != null) contextType = contextType.outermostEnclosingType(); // maybe null when used programmatically by DOM
+ CompilationUnitScope compilationUnitScope = scope.compilationUnitScope();
+ ASTNode cud = compilationUnitScope.referenceContext;
+ long sourceLevel = this.environment.globalOptions.sourceLevel;
+ final boolean needUniqueCapture = sourceLevel >= ClassFileConstants.JDK1_8;
+
for (int i = 0; i < length; i++) {
TypeBinding argument = originalArguments[i];
if (argument.kind() == Binding.WILDCARD_TYPE) { // no capture for intersection types
final WildcardBinding wildcard = (WildcardBinding) argument;
if (wildcard.boundKind == Wildcard.SUPER && wildcard.bound.id == TypeIds.T_JavaLangObject)
capturedArguments[i] = wildcard.bound;
- else
- capturedArguments[i] = new CaptureBinding(wildcard, contextType, position, scope.compilationUnitScope().nextCaptureID());
+ else if (needUniqueCapture)
+ capturedArguments[i] = this.environment.createCapturedWildcard(wildcard, contextType, position, cud, compilationUnitScope.nextCaptureID());
+ else
+ capturedArguments[i] = new CaptureBinding(wildcard, contextType, position, compilationUnitScope.nextCaptureID());
} else {
capturedArguments[i] = argument;
}
@@ -198,7 +207,7 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
}
return capturedParameterizedType;
}
-
+
/**
* Perform capture deconversion for a parameterized type with captured wildcard arguments
* @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#uncapture(Scope)
@@ -1560,12 +1569,15 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
return this.fields;
}
public MethodBinding getSingleAbstractMethod(final Scope scope, boolean replaceWildcards) {
- int index = replaceWildcards ? 0 : 1;
+ return getSingleAbstractMethod(scope, replaceWildcards, -1 /* do not capture */);
+ }
+ public MethodBinding getSingleAbstractMethod(final Scope scope, boolean replaceWildcards, int capturePosition) {
+ int index = replaceWildcards ? capturePosition < 0 ? 0 : 1 : 2; // capturePosition >= 0 IFF replaceWildcard == true
if (this.singleAbstractMethod != null) {
if (this.singleAbstractMethod[index] != null)
- return this.singleAbstractMethod[index];
+ return this.singleAbstractMethod[index];
} else {
- this.singleAbstractMethod = new MethodBinding[2];
+ this.singleAbstractMethod = new MethodBinding[3];
}
if (!isValidBinding())
return null;
@@ -1583,6 +1595,13 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
} else if (types == null) {
types = NO_TYPES;
}
+ if (capturePosition >= 0) {
+ // caller is going to require the sam's parameters to be treated as argument expressions, post substitution capture will lose identity, where substitution results in fan out
+ // capture first and then substitute.
+ for (int i = 0, length = types.length; i < length; i++) {
+ types[i] = types[i].capture(scope, 0);
+ }
+ }
declaringType = scope.environment().createParameterizedType(genericType, types, genericType.enclosingType());
TypeVariableBinding [] typeParameters = genericType.typeVariables();
for (int i = 0, length = typeParameters.length; i < length; i++) {
@@ -1669,21 +1688,6 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
}
return types;
}
- static boolean typeParametersMentioned(TypeBinding upperBound) {
- class MentionListener extends TypeBindingVisitor {
- private boolean typeParametersMentioned = false;
- public boolean visit(TypeVariableBinding typeVariable) {
- this.typeParametersMentioned = true;
- return false;
- }
- public boolean typeParametersMentioned() {
- return this.typeParametersMentioned;
- }
- }
- MentionListener mentionListener = new MentionListener();
- TypeBindingVisitor.visit(mentionListener, upperBound);
- return mentionListener.typeParametersMentioned();
- }
//{ObjectTeams: recursive role wrapping:
@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java
index ff02719c8..5c75b9018 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java
@@ -36,6 +36,21 @@ public class PolyTypeBinding extends TypeBinding {
public boolean isCompatibleWith(TypeBinding left, Scope scope) {
return this.vanillaCompatibilty ? this.expression.isCompatibleWith(left, scope) : this.expression.isBoxingCompatibleWith(left, scope);
}
+
+ @Override
+ public boolean isPertinentToApplicability(TypeBinding targetType, MethodBinding method) {
+ return this.expression.isPertinentToApplicability(targetType, method);
+ }
+
+ @Override
+ public boolean isPertinentToApplicability(TypeVariableBinding typeVariable, MethodBinding method) {
+ return this.expression.isPertinentToApplicability(typeVariable, method);
+ }
+
+ @Override
+ public boolean isPolyType() {
+ return true;
+ }
public char[] qualifiedSourceName() {
return readableName();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
index defc4f45f..5aa2ab058 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
@@ -83,6 +83,10 @@ private MethodBinding getMethodClone(MethodBinding closestMatch) {
}
// SH}
+@Override
+public MethodBinding shallowOriginal() {
+ return this.closestMatch == null ? this : this.closestMatch.shallowOriginal();
+}
/* API
* Answer the problem id associated with the receiver.
* NoError if the receiver is a valid binding.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
index fdd9787e7..8f043ec19 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReasons.java
@@ -45,11 +45,14 @@ public interface ProblemReasons {
final int ParameterizedMethodExpectedTypeProblem = 23;
final int ApplicableMethodOverriddenByInapplicable = 24;
final int ContradictoryNullAnnotations = 25;
+ final int NoSuchMethodOnArray = 26;
+ final int InferredAppliableMethodInapplicable = 27; // 18.5.1 ignores arguments not pertinent to applicability. When these are taken into consideration method could fail applicability
+ final int NoProperEnclosingInstance = 28;
//{ObjectTeams;
- final int NoTeamContext = 26;
- final int AnchorNotFinal = 27;
- final int AnchorNotATeam = 28;
- final int AnchorNotFound = 29;
- final int ProblemAlreadyReported = 30;
+ final int NoTeamContext = 29;
+ final int AnchorNotFinal = 30;
+ final int AnchorNotATeam = 31;
+ final int AnchorNotFound = 32;
+ final int ProblemAlreadyReported = 33;
// SH}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index a5c5a2527..9265bce07 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -2201,7 +2201,7 @@ public abstract class Scope {
}
methodBinding = findMethod(object, selector, argumentTypes, invocationSite, false);
if (methodBinding == null)
- return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NotFound);
+ return new ProblemMethodBinding(selector, argumentTypes, ProblemReasons.NoSuchMethodOnArray);
return methodBinding;
}
@@ -4920,6 +4920,12 @@ public abstract class Scope {
continue nextJ;
}
}
+ if (levelj == VARARGS_COMPATIBLE && levelk == VARARGS_COMPATIBLE) {
+ TypeBinding s = InferenceContext18.getParameter(mbjParameters, argumentTypes.length, true);
+ TypeBinding t = InferenceContext18.getParameter(mbkParameters, argumentTypes.length, true);
+ if (TypeBinding.notEquals(s, t) && t.isSubtypeOf(s))
+ continue nextJ;
+ }
}
}
moreSpecific[count++] = visible[j];
@@ -4952,6 +4958,7 @@ public abstract class Scope {
public boolean receiverIsImplicitThis() { return invocationSite.receiverIsImplicitThis();}
public InferenceContext18 freshInferenceContext(Scope scope) { return null; /* no inference when ignoring genericTypeArgs */ }
public ExpressionContext getExpressionContext() { return ExpressionContext.VANILLA_CONTEXT; }
+ public boolean isQualifiedSuper() { return invocationSite.isQualifiedSuper(); }
};
int count = 0;
for (int level = 0, max = VARARGS_COMPATIBLE; level <= max; level++) {
@@ -5689,6 +5696,7 @@ public abstract class Scope {
methodScope = methodScope.enclosingMethodScope();
}
}
+ MethodBinding enclosingMethod = enclosingType != null ? enclosingType.enclosingMethod() : null;
while (methodScope != null) {
while (methodScope != null && methodScope.referenceContext instanceof LambdaExpression) {
LambdaExpression lambda = (LambdaExpression) methodScope.referenceContext;
@@ -5699,6 +5707,8 @@ public abstract class Scope {
if (methodScope != null) {
if (methodScope.referenceContext instanceof MethodDeclaration) {
MethodDeclaration methodDeclaration = (MethodDeclaration) methodScope.referenceContext;
+ if (methodDeclaration.binding == enclosingMethod)
+ break;
methodDeclaration.bits &= ~ASTNode.CanBeStatic;
}
ClassScope enclosingClassScope = methodScope.enclosingClassScope();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index dcb3a7a3b..3b3e5d1f3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -29,6 +29,7 @@
* Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
* Bug 440759 - [1.8][null] @NonNullByDefault should never affect wildcards and uses of a type variable
* Bug 441693 - [1.8][null] Bogus warning for type argument annotated with @NonNull
+ * Bug 446434 - [1.8][null] Enable interned captures also when analysing null type annotations
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
*******************************************************************************/
@@ -111,9 +112,9 @@ public TypeBinding() {
super();
}
-public TypeBinding(TypeBinding prototype) { // faithfully copy all instance state - clone operation should specialize/override suitably.
+public TypeBinding(TypeBinding prototype) { // faithfully copy most instance state - clone operation should specialize/override suitably.
this.id = prototype.id;
- this.tagBits = prototype.tagBits;
+ this.tagBits = prototype.tagBits & ~TagBits.AnnotationNullMASK;
}
/**
@@ -266,6 +267,13 @@ public int depth() {
return 0;
}
+/* Answer the receiver's enclosing method ... null if the receiver is not a local type.
+ */
+public MethodBinding enclosingMethod() {
+ return null;
+}
+
+
/* Answer the receiver's enclosing type... null if the receiver is a top level type or is an array or a non reference type.
*/
public ReferenceBinding enclosingType() {
@@ -553,6 +561,14 @@ public final boolean isBaseType() {
return (this.tagBits & TagBits.IsBaseType) != 0;
}
+public boolean isPertinentToApplicability(TypeVariableBinding typeVariable, MethodBinding method) {
+ return true;
+}
+
+public boolean isPertinentToApplicability(TypeBinding argument, MethodBinding method) {
+ return true;
+}
+
/* Answer true if the receiver is a base type other than void or null
*/
public final boolean isPrimitiveType() {
@@ -782,6 +798,11 @@ public boolean isParameterizedWithOwnVariables() {
public boolean isProperType(boolean admitCapture18) {
return true;
}
+
+public boolean isPolyType() {
+ return false;
+}
+
/**
* Substitute all occurrences of 'var' within the current type by 'substituteType.
* @param var an inference variable (JLS8 18.1.1)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java
index ad520b73f..dbb99b90c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java
@@ -59,13 +59,15 @@ public class TypeBound extends ReductionResult {
boolean isBound() {
return this.right.isProperType(true);
}
+
public int hashCode() {
return this.left.hashCode() + this.right.hashCode() + this.relation;
}
+
public boolean equals(Object obj) {
if (obj instanceof TypeBound) {
TypeBound other = (TypeBound) obj;
- return TypeBinding.equalsEquals(this.left, other.left) && TypeBinding.equalsEquals(this.right, other.right) && this.relation == other.relation;
+ return (this.relation == other.relation) && TypeBinding.equalsEquals(this.left, other.left) && TypeBinding.equalsEquals(this.right, other.right);
}
return false;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
index 20e76b10b..52982af2e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
@@ -15,6 +15,7 @@ package org.eclipse.jdt.internal.compiler.lookup;
import java.util.HashMap;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
@@ -214,7 +215,9 @@ public class TypeSystem {
// Given a type, answer its unannotated aka naked prototype. This is also a convenient way to "register" a type with TypeSystem and have it id stamped.
public final TypeBinding getUnannotatedType(TypeBinding type) {
+ UnresolvedReferenceBinding urb = null;
if (type.isUnresolvedType() && CharOperation.indexOf('$', type.sourceName()) > 0) {
+ urb = (UnresolvedReferenceBinding) type;
boolean mayTolerateMissingType = this.environment.mayTolerateMissingType;
this.environment.mayTolerateMissingType = true;
try {
@@ -230,6 +233,8 @@ public class TypeSystem {
if (this.typeid == typesLength)
System.arraycopy(this.types, 0, this.types = new TypeBinding[typesLength * 2][], 0, typesLength);
this.types[type.id = this.typeid++] = new TypeBinding[4];
+ if (urb != null)
+ urb.id = type.id;
} else {
TypeBinding nakedType = this.types[type.id] == null ? null : this.types[type.id][0];
if (type.hasTypeAnnotations() && nakedType == null)
@@ -433,6 +438,37 @@ public class TypeSystem {
return (WildcardBinding) (this.types[wildcard.id = this.typeid++][0] = wildcard);
}
+ // No need for an override in ATS, since we are dealing with recaptures here.
+ public final CaptureBinding getCapturedWildcard(WildcardBinding wildcard, ReferenceBinding contextType, int position, ASTNode cud, int id) {
+
+ WildcardBinding unannotatedWildcard = (WildcardBinding) getUnannotatedType(wildcard);
+ TypeBinding[] derivedTypes = this.types[unannotatedWildcard.id]; // by construction, cachedInfo != null now.
+ int i, length = derivedTypes.length;
+ for (i = 0; i < length; i++) {
+ TypeBinding derivedType = derivedTypes[i];
+ if (derivedType == null)
+ break;
+ if (!derivedType.isCapture())
+ continue;
+ CaptureBinding prior = (CaptureBinding) derivedType;
+ if (prior.sourceType != contextType || prior.position != position || prior.cud != cud) //$IDENTITY-COMPARISON$
+ continue;
+ return prior;
+ }
+
+ if (i == length) {
+ System.arraycopy(derivedTypes, 0, derivedTypes = new TypeBinding[length * 2], 0, length);
+ this.types[unannotatedWildcard.id] = derivedTypes;
+ }
+ TypeBinding capture = derivedTypes[i] = new CaptureBinding(wildcard, contextType, position, cud, id);
+
+ int typesLength = this.types.length;
+ if (this.typeid == typesLength)
+ System.arraycopy(this.types, 0, this.types = new TypeBinding[typesLength * 2][], 0, typesLength);
+ this.types[this.typeid] = new TypeBinding[1];
+ return (CaptureBinding) (this.types[capture.id = this.typeid++][0] = capture);
+ }
+
public WildcardBinding getWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, AnnotationBinding[] annotations) {
return getWildcard(genericType, rank, bound, otherBounds, boundKind);
}
@@ -520,6 +556,7 @@ public class TypeSystem {
this.annotationTypes = new SimpleLookupTable(16);
this.typeid = TypeIds.T_LastWellKnownTypeId;
this.types = new TypeBinding[TypeIds.T_LastWellKnownTypeId * 2][];
+ this.parameterizedTypes = new HashedParameterizedTypes();
}
public void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
index 61fff8180..7e6056f26 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -611,6 +611,10 @@ public class TypeVariableBinding extends ReferenceBinding {
this.inRecursiveFunction = false;
}
+ public boolean isPertinentToApplicability(TypeBinding argument, MethodBinding method) {
+ return argument.isPertinentToApplicability(this, method);
+ }
+
public boolean isProperType(boolean admitCapture18) {
// handle recursive calls:
if (this.inRecursiveFunction) // be optimistic, since this node is not an inference variable
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
index e0b777134..121f54d81 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
@@ -44,8 +44,8 @@ public UnresolvedReferenceBinding(UnresolvedReferenceBinding prototype) {
}
public TypeBinding clone(TypeBinding outerType) {
- if (this.resolvedType != null || this.depth() > 0)
- throw new IllegalStateException();
+ if (this.resolvedType != null)
+ return this.resolvedType.clone(outerType);
UnresolvedReferenceBinding copy = new UnresolvedReferenceBinding(this);
this.addWrapper(copy, null);
return copy;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/CommitRollbackParser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/CommitRollbackParser.java
index ec3036dca..ac09e687d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/CommitRollbackParser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/CommitRollbackParser.java
@@ -56,28 +56,28 @@ public abstract class CommitRollbackParser implements TerminalTokens, ParserBasi
// We get here on real syntax error or syntax error triggered by fake EOF at completion site, never due to triggered recovery.
protected int fallBackToSpringForward(Statement unused) {
int nextToken;
- boolean atCompletionSite = false;
int automatonState = automatonState();
// If triggered fake EOF at completion site, see if the real next token would have passed muster.
if (this.currentToken == TokenNameEOF) {
if (this.scanner.eofPosition < this.scanner.source.length) {
- atCompletionSite = true;
+ shouldStackAssistNode();
this.scanner.eofPosition = this.scanner.source.length;
nextToken = getNextToken();
if (automatonWillShift(nextToken, automatonState)) {
this.currentToken = nextToken;
return RESUME;
}
+ this.scanner.ungetToken(nextToken); // spit out what has been bitten more than we can chew.
} else {
- nextToken = TokenNameEOF;
+ return HALT; // don't know how to proceed.
}
} else {
nextToken = this.currentToken;
+ this.scanner.ungetToken(nextToken);
+ if (nextToken == TokenNameRBRACE)
+ ignoreNextClosingBrace(); // having ungotten it, recoveryTokenCheck will see this again.
}
- if (nextToken == TokenNameEOF)
- return HALT; // don't know how to proceed.
- this.scanner.ungetToken(nextToken); // spit out what has been bitten more than we can chew.
// OK, next token is no good to resume "in place", attempt some local repair. FIXME: need to make sure we don't get stuck keep reducing empty statements !!
for (int i = 0, length = RECOVERY_TOKENS.length; i < length; i++) {
if (automatonWillShift(RECOVERY_TOKENS[i], automatonState)) {
@@ -90,15 +90,22 @@ public abstract class CommitRollbackParser implements TerminalTokens, ParserBasi
return RESTART;
this.copyState(this.snapShot);
- if (atCompletionSite) {
+ if (assistNodeNeedsStacking()) {
this.currentToken = TokenNameSEMICOLON;
- shouldStackAssistNode();
return RESUME;
}
this.currentToken = this.scanner.fastForward(unused);
return RESUME;
}
+ protected void ignoreNextClosingBrace() {
+ return;
+ }
+
+ protected boolean assistNodeNeedsStacking() {
+ return false;
+ }
+
public abstract int automatonState();
public abstract boolean automatonWillShift(int nextToken, int lastAction);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 754b03287..5cd0ab697 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -901,6 +901,7 @@ public class Parser extends CommitRollbackParser implements ConflictedParser, Op
protected int identifierPtr;
protected char[][] identifierStack;
protected boolean ignoreNextOpeningBrace;
+ protected boolean ignoreNextClosingBrace;
//positions , dimensions , .... (int stacks)
protected int intPtr;
@@ -1518,7 +1519,9 @@ protected void consumeAllocationHeader() {
this.lastCheckPoint = anonymousType.bodyStart = this.scanner.currentPosition;
this.currentElement = this.currentElement.add(anonymousType, 0);
this.lastIgnoredToken = -1;
- if (!isIndirectlyInsideLambdaExpression())
+ if (isIndirectlyInsideLambdaExpression())
+ this.ignoreNextOpeningBrace = true;
+ else
this.currentToken = 0; // opening brace already taken into account
return;
}
@@ -4293,7 +4296,9 @@ protected void consumeEnterAnonymousClassBody(boolean qualified) {
this.lastCheckPoint = anonymousType.bodyStart;
this.currentElement = this.currentElement.add(anonymousType, 0);
if (!(this.currentElement instanceof RecoveredAnnotation)) {
- if (!isIndirectlyInsideLambdaExpression())
+ if (isIndirectlyInsideLambdaExpression())
+ this.ignoreNextOpeningBrace = true;
+ else
this.currentToken = 0; // opening brace already taken into account
} else {
this.ignoreNextOpeningBrace = true;
@@ -4495,8 +4500,10 @@ protected void consumeEnumConstantHeader() {
this.currentElement = this.currentElement.add(anonymousType, 0);
this.lastCheckPoint = anonymousType.bodyStart;
this.lastIgnoredToken = -1;
- if (!isIndirectlyInsideLambdaExpression())
- this.currentToken = 0; // opening brace already taken into account
+ if (isIndirectlyInsideLambdaExpression())
+ this.ignoreNextOpeningBrace = true;
+ else
+ this.currentToken = 0; // opening brace already taken into account
} else {
if(this.currentToken == TokenNameSEMICOLON) {
RecoveredType currentType = currentRecoveryType();
@@ -10144,9 +10151,11 @@ protected void consumeLambdaExpression() {
Statement body = (Statement) this.astStack[this.astPtr--];
if (body instanceof Block) {
if (this.options.ignoreMethodBodies) {
+ Statement oldBody = body;
body = new Block(0);
+ body.sourceStart = oldBody.sourceStart;
+ body.sourceEnd = oldBody.sourceEnd;
}
- ((Block) body).lambdaBody = true; // for consistency's sakes.
}
LambdaExpression lexp = (LambdaExpression) this.astStack[this.astPtr--];
@@ -13244,6 +13253,11 @@ public boolean hasLeadingTagComment(char[] commentPrefixTag, int rangeEnd) {
}
return false;
}
+
+@Override
+protected void ignoreNextClosingBrace() {
+ this.ignoreNextClosingBrace = true;
+}
protected void ignoreExpressionAssignment() {
// Assignment ::= InvalidArrayInitializerAssignement
// encoded operator would be: this.intStack[this.intPtr]
@@ -15239,6 +15253,10 @@ public void recoveryTokenCheck() {
break;
case TokenNameRBRACE :
+ if (this.ignoreNextClosingBrace) {
+ this.ignoreNextClosingBrace = false;
+ break;
+ }
this.rBraceStart = this.scanner.startPosition - 1;
this.rBraceEnd = this.scanner.currentPosition - 1;
this.endPosition = flushCommentsDefinedPriorTo(this.rBraceEnd);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java
index cd7a56f3a..31ac07708 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredBlock.java
@@ -19,7 +19,6 @@ import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
@@ -156,9 +155,6 @@ public RecoveredElement add(Statement stmt, int bracketBalanceValue) {
*/
public RecoveredElement add(Statement stmt, int bracketBalanceValue, boolean delegatedByParent) {
- if (stmt instanceof LambdaExpression) // lambdas are recovered up to the containing statement anyways.
- return this;
-
resetPendingModifiers();
/* do not consider a nested block starting passed the block end (if set)
@@ -293,11 +289,6 @@ public Block updatedBlock(int depth, Set knownTypes){
// if block was not marked to be preserved or empty, then ignore it
if (!this.preserveContent || this.statementCount == 0) return null;
- /* If this block stands for the lambda body, trash the contents. Lambda expressions are recovered as part of the enclosing statement.
- We still have left in a block here to make sure that contained elements can be trapped and tossed out.
- */
- if (this.blockDeclaration.lambdaBody) return null;
-
Statement[] updatedStatements = new Statement[this.statementCount];
int updatedCount = 0;
@@ -338,9 +329,19 @@ public Block updatedBlock(int depth, Set knownTypes){
int lastEnd = this.blockDeclaration.sourceStart;
// only collect the non-null updated statements
+ next:
for (int i = 0; i < this.statementCount; i++){
Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes);
- if (updatedStatement != null){
+ if (updatedStatement != null) {
+ for (int j = 0; j < i; j++) {
+ if (updatedStatements[j] instanceof LocalDeclaration) {
+ LocalDeclaration local = (LocalDeclaration) updatedStatements[j];
+ if (local.initialization != null) {
+ if (updatedStatement.sourceStart >= local.initialization.sourceStart && updatedStatement.sourceEnd <= local.initialization.sourceEnd)
+ continue next;
+ }
+ }
+ }
updatedStatements[updatedCount++] = updatedStatement;
if (updatedStatement instanceof LocalDeclaration) {
@@ -427,42 +428,6 @@ public void updateParseTree(){
updatedBlock(0, new HashSet());
}
/*
- * Rebuild a flattened block from the nested structure which is in scope
- */
-public Statement updateStatement(int depth, Set knownTypes){
-
- // if block was closed or empty, then ignore it
- if (this.blockDeclaration.sourceEnd != 0 || this.statementCount == 0) return null;
-
- /* If this block stands for the lambda body, trash the contents. Lambda expressions are recovered as part of the enclosing statement.
- We still have left in a block here to make sure that contained elements can be trapped and tossed out.
- */
- if (this.blockDeclaration.lambdaBody) return null;
-
- Statement[] updatedStatements = new Statement[this.statementCount];
- int updatedCount = 0;
-
- // only collect the non-null updated statements
- for (int i = 0; i < this.statementCount; i++){
- Statement updatedStatement = this.statements[i].updatedStatement(depth, knownTypes);
- if (updatedStatement != null){
- updatedStatements[updatedCount++] = updatedStatement;
- }
- }
- if (updatedCount == 0) return null; // not interesting block
-
- // resize statement collection if necessary
- if (updatedCount != this.statementCount){
- this.blockDeclaration.statements = new Statement[updatedCount];
- System.arraycopy(updatedStatements, 0, this.blockDeclaration.statements, 0, updatedCount);
- } else {
- this.blockDeclaration.statements = updatedStatements;
- }
-
- return this.blockDeclaration;
-}
-
-/*
* Record a field declaration
*/
public RecoveredElement add(FieldDeclaration fieldDeclaration, int bracketBalanceValue) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
index 4e5d8a4c3..4dcc21ee1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredMethod.java
@@ -77,6 +77,9 @@ public RecoveredMethod(AbstractMethodDeclaration methodDeclaration, RecoveredEle
* Record a nested block declaration
*/
public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue) {
+ return this.add(nestedBlockDeclaration, bracketBalanceValue, false);
+}
+public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValue, boolean isArgument) {
/* default behavior is to delegate recording to parent if any,
do not consider elements passed the known end (if set)
it must be belonging to an enclosing element
@@ -92,7 +95,7 @@ public RecoveredElement add(Block nestedBlockDeclaration, int bracketBalanceValu
}
}
/* consider that if the opening brace was not found, it is there */
- if (!this.foundOpeningBrace){
+ if (!this.foundOpeningBrace && !isArgument){
this.foundOpeningBrace = true;
this.bracketBalance++;
}
@@ -177,7 +180,7 @@ public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanc
if (this.methodBody == null){
Block block = new Block(0);
block.sourceStart = this.methodDeclaration.bodyStart;
- RecoveredElement currentBlock = this.add(block, 1);
+ RecoveredElement currentBlock = this.add(block, 1, localDeclaration.isArgument());
if (this.bracketBalance > 0){
for (int i = 0; i < this.bracketBalance - 1; i++){
currentBlock = currentBlock.add(new Block(0), 1);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
index ac217d9a1..8155e9c4c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredType.java
@@ -645,12 +645,20 @@ public TypeDeclaration updatedTypeDeclaration(int depth, Set knownTypes){
this.methods[this.methodCount - 1].methodDeclaration.declarationSourceEnd = bodyEndValue;
this.methods[this.methodCount - 1].methodDeclaration.bodyEnd = bodyEndValue;
}
+ int totalMethods = existingCount;
+ next:
for (int i = 0; i < this.methodCount; i++){
+ for (int j = 0; j < existingCount; j++) {
+ if (methodDeclarations[j] == this.methods[i].methodDeclaration)
+ continue next;
+ }
AbstractMethodDeclaration updatedMethod = this.methods[i].updatedMethodDeclaration(depth, knownTypes);
if (updatedMethod.isConstructor()) hasRecoveredConstructor = true;
if (updatedMethod.isAbstract()) hasAbstractMethods = true;
- methodDeclarations[existingCount + i] = updatedMethod;
+ methodDeclarations[totalMethods ++] = updatedMethod;
}
+ if (totalMethods != methodDeclarations.length)
+ System.arraycopy(methodDeclarations, 0, methodDeclarations = new AbstractMethodDeclaration[totalMethods], 0, totalMethods);
this.typeDeclaration.methods = methodDeclarations;
if(methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd > lastEnd) {
lastEnd = methodDeclarations[methodDeclarations.length - 1].declarationSourceEnd;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index fc2c92b1f..f5479ee5c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -2450,13 +2450,13 @@ public void fieldHiding(FieldDeclaration fieldDecl, Binding hiddenVariable) {
nodeSourceEnd(hiddenField, fieldDecl));
}
}
-public void fieldsOrThisBeforeConstructorInvocation(ThisReference reference) {
+public void fieldsOrThisBeforeConstructorInvocation(ASTNode reference) {
this.handle(
IProblem.ThisSuperDuringConstructorInvocation,
NoArgument,
NoArgument,
reference.sourceStart,
- reference.sourceEnd);
+ reference instanceof LambdaExpression ? ((LambdaExpression) reference).diagnosticsSourceEnd() : reference.sourceEnd);
}
public void finallyMustCompleteNormally(Block finallyBlock) {
this.handle(
@@ -4170,6 +4170,9 @@ public void invalidField(FieldReference fieldRef, TypeBinding searchedType) {
case ProblemReasons.Ambiguous :
id = IProblem.AmbiguousField;
break;
+ case ProblemReasons.NoProperEnclosingInstance:
+ noSuchEnclosingInstance(fieldRef.actualReceiverType, fieldRef.receiver, false);
+ return;
case ProblemReasons.NonStaticReferenceInStaticContext :
id = IProblem.NonStaticFieldFromStaticInvocation;
break;
@@ -4447,6 +4450,8 @@ public void invalidMethod(MessageSend messageSend, MethodBinding method) {
int id = IProblem.UndefinedMethod; //default...
MethodBinding shownMethod = method;
switch (method.problemId()) {
+ case ProblemReasons.NoSuchMethodOnArray :
+ return; // secondary error.
case ProblemReasons.NotFound :
if ((method.declaringClass.tagBits & TagBits.HasMissingType) != 0) {
this.handle(
@@ -14578,4 +14583,10 @@ public void uninternedIdentityComparison(EqualExpression expr, TypeBinding lhs,
expr.sourceStart,
expr.sourceEnd);
}
+public void invalidTypeArguments(TypeReference[] typeReference) {
+ this.handle(IProblem.InvalidTypeArguments,
+ NoArgument, NoArgument,
+ typeReference[0].sourceStart,
+ typeReference[typeReference.length - 1].sourceEnd);
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 77a3f6400..c410b78fd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -573,6 +573,7 @@
579 = Unused type arguments for the non generic method {0}({1}) of type {2}; it should not be parameterized with arguments <{3}>
583 = Duplicate methods named {0} with the parameters ({1}) and ({2}) are inherited from the types {3} and {4}
584 = Name clash: The method {0}({1}) of type {2} has the same erasure as {0}({3}) of type {4} but does not hide it
+586 = Type arguments are not allowed here
### FOREACH
580 = Type mismatch: cannot convert from element type {0} to {1}

Back to the top