diff options
author | Stephan Herrmann | 2014-10-03 20:03:34 +0000 |
---|---|---|
committer | Stephan Herrmann | 2014-10-03 20:29:29 +0000 |
commit | 881bc14111c034e0b90ec9961e6a7ddeaec8517b (patch) | |
tree | dcc271e61766b9814da11408e96bff26b9279c04 | |
parent | eb086338780463648761a8e416dab97ac4270c0b (diff) | |
download | org.eclipse.objectteams-881bc14111c034e0b90ec9961e6a7ddeaec8517b.tar.gz org.eclipse.objectteams-881bc14111c034e0b90ec9961e6a7ddeaec8517b.tar.xz org.eclipse.objectteams-881bc14111c034e0b90ec9961e6a7ddeaec8517b.zip |
update jdt.core to I20140806-2000 (4.5 M1)
73 files changed, 884 insertions, 275 deletions
diff --git a/org.eclipse.jdt.core/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jdt.core/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..796937ca4 --- /dev/null +++ b/org.eclipse.jdt.core/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +encoding//scripts/ecj.1=ISO-8859-1 +encoding/<project>=UTF-8 diff --git a/org.eclipse.jdt.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/META-INF/MANIFEST.MF index 64f17a935..565079a50 100644 --- a/org.eclipse.jdt.core/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.jdt.core; singleton:=true -Bundle-Version: 3.10.0.v_OTDT_r240_qualifier +Bundle-Version: 3.11.0.v_OTDT_r240_qualifier Bundle-Activator: org.eclipse.jdt.core.JavaCore Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java index 4a80caf84..65adef4d6 100644 --- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java +++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java @@ -583,6 +583,17 @@ public final class SelectionEngine extends Engine implements ISearchRequestor { case '"': case '\'': break lineLoop; + case '-': + if (source[nextCharacterPosition] == '>') { + nextCharacterPosition--; // nextCharacterPosition = currentPosition + break lineLoop; + } + break; + case ':': + if (source[nextCharacterPosition] == ':') { + nextCharacterPosition--; // nextCharacterPosition = currentPosition + break lineLoop; + } } currentPosition--; } @@ -620,6 +631,15 @@ public final class SelectionEngine extends Engine implements ISearchRequestor { break isolateLastName; } break; + case TerminalTokens.TokenNameARROW: + case TerminalTokens.TokenNameCOLON_COLON: + if (scanner.startPosition <= selectionStart && selectionStart <= scanner.currentPosition) { + lastIdentifierStart = scanner.startPosition; + lastIdentifierEnd = scanner.currentPosition - 1; + lastIdentifier = scanner.getCurrentTokenSource(); + break isolateLastName; + } + break; } } while (token != TerminalTokens.TokenNameEOF); } else { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java index 7519a318f..a0c391ac5 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.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 @@ -194,6 +194,8 @@ * NonNullDefaultDetailIsNotEvaluated * NullNotCompatibleToFreeTypeVariable * NullityMismatchAgainstFreeTypeVariable + * ImplicitObjectBoundNoNullDefault + * IllegalParameterNullityRedefinition * Jesper S Moller - added the following constants * TargetTypeNotAFunctionalInterface * OuterLocalMustBeEffectivelyFinal @@ -406,6 +408,8 @@ void setSourceStart(int sourceStart); int NonStaticContextForEnumMemberType = Internal + 32; /** @since 3.3 */ int TypeHidingType = TypeRelated + 33; + /** @since 3.11 */ + int NotAnnotationType = TypeRelated + 34; // variables int UndefinedName = Internal + FieldRelated + 50; @@ -459,6 +463,10 @@ void setSourceStart(int sourceStart); int UnresolvedVariable = FieldRelated + 83; /** @since 3.10 */ int NonStaticOrAlienTypeReceiver = MethodRelated + 84; + + /** @since 3.11 */ + int ExceptionParameterIsNeverUsed = Internal + 85; + // variable hiding /** @since 3.0 */ int LocalVariableHidingLocalVariable = Internal + 90; @@ -1789,6 +1797,11 @@ void setSourceStart(int sourceStart); int NullNotCompatibleToFreeTypeVariable = 969; /** @since 3.10 */ int NullityMismatchAgainstFreeTypeVariable = 970; + /** @since 3.11 */ + int ImplicitObjectBoundNoNullDefault = 971; + /** @since 3.11 */ + int IllegalParameterNullityRedefinition = MethodRelated + 972; + // Java 8 work /** @since 3.10 */ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java index 999aee20c..f1a0c185d 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java @@ -22,6 +22,8 @@ * Bug 415399 - [1.8][compiler] Type annotations on constructor results dropped by the code generator * Bug 415470 - [1.8][compiler] Type annotations on class declaration go vanishing * Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas + * Stephan Herrmann - Contribution for + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables *******************************************************************************/ package org.eclipse.jdt.internal.compiler; @@ -2994,7 +2996,8 @@ public class ClassFile implements TypeConstants, TypeIds { // functional expressions, we know the size ahead of time - this less general // than the full invokedynamic scope, but fine for Java 8 - int exSize = 10 * numberOfBootstraps + 8; + final int contentsEntries = 10; + int exSize = contentsEntries * numberOfBootstraps + 8; if (exSize + localContentsOffset >= this.contents.length) { resizeContents(exSize); } @@ -3028,8 +3031,8 @@ public class ClassFile implements TypeConstants, TypeIds { // 2 for bridge count then 2 per bridge method type. extraSpace += (2 + 2 * bridges.length); } - if (extraSpace + localContentsOffset >= this.contents.length) { - resizeContents(extraSpace); + if (extraSpace + contentsEntries + localContentsOffset >= this.contents.length) { + resizeContents(extraSpace + contentsEntries); } if (indexForAltMetaFactory == 0) { @@ -5296,11 +5299,11 @@ public class ClassFile implements TypeConstants, TypeIds { this.innerClassesBindings = new HashSet(INNER_CLASSES_SIZE); } ReferenceBinding innerClass = (ReferenceBinding) binding; - this.innerClassesBindings.add(innerClass.erasure().unannotated()); // should not emit yet another inner class for Outer.@Inner Inner. + this.innerClassesBindings.add(innerClass.erasure().unannotated(false)); // should not emit yet another inner class for Outer.@Inner Inner. ReferenceBinding enclosingType = innerClass.enclosingType(); while (enclosingType != null && enclosingType.isNestedType()) { - this.innerClassesBindings.add(enclosingType.erasure().unannotated()); + this.innerClassesBindings.add(enclosingType.erasure().unannotated(false)); enclosingType = enclosingType.enclosingType(); } } 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 9cf550f9f..4a414f6b3 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 @@ -31,6 +31,7 @@ * Bug 428352 - [1.8][compiler] Resolution errors don't always surface * Bug 427163 - [1.8][null] bogus error "Contradictory null specification" on varags * Bug 432348 - [1.8] Internal compiler error (NPE) after upgrade to 1.8 + * Bug 440143 - [1.8][null] one more case of contradictory null annotations regarding type variables * Jesper S Moller - Contributions for * bug 382721 - [1.8][compiler] Effectively final variables needs special treatment * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable @@ -1035,7 +1036,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { } } if (copySE8AnnotationsToType) - copySE8AnnotationsToType(scope, recipient, sourceAnnotations, true); + copySE8AnnotationsToType(scope, recipient, sourceAnnotations, false); return annotations; } @@ -1061,7 +1062,7 @@ public abstract class ASTNode implements TypeConstants, TypeIds { } // When SE8 annotations feature in SE7 locations, they get attributed to the declared entity. Copy/move these to the type of the declared entity (field, local, argument etc.) - public static void copySE8AnnotationsToType(BlockScope scope, Binding recipient, Annotation[] annotations, boolean isLegalLocation) { + public static void copySE8AnnotationsToType(BlockScope scope, Binding recipient, Annotation[] annotations, boolean annotatingEnumerator) { if (annotations == null || annotations.length == 0 || recipient == null) return; @@ -1085,15 +1086,20 @@ public abstract class ASTNode implements TypeConstants, TypeIds { int se8count = 0; long se8nullBits = 0; Annotation se8NullAnnotation = null; - int firstSE8 = -1, lastSE8 = 0; + int firstSE8 = -1; for (int i = 0, length = annotations.length; i < length; i++) { AnnotationBinding annotation = annotations[i].getCompilerAnnotation(); if (annotation == null) continue; final ReferenceBinding annotationType = annotation.getAnnotationType(); long metaTagBits = annotationType.getAnnotationTagBits(); if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) { + if (annotatingEnumerator) { + if ((metaTagBits & recipientTargetMask) == 0) { + scope.problemReporter().misplacedTypeAnnotations(annotations[i], annotations[i]); + } + continue; + } if (firstSE8 == -1) firstSE8 = i; - lastSE8 = i; if (se8Annotations == null) { se8Annotations = new AnnotationBinding[] { annotation }; se8count = 1; @@ -1111,10 +1117,6 @@ public abstract class ASTNode implements TypeConstants, TypeIds { } } if (se8Annotations != null) { - if (!isLegalLocation) { - scope.problemReporter().misplacedTypeAnnotations(annotations[firstSE8], annotations[lastSE8]); - return; - } switch (recipient.kind()) { case Binding.LOCAL: LocalVariableBinding local = (LocalVariableBinding) recipient; @@ -1175,7 +1177,12 @@ public abstract class ASTNode implements TypeConstants, TypeIds { // for arrays: @T X[] SE7 associates @T to the type, but in SE8 it affects the leaf component type long prevNullBits = existingType.leafComponentType().tagBits & TagBits.AnnotationNullMASK; if (se8nullBits != 0 && prevNullBits != se8nullBits && ((prevNullBits | se8nullBits) == TagBits.AnnotationNullMASK)) { - scope.problemReporter().contradictoryNullAnnotations(se8NullAnnotation); + if (existingType instanceof TypeVariableBinding) { + // let type-use annotations override annotations on the type parameter declaration + existingType = existingType.unannotated(true); + } else { + scope.problemReporter().contradictoryNullAnnotations(se8NullAnnotation); + } } TypeBinding oldLeafType = (unionRef == null) ? existingType.leafComponentType() : unionRef.resolvedType; AnnotationBinding [][] goodies = new AnnotationBinding[typeRef.getAnnotatableLevels()][]; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java index 1a758068a..d3ff2fb0b 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java @@ -23,6 +23,7 @@ * Bug 403216 - [1.8][null] TypeReference#captureTypeAnnotations treats type annotations as type argument annotations * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -882,7 +883,7 @@ public abstract class AbstractMethodDeclaration this.scope.problemReporter().illegalTypeForExplicitThis(this.receiver, enclosingReceiver); } - if (resolvedReceiverType.hasNullTypeAnnotations()) { + if (this.receiver.type.hasNullTypeAnnotation()) { this.scope.problemReporter().nullAnnotationUnsupportedLocation(this.receiver.type); } } 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 d1f1ac40c..fa9b241f7 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 @@ -338,7 +338,7 @@ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, Fl // perform some emulation work in case there is some and we are inside a local type only if (allocatedTypeErasure.isNestedType() - && currentScope.enclosingSourceType().isLocalType()) { + && (currentScope.enclosingSourceType().isLocalType() || currentScope.isLambdaScope())) { if (allocatedTypeErasure.isLocalType()) { ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, false); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java index 74c88b26d..9e4982478 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java @@ -808,7 +808,7 @@ public abstract class Annotation extends Expression { this.resolvedType = typeBinding; // ensure type refers to an annotation type if (!typeBinding.isAnnotationType() && typeBinding.isValidBinding()) { - scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type, null); + scope.problemReporter().notAnnotationType(typeBinding, this.type); return null; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java index 83b3cd0b6..74feee392 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java @@ -14,6 +14,8 @@ * bug 365519 - editorial cleanup after bug 186342 and bug 365387 * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" + * Bug 438012 - [1.8][null] Bogus Warning: The nullness annotation is redundant with a default that applies to this location * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 409246 - [1.8][compiler] Type annotations on catch parameters not handled properly *******************************************************************************/ @@ -175,6 +177,12 @@ public class Argument extends LocalDeclaration { return (this.bits & IsTypeElided) != 0; } + public boolean hasNullTypeAnnotation() { + // parser associates SE8 annotations to the declaration + return TypeReference.containsNullAnnotation(this.annotations) || + (this.type != null && this.type.hasNullTypeAnnotation()); // just in case + } + public StringBuffer print(int indent, StringBuffer output) { printIndent(indent, output); @@ -245,7 +253,9 @@ public class Argument extends LocalDeclaration { } resolveAnnotations(scope, this.annotations, this.binding, true); Annotation.isTypeUseCompatible(this.type, scope, this.annotations); - if (this.type.resolvedType != null && this.type.resolvedType.hasNullTypeAnnotations()) { + if (scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled && + (this.type.hasNullTypeAnnotation() || TypeReference.containsNullAnnotation(this.annotations))) + { scope.problemReporter().nullAnnotationUnsupportedLocation(this.type); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java index 05136255a..5ea23f716 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java @@ -9,6 +9,7 @@ * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -179,4 +180,20 @@ public class ArrayTypeReference extends SingleTypeReference { TypeBinding internalResolveType = super.internalResolveType(scope, location); return internalResolveType; } + + @Override + public boolean hasNullTypeAnnotation() { + if (super.hasNullTypeAnnotation()) + return true; + if (this.resolvedType != null && !this.resolvedType.hasNullTypeAnnotations()) + return false; // shortcut + if (this.annotationsOnDimensions != null) { + for (int i = 0; i < this.annotationsOnDimensions.length; i++) { + Annotation[] innerAnnotations = this.annotationsOnDimensions[i]; + if (containsNullAnnotation(innerAnnotations)) + return true; + } + } + return false; + } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java index f0656acd7..426f48d82 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java @@ -264,14 +264,14 @@ public abstract class FunctionalExpression extends Expression { VisibilityInspector inspector = new VisibilityInspector(this, scope, shouldChatter); boolean status = true; - if (!inspector.visible(sam.returnType)) status = false; if (!inspector.visible(sam.parameters)) status = false; if (!inspector.visible(sam.thrownExceptions)) status = false; - + if (!inspector.visible(sam.declaringClass)) + status = false; return status; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java index 05983ea35..f50126f30 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java @@ -16,6 +16,7 @@ * Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" * Andy Clement - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ @@ -152,7 +153,7 @@ public TypeBinding resolveType(BlockScope scope) { this.constant = Constant.NotAConstant; TypeBinding expressionType = this.expression.resolveType(scope); TypeBinding checkedType = this.type.resolveType(scope, true /* check bounds*/); - if (expressionType != null && checkedType != null && checkedType.hasNullTypeAnnotations()) { + if (expressionType != null && checkedType != null && this.type.hasNullTypeAnnotation()) { // don't complain if the entire operation is redundant anyway if (!expressionType.isCompatibleWith(checkedType) || NullAnnotationMatching.analyse(checkedType, expressionType, -1).isAnyMismatch()) scope.problemReporter().nullAnnotationUnsupportedLocation(this.type); 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 9fcca2c0a..b90060ddc 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 @@ -31,6 +31,7 @@ * Bug 428980 - [1.8][null] simple expression as lambda body doesn't leverage null annotation on argument * Bug 429430 - [1.8] Lambdas and method reference infer wrong exception type with generics (RuntimeException instead of IOException) * Bug 432110 - [1.8][compiler] nested lambda type incorrectly inferred vs javac + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas *******************************************************************************/ @@ -52,6 +53,7 @@ import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.CodeStream; +import org.eclipse.jdt.internal.compiler.env.ICompilationUnit; import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; @@ -114,6 +116,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC private ReferenceBinding classType; public int ordinal; 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); @@ -333,9 +336,6 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC } } - 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; @@ -371,7 +371,6 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC if ((exception.tagBits & TagBits.HasMissingType) != 0) { this.binding.tagBits |= TagBits.HasMissingType; } - this.binding.modifiers |= (exception.modifiers & ExtraCompilerModifiers.AccGenericSignature); } TypeBinding returnType = this.binding.returnType; @@ -379,9 +378,6 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC if ((returnType.tagBits & TagBits.HasMissingType) != 0) { this.binding.tagBits |= TagBits.HasMissingType; } - 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) { @@ -514,7 +510,7 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC int length = this.binding.parameters.length; for (int i=0; i<length; i++) { if (!this.scope.validateNullAnnotation(this.binding.returnType.tagBits, this.arguments[i].type, this.arguments[i].annotations)) - this.binding.returnType = this.binding.returnType.unannotated(); + this.binding.returnType = this.binding.returnType.unannotated(true); } } } @@ -943,8 +939,9 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC LambdaExpression copy() { final Parser parser = new Parser(this.enclosingScope.problemReporter(), false); - final char[] source = this.compilationResult.getCompilationUnit().getContents(); - LambdaExpression copy = (LambdaExpression) parser.parseLambdaExpression(source, this.sourceStart, this.sourceEnd - this.sourceStart + 1, + final ICompilationUnit compilationUnit = this.compilationResult.getCompilationUnit(); + char[] source = compilationUnit != null ? compilationUnit.getContents() : this.text; + LambdaExpression copy = (LambdaExpression) parser.parseLambdaExpression(source, compilationUnit != null ? this.sourceStart : 0, this.sourceEnd - this.sourceStart + 1, this.enclosingScope.referenceCompilationUnit(), false /* record line separators */); if (copy != null) { // ==> syntax errors == null diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java index 66a6d52ea..f2dbaaf3f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java @@ -19,6 +19,7 @@ * Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations * Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables + * Bug 438012 - [1.8][null] Bogus Warning: The nullness annotation is redundant with a default that applies to this location * Jesper S Moller <jesper@selskabet.org> - Contributions for * bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ @@ -241,6 +242,12 @@ public class MethodDeclaration extends AbstractMethodDeclaration { annotation.traverse(collector, (BlockScope) null); } } + + public boolean hasNullTypeAnnotation() { + // parser associates SE8 annotations to the declaration + return TypeReference.containsNullAnnotation(this.annotations) || + (this.returnType != null && this.returnType.hasNullTypeAnnotation()); // just in case + } public boolean isDefaultMethod() { return (this.modifiers & ExtraCompilerModifiers.AccDefaultMethod) != 0; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java index f815a4582..ca0929a80 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java @@ -175,18 +175,16 @@ public class NullAnnotationMatching { int dims = requiredType.dimensions(); if (requiredType.dimensions() == providedType.dimensions()) { long[] providedDimsTagBits = ((ArrayBinding)providedType).nullTagBitsPerDimension; - if (providedDimsTagBits == null) { - severity = 1; // required is annotated, provided not, need unchecked conversion - } else { - for (int i=0; i<=dims; i++) { - long requiredBits = validNullTagBits(requiredDimsTagBits[i]); - long providedBits = validNullTagBits(providedDimsTagBits[i]); - if (i > 0) - nullStatus = -1; // don't use beyond the outermost dimension - severity = Math.max(severity, computeNullProblemSeverity(requiredBits, providedBits, nullStatus, mode == CheckMode.OVERRIDE)); - if (severity == 2) - return NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH; - } + if (providedDimsTagBits == null) + providedDimsTagBits = new long[dims+1]; // set to unspec'd at all dimensions + for (int i=0; i<=dims; i++) { + long requiredBits = validNullTagBits(requiredDimsTagBits[i]); + long providedBits = validNullTagBits(providedDimsTagBits[i]); + if (i > 0) + nullStatus = -1; // don't use beyond the outermost dimension + severity = Math.max(severity, computeNullProblemSeverity(requiredBits, providedBits, nullStatus, mode == CheckMode.OVERRIDE && nullStatus == -1)); + if (severity == 2) + return NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH; } } else if (providedType.id == TypeIds.T_null) { if (dims > 0 && requiredDimsTagBits[0] == TagBits.AnnotationNonNull) @@ -389,13 +387,25 @@ public class NullAnnotationMatching { return one; } - private static int computeNullProblemSeverity(long requiredBits, long providedBits, int nullStatus, boolean strict) { - if ((requiredBits != 0 || strict) && requiredBits != providedBits) { + /** + * Evaluate problem severity from the given details: + * @param requiredBits null tagBits of the required type + * @param providedBits null tagBits of the provided type + * @param nullStatus -1 means: don't use, other values see constants in FlowInfo + * @param overrideDetailChecking true enables strictest mode during override analysis when checking type details (type argument, array content) + * @return see {@link #severity} for interpretation of values + */ + private static int computeNullProblemSeverity(long requiredBits, long providedBits, int nullStatus, boolean overrideDetailChecking) { + // nullStatus: + // overrideDetailChecking: + if ((requiredBits != 0 || overrideDetailChecking) && requiredBits != providedBits) { if (requiredBits == TagBits.AnnotationNonNull && nullStatus == FlowInfo.NON_NULL) { return 0; // OK by flow analysis } if (requiredBits == TagBits.AnnotationNullMASK) return 0; // OK since LHS accepts either + if (nullStatus != -1 && !overrideDetailChecking && requiredBits == TagBits.AnnotationNullable) + return 0; // when using flow info, everything is compatible to nullable if (providedBits != 0) { return 2; // mismatching annotations } else { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java index c650029bb..218cdddd4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java @@ -13,9 +13,10 @@ * bug 342671 - ClassCastException: org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding cannot be cast to org.eclipse.jdt.internal.compiler.lookup.ArrayBinding * bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis * Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099 - * Bug 416181 – [1.8][compiler][null] Invalid assignment is not rejected by the compiler + * Bug 416181 - [1.8][compiler][null] Invalid assignment is not rejected by the compiler * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault * Bug 434600 - Incorrect null analysis error reporting on type parameters + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" * Andy Clement - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ @@ -116,6 +117,24 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer return true; } + @Override + public boolean hasNullTypeAnnotation() { + if (super.hasNullTypeAnnotation()) + return true; + if (this.resolvedType != null && !this.resolvedType.hasNullTypeAnnotations()) + return false; // shortcut + if (this.typeArguments != null) { + for (int i = 0; i < this.typeArguments.length; i++) { + TypeReference[] arguments = this.typeArguments[i]; + for (int j = 0; j < arguments.length; j++) { + if (arguments[i].hasNullTypeAnnotation()) + return true; + } + } + } + return false; + } + /** * @return char[][] */ @@ -341,7 +360,7 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null; if (currentOriginal.isGenericType()) { - if (typeIsConsistent && qualifyingType != null && qualifyingType.isParameterizedType()) { + if (typeIsConsistent && qualifyingType != null && qualifyingType.isParameterizedType() && !currentOriginal.isStatic()) { scope.problemReporter().parameterizedMemberTypeMissingArguments(this, scope.environment().createParameterizedType(currentOriginal, null, qualifyingType), i); typeIsConsistent = false; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java index d9e4fd121..93fac3cc0 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java @@ -16,6 +16,7 @@ * Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099 * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault * Bug 434600 - Incorrect null analysis error reporting on type parameters + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" * Andy Clement - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ @@ -165,6 +166,21 @@ public class ParameterizedSingleTypeReference extends ArrayTypeReference { return true; } + @Override + public boolean hasNullTypeAnnotation() { + if (super.hasNullTypeAnnotation()) + return true; + if (this.resolvedType != null && !this.resolvedType.hasNullTypeAnnotations()) + return false; // shortcut + if (this.typeArguments != null) { + for (int i = 0; i < this.typeArguments.length; i++) { + if (this.typeArguments[i].hasNullTypeAnnotation()) + return true; + } + } + return false; + } + /* * No need to check for reference to raw type per construction */ 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 a2ab15d3b..9e7c2a074 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 @@ -333,7 +333,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc // perform some extra emulation work in case there is some and we are inside a local type only if (allocatedTypeErasure.isNestedType() - && currentScope.enclosingSourceType().isLocalType()) { + && (currentScope.enclosingSourceType().isLocalType() || currentScope.isLambdaScope())) { if (allocatedTypeErasure.isLocalType()) { ((LocalTypeBinding) allocatedTypeErasure).addInnerEmulationDependent(currentScope, this.enclosingInstance != null); 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 51a63781e..9ce03b569 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 @@ -26,6 +26,9 @@ * Bug 428264 - [1.8] method reference of generic class causes problems (wrong inference result or NPE) * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations * Bug 426537 - [1.8][inference] Eclipse compiler thinks I<? super J> is compatible with I<J<?>> - raw type J involved + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" + * Bug 435689 - [1.8][inference] Type inference not occurring with lambda expression and method reference + * Bug 438383 - [1.8][null] Bogus warning: Null type safety at method return type * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contribution for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) *******************************************************************************/ @@ -385,9 +388,10 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat return this.resolvedType = null; } + if (lhsType != null && !lhsType.isRawType()) // RawType::m and RawType::new are not exact method references + this.exactMethodBinding = isMethodReference() ? scope.getExactMethod(lhsType, this.selector, this) : scope.getExactConstructor(lhsType, this); + if (this.expectedType == null && this.expressionContext == INVOCATION_CONTEXT) { - if (lhsType != null && !lhsType.isRawType()) // RawType::m and RawType::new are not exact method references - this.exactMethodBinding = isMethodReference() ? scope.getExactMethod(lhsType, this.selector, this) : scope.getExactConstructor(lhsType, this); return new PolyTypeBinding(this); } super.resolveType(scope); @@ -409,7 +413,7 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat return this.resolvedType = null; } - if (this.lhs instanceof TypeReference && lhsType.hasNullTypeAnnotations()) { + if (this.lhs instanceof TypeReference && ((TypeReference)this.lhs).hasNullTypeAnnotation()) { scope.problemReporter().nullAnnotationUnsupportedLocation((TypeReference) this.lhs); } @@ -602,7 +606,8 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat scope.problemReporter().referenceExpressionArgumentNullityMismatch(this, bindingParameter, descriptorParameter, this.descriptor, i, annotationStatus); } } - if ((this.descriptor.returnType.tagBits & TagBits.AnnotationNonNull) != 0) { + if (!this.binding.isConstructor() && (this.descriptor.returnType.tagBits & TagBits.AnnotationNonNull) != 0) { + // since constructors never return null we don't have to check those anyway. if ((this.binding.returnType.tagBits & TagBits.AnnotationNonNull) == 0) { char[][] providedAnnotationName = ((this.binding.returnType.tagBits & TagBits.AnnotationNullable) != 0) ? scope.environment().getNullableAnnotationName() : null; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java index 1bdffbcd3..e4ca0bc35 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.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 @@ -1175,6 +1175,8 @@ protected void verifyDuplicationAndOrder(int length, TypeBinding[] argumentTypes int totalCount = 0; ReferenceBinding[][] allExceptionTypes = new ReferenceBinding[length][]; for (int i = 0; i < length; i++) { + if (argumentTypes[i] instanceof ArrayBinding) + continue; ReferenceBinding currentExceptionType = (ReferenceBinding) argumentTypes[i]; TypeReference catchArgumentType = this.catchArguments[i].type; if ((catchArgumentType.bits & ASTNode.IsUnionType) != 0) { @@ -1195,6 +1197,7 @@ protected void verifyDuplicationAndOrder(int length, TypeBinding[] argumentTypes this.caughtExceptionsCatchBlocks = new int[totalCount]; for (int i = 0, l = 0; i < length; i++) { ReferenceBinding[] currentExceptions = allExceptionTypes[i]; + if (currentExceptions == null) continue; loop: for (int j = 0, max = currentExceptions.length; j < max; j++) { ReferenceBinding exception = currentExceptions[j]; this.caughtExceptionTypes[l] = exception; @@ -1202,6 +1205,7 @@ protected void verifyDuplicationAndOrder(int length, TypeBinding[] argumentTypes // now iterate over all previous exceptions for (int k = 0; k < i; k++) { ReferenceBinding[] exceptions = allExceptionTypes[k]; + if (exceptions == null) continue; for (int n = 0, max2 = exceptions.length; n < max2; n++) { ReferenceBinding currentException = exceptions[n]; if (exception.isCompatibleWith(currentException)) { @@ -1222,6 +1226,8 @@ protected void verifyDuplicationAndOrder(int length, TypeBinding[] argumentTypes } else { this.caughtExceptionTypes = new ReferenceBinding[length]; for (int i = 0; i < length; i++) { + if (argumentTypes[i] instanceof ArrayBinding) + continue; this.caughtExceptionTypes[i] = (ReferenceBinding) argumentTypes[i]; for (int j = 0; j < i; j++) { if (this.caughtExceptionTypes[i].isCompatibleWith(argumentTypes[j])) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java index 6f27fb007..998bcdeda 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java @@ -1406,8 +1406,8 @@ public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, Fl ReferenceBinding superclassBinding = (ReferenceBinding)nestedType.superclass.erasure(); if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) { if (!superclassBinding.isLocalType() - || ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null){ - + || ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null + || superclassBinding.isMemberType()){ nestedType.addSyntheticArgument(superclassBinding.enclosingType()); } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java index 5e96f02bf..3b974833a 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java @@ -20,6 +20,9 @@ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault * Bug 434570 - Generic type mismatch for parametrized class annotation attribute with inner class * Bug 434600 - Incorrect null analysis error reporting on type parameters + * Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator @@ -803,12 +806,16 @@ protected void resolveAnnotations(Scope scope, int location) { && (this.resolvedType.tagBits & TagBits.AnnotationNullMASK) == 0 && !this.resolvedType.isTypeVariable() && !this.resolvedType.isWildcard() - && location != 0 + && location != 0 && scope.hasDefaultNullnessFor(location)) { - LookupEnvironment environment = scope.environment(); - AnnotationBinding[] annots = new AnnotationBinding[]{environment.getNonNullAnnotation()}; - this.resolvedType = environment.createAnnotatedType(this.resolvedType, annots); + if (location == Binding.DefaultLocationTypeBound && this.resolvedType.id == TypeIds.T_JavaLangObject) { + scope.problemReporter().implicitObjectBoundNoNullDefault(this); + } else { + LookupEnvironment environment = scope.environment(); + AnnotationBinding[] annots = new AnnotationBinding[]{environment.getNonNullAnnotation()}; + this.resolvedType = environment.createAnnotatedType(this.resolvedType, annots); + } } } public int getAnnotatableLevels() { @@ -824,12 +831,12 @@ protected void checkNullConstraints(Scope scope, TypeReference[] typeArguments) TypeVariableBinding[] typeVariables = this.resolvedType.original().typeVariables(); for (int i = 0; i < typeArguments.length; i++) { TypeReference arg = typeArguments[i]; - if (arg.resolvedType != null && arg.resolvedType.hasNullTypeAnnotations()) + if (arg.resolvedType != null) arg.checkNullConstraints(scope, typeVariables, i); } } } -/** Check whether this type reference conforms to all null constraints defined for any of the given type variables. */ +/** Check whether this type reference conforms to the null constraints defined for the corresponding type variable. */ protected void checkNullConstraints(Scope scope, TypeBinding[] variables, int rank) { if (variables != null && variables.length > rank) { TypeBinding variable = variables[rank]; @@ -855,6 +862,26 @@ public Annotation findAnnotation(long nullTagBits) { } return null; } +public boolean hasNullTypeAnnotation() { + if (this.annotations != null) { + Annotation[] innerAnnotations = this.annotations[this.annotations.length-1]; + if (containsNullAnnotation(innerAnnotations)) + return true; + } + return false; +} +public static boolean containsNullAnnotation(Annotation[] annotations) { + if (annotations != null) { + for (int i = 0; i < annotations.length; i++) { + if (annotations[i] != null + && annotations[i].resolvedType != null + && (annotations[i].resolvedType.id == TypeIds.T_ConfiguredAnnotationNonNull + || annotations[i].resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable)) + return true; + } + } + return false; +} public TypeReference[] getTypeReferences() { return new TypeReference [] { this }; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java index 7f908cc37..adb00abf1 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java @@ -13,6 +13,7 @@ * Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099 * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault + * Bug 440462 - [null][compiler]NPE in EJC for erroneous null annotations *******************************************************************************/ package org.eclipse.jdt.internal.compiler.ast; @@ -75,7 +76,13 @@ public class Wildcard extends SingleTypeReference { if (boundType != null && boundType.hasNullTypeAnnotations() && this.resolvedType.hasNullTypeAnnotations()) { if (((boundType.tagBits | this.resolvedType.tagBits) & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) { // are both set? Annotation annotation = this.bound.findAnnotation(boundType.tagBits & TagBits.AnnotationNullMASK); - scope.problemReporter().contradictoryNullAnnotationsOnBounds(annotation, this.resolvedType.tagBits); + if (annotation == null) { // false alarm, implicit annotation is no conflict, but should be removed: + TypeBinding newBound = boundType.unannotated(true); + ((WildcardBinding)this.resolvedType).bound = newBound; + this.bound.resolvedType = newBound; + } else { + scope.problemReporter().contradictoryNullAnnotationsOnBounds(annotation, this.resolvedType.tagBits); + } } } return this.resolvedType; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java index fd8105b6b..cac02c8e7 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java @@ -16,6 +16,7 @@ import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair; import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; +import org.eclipse.jdt.internal.compiler.lookup.TypeIds; /** * A type annotation walker that adds missing NonNull annotations according to the current default. @@ -25,6 +26,8 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke private int defaultNullness; private boolean atDefaultLocation; private boolean nextIsDefaultLocation; + private boolean atTypeBound; + private boolean nextIsTypeBound; private boolean isEmpty; IBinaryAnnotation nonNullAnnotation; @@ -38,24 +41,26 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke /** Create an initial walker without 'real' type annotations, but with a nonnull default. */ public NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, LookupEnvironment environment) { - this(defaultNullness, getNonNullAnnotation(environment), false); + this(defaultNullness, getNonNullAnnotation(environment), false, false); } /** Get restricted walker, still with non-empty type annotations. */ NonNullDefaultAwareTypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations, long newMatches, int newPathPtr, - int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation) { + int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation, boolean atTypeBound) { super(typeAnnotations, newMatches, newPathPtr); this.defaultNullness = defaultNullness; this.nonNullAnnotation = nonNullAnnotation; this.atDefaultLocation = atDefaultLocation; + this.atTypeBound = atTypeBound; } /** Create a restricted walker without 'real' type annotations, but with a nonnull default. */ - NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation) { + NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation, boolean atTypeBound) { super(null, 0, 0); this.nonNullAnnotation = nonNullAnnotation; this.defaultNullness = defaultNullness; this.atDefaultLocation = atDefaultLocation; + this.atTypeBound = atTypeBound; this.isEmpty = true; } @@ -79,16 +84,19 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke // considers nextIsDefaultLocation as the new atDefaultLocation try { // do we have any change at all? - if (this.matches == newMatches && this.pathPtr == newPathPtr && this.atDefaultLocation == this.nextIsDefaultLocation) + if (this.matches == newMatches && this.pathPtr == newPathPtr + && this.atDefaultLocation == this.nextIsDefaultLocation && this.atTypeBound == this.nextIsTypeBound) return this; // are we running out of real type annotations? if (newMatches == 0 || this.typeAnnotations == null || this.typeAnnotations.length == 0) - return new NonNullDefaultAwareTypeAnnotationWalker(this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation); + return new NonNullDefaultAwareTypeAnnotationWalker(this.defaultNullness, this.nonNullAnnotation, + this.nextIsDefaultLocation, this.nextIsTypeBound); // proceed as normal, but pass on our specific fields, too: return new NonNullDefaultAwareTypeAnnotationWalker(this.typeAnnotations, newMatches, newPathPtr, - this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation); + this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation, this.nextIsTypeBound); } finally { this.nextIsDefaultLocation = false; // expire + this.nextIsTypeBound = false; } } @@ -109,6 +117,7 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke @Override public TypeAnnotationWalker toTypeBound(short boundIndex) { this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeBound) != 0; + this.nextIsTypeBound = true; if (this.isEmpty) return restrict(this.matches, this.pathPtr); return super.toTypeBound(boundIndex); } @@ -116,6 +125,7 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke @Override public TypeAnnotationWalker toTypeParameterBounds(boolean isClassTypeParameter, int parameterRank) { this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeBound) != 0; + this.nextIsTypeBound = true; if (this.isEmpty) return restrict(this.matches, this.pathPtr); return super.toTypeParameterBounds(isClassTypeParameter, parameterRank); } @@ -123,6 +133,7 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke @Override public TypeAnnotationWalker toTypeArgument(int rank) { this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeArgument) != 0; + this.nextIsTypeBound = false; if (this.isEmpty) return restrict(this.matches, this.pathPtr); return super.toTypeArgument(rank); } @@ -130,14 +141,17 @@ public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalke @Override public TypeAnnotationWalker toTypeParameter(boolean isClassTypeParameter, int rank) { this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeParameter) != 0; + this.nextIsTypeBound = false; if (this.isEmpty) return restrict(this.matches, this.pathPtr); return super.toTypeParameter(isClassTypeParameter, rank); } @Override - public IBinaryAnnotation[] getAnnotationsAtCursor() { - IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor(); - if (this.atDefaultLocation) { + public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) { + IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor(currentTypeId); + if (this.atDefaultLocation && + !(this.atTypeBound && currentTypeId == TypeIds.T_JavaLangObject)) // for CLIMB-to-top consider a j.l.Object type bound as no explicit type bound + { if (normalAnnotations == null || normalAnnotations.length == 0) return new IBinaryAnnotation[] { this.nonNullAnnotation }; int len = normalAnnotations.length; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java index 9f189b7cf..3e525b787 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java @@ -41,7 +41,7 @@ public class TypeAnnotationWalker { public TypeAnnotationWalker toTypeBound(short boundIndex) { return this; } public TypeAnnotationWalker toTypeParameter(boolean isClassTypeParameter, int rank) { return this; } public TypeAnnotationWalker toNextDetail(int detailKind) { return this; } - public IBinaryAnnotation[] getAnnotationsAtCursor() { return NO_ANNOTATIONS; } + public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) { return NO_ANNOTATIONS; } }; final protected IBinaryTypeAnnotation[] typeAnnotations; // the actual material we're managing here @@ -298,7 +298,7 @@ public class TypeAnnotationWalker { * Retrieve the type annotations at the current position * reached by invocations of toXYZ() methods. */ - public IBinaryAnnotation[] getAnnotationsAtCursor() { + public IBinaryAnnotation[] getAnnotationsAtCursor(int currentTypeId) { int length = this.typeAnnotations.length; IBinaryAnnotation[] filtered = new IBinaryAnnotation[length]; long ptr = 1; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java index a09369de7..bcd345fa4 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java @@ -14,6 +14,7 @@ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for * Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas + * Bug 439889 - [1.8][compiler] [lambda] Deserializing lambda fails with IllegalArgumentException: "Invalid lambda deserialization" *******************************************************************************/ package org.eclipse.jdt.internal.compiler.codegen; @@ -786,6 +787,7 @@ public class ConstantPool implements ClassFileConstants, TypeIds { isInterface ? binding.isStatic() ? MethodHandleRefKindInvokeStatic : binding.isPrivate() ? MethodHandleRefKindInvokeSpecial : MethodHandleRefKindInvokeInterface : binding.isConstructor() ? MethodHandleRefKindNewInvokeSpecial : binding.isStatic() ? MethodHandleRefKindInvokeStatic + : binding.isPrivate() ? MethodHandleRefKindInvokeSpecial : MethodHandleRefKindInvokeVirtual; return literalIndexForMethodHandle(referenceKind, binding.declaringClass, binding.selector, binding.signature(), isInterface); diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java index e2cd3329d..5d652aa0c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java @@ -21,6 +21,8 @@ * Bug 425460 - [1.8] [inference] Type not inferred on stream.toArray * Bug 426792 - [1.8][inference][impl] generify new type inference engine * Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation. + * 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 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -476,8 +478,17 @@ public TypeBinding maybeWrapRoleType(ASTNode typedNode, TypeArgumentUpdater upda public String toString() { return this.leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$ } -public TypeBinding unannotated() { - return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this; +public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { + if (!hasTypeAnnotations()) + return this; + if (removeOnlyNullAnnotations) { + if (!hasNullTypeAnnotations()) + return this; + AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations); + if (newAnnotations.length > 0) + return this.environment.createArrayType(this.leafComponentType.unannotated(false), this.dimensions, newAnnotations); + } + return this.environment.getUnannotatedType(this); } @Override public TypeBinding uncapture(Scope scope) { @@ -486,5 +497,8 @@ public TypeBinding uncapture(Scope scope) { TypeBinding leafType = this.leafComponentType.uncapture(scope); return scope.environment().createArrayType(leafType, this.dimensions, this.typeAnnotations); } - +@Override +public boolean acceptsNonNullDefault() { + return true; +} } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java index 6e0bd31fe..aad394b07 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.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 @@ -10,6 +10,7 @@ * Stephan Herrmann - Contribution for * bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation. * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -172,7 +173,7 @@ public class BaseTypeBinding extends TypeBinding { super.setTypeAnnotations(annotations, false); // never set nullTagBits on base types } - public TypeBinding unannotated() { + public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { if (!this.hasTypeAnnotations()) return this; switch (this.id) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index 8c7f6feb6..87c7cf542 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -28,6 +28,9 @@ * Bug 392245 - [1.8][compiler][null] Define whether / how @NonNullByDefault applies to TYPE_USE locations * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault * Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE. + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables + * Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type + * Bug 434602 - Possible error with inferred null annotations leading to contradictory null annotations * Jesper Steen Moller - Contributions for * Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable @@ -1003,7 +1006,7 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[ ? new MethodBinding(methodModifiers, parameters, exceptions, this) : new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this); - IBinaryAnnotation[] receiverAnnotations = walker.toReceiver().getAnnotationsAtCursor(); + IBinaryAnnotation[] receiverAnnotations = walker.toReceiver().getAnnotationsAtCursor(0); if (receiverAnnotations != null && receiverAnnotations.length > 0) { result.receiver = this.environment.createAnnotatedType(this, createAnnotations(receiverAnnotations, this.environment, missingTypeNames)); } @@ -1012,7 +1015,7 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[ IBinaryAnnotation[] annotations = method.getAnnotations(); if (annotations == null || annotations.length == 0) if (method.isConstructor()) - annotations = walker.toMethodReturn().getAnnotationsAtCursor(); // FIXME: When both exist, order could become an issue. + annotations = walker.toMethodReturn().getAnnotationsAtCursor(0); // FIXME: When both exist, order could become an issue. result.setAnnotations( createAnnotations(annotations, this.environment, missingTypeNames), paramAnnotations, @@ -1025,9 +1028,9 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[ if (use15specifics) result.tagBits |= method.getTagBits(); result.typeVariables = typeVars; - // fixup the declaring element of the type variable + // fixup the declaring element of all type variables for (int i = 0, length = typeVars.length; i < length; i++) - typeVars[i].declaringElement = result; + this.environment.typeSystem.fixTypeVariableDeclaringElement(typeVars[i], result); //{ObjectTeams: // transfer "callsBaseCtor": if (method instanceof MethodInfo && ((MethodInfo)method).callsBaseCtor()) { @@ -1190,7 +1193,7 @@ private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, bool int colon = CharOperation.indexOf(Util.C_COLON, typeSignature, i); char[] variableName = CharOperation.subarray(typeSignature, i, colon); TypeVariableBinding typeVariable = new TypeVariableBinding(variableName, this, rank, this.environment); - AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.toTypeParameter(isClassTypeParameter, rank++).getAnnotationsAtCursor(), + AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.toTypeParameter(isClassTypeParameter, rank++).getAnnotationsAtCursor(0), this.environment, missingTypeNames); if (annotations != null && annotations != Binding.NO_ANNOTATIONS) typeVariable.setTypeAnnotations(annotations, this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled); @@ -1892,6 +1895,12 @@ SimpleLookupTable storedAnnotations(boolean forceInitialize) { //pre: null annotation analysis is enabled private void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBinding, boolean isEnum) { if (!isPrototype()) throw new IllegalStateException(); + + if (isEnum && (field.getModifiers() & ClassFileConstants.AccEnum) != 0) { + fieldBinding.tagBits |= TagBits.AnnotationNonNull; + return; // we know it's nonnull, no need to look for null *annotations* on enum constants. + } + if (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8) { TypeBinding fieldType = fieldBinding.type; if (fieldType != null @@ -1935,11 +1944,6 @@ private void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBi if (!explicitNullness && (this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) { fieldBinding.tagBits |= TagBits.AnnotationNonNull; } - if (isEnum) { - if ((field.getModifiers() & ClassFileConstants.AccEnum) != 0) { - fieldBinding.tagBits |= TagBits.AnnotationNonNull; - } - } } private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding) { @@ -2369,7 +2373,14 @@ public String toString() { return buffer.toString(); } -public TypeBinding unannotated() { +public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { + if (removeOnlyNullAnnotations) { + if (!hasNullTypeAnnotations()) + return this; + AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations); + if (newAnnotations.length > 0) + return this.environment.createAnnotatedType(this.prototype, newAnnotations); + } return this.prototype; } 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 8a88b1bf3..59506820f 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 @@ -296,8 +296,12 @@ void computeLocalVariablePositions(int ilocal, int initOffset, CodeStream codeSt // SH} && ((local.declaration.bits & ASTNode.IsLocalDeclarationReachable) != 0)) { // declaration is reachable - if (!(local.declaration instanceof Argument)) // do not report unused catch arguments + if (local.isCatchParameter()) { + problemReporter().unusedExceptionParameter(local.declaration); // report unused catch arguments + } + else { problemReporter().unusedLocalVariable(local.declaration); + } } // could be optimized out, but does need to preserve unread variables ? 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 24f9b2a07..d121d3edc 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 @@ -116,6 +116,7 @@ class BoundSet { InferenceContext18.sortTypes(rights); return rights; } + // pre: beta is a prototype public boolean hasDependency(InferenceVariable beta) { if (this.superBounds != null && hasDependency(this.superBounds, beta)) return true; @@ -131,11 +132,12 @@ class BoundSet { } return false; } + // pre: var is a prototype private boolean hasDependency(Set<TypeBound> someBounds, InferenceVariable var) { Iterator<TypeBound> bIt = someBounds.iterator(); while (bIt.hasNext()) { TypeBound bound = bIt.next(); - if (bound.right == var || bound.right.mentionsAny(new TypeBinding[] {var}, -1)) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(bound.right, var) || bound.right.mentionsAny(new TypeBinding[] {var}, -1)) return true; } return false; @@ -236,7 +238,7 @@ class BoundSet { if (nullHints == TagBits.AnnotationNullMASK) { // on contradiction remove null type annotations for (int i = 0; i < boundTypes.length; i++) - boundTypes[i] = boundTypes[i].unannotated(); + boundTypes[i] = boundTypes[i].unannotated(true); } else { AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints); if (annot != null) { @@ -266,7 +268,7 @@ class BoundSet { nullHints |= it.next().nullHints; } if (nullHints == TagBits.AnnotationNullMASK) // on contradiction remove null type annotations - return type.unannotated(); + return type.unannotated(true); AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints); if (annot != null) // only get here if exactly one of @NonNull or @Nullable was hinted; now apply this hint: @@ -286,7 +288,7 @@ class BoundSet { // adjust 'type' to fit the newBits AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(newBits); if (annot != null) - type = environment.createAnnotatedType(type.unannotated(), annot); + type = environment.createAnnotatedType(type.unannotated(true), annot); } } this.instantiation = type; @@ -355,19 +357,20 @@ class BoundSet { } public void addBound(TypeBound bound, LookupEnvironment environment) { - ThreeSets three = this.boundsPerVariable.get(bound.left); + InferenceVariable variable = bound.left.prototype(); + ThreeSets three = this.boundsPerVariable.get(variable); if (three == null) - this.boundsPerVariable.put(bound.left, (three = new ThreeSets())); + 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, bound.left, environment); + 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; + InferenceVariable rightIV = (InferenceVariable) bound.right.prototype(); three = this.boundsPerVariable.get(rightIV); if (three == null) this.boundsPerVariable.put(rightIV, (three = new ThreeSets())); @@ -387,14 +390,14 @@ class BoundSet { } public boolean isInstantiated(InferenceVariable inferenceVariable) { - ThreeSets three = this.boundsPerVariable.get(inferenceVariable); + ThreeSets three = this.boundsPerVariable.get(inferenceVariable.prototype()); if (three != null) return three.instantiation != null; return false; } public TypeBinding getInstantiation(InferenceVariable inferenceVariable, LookupEnvironment environment) { - ThreeSets three = this.boundsPerVariable.get(inferenceVariable); + ThreeSets three = this.boundsPerVariable.get(inferenceVariable.prototype()); if (three != null) { TypeBinding instantiation = three.instantiation; if (environment != null && environment.globalOptions.isAnnotationBasedNullAnalysisEnabled @@ -531,7 +534,7 @@ class BoundSet { if (ai instanceof WildcardBinding) { WildcardBinding wildcardBinding = (WildcardBinding)ai; TypeBinding t = wildcardBinding.bound; - ThreeSets three = this.boundsPerVariable.get(alpha); + ThreeSets three = this.boundsPerVariable.get(alpha.prototype()); if (three != null) { Iterator<TypeBound> it; if (three.sameBounds != null) { @@ -617,7 +620,7 @@ class BoundSet { private ConstraintTypeFormula combineSameSame(TypeBound boundS, TypeBound boundT) { // α = S and α = T imply ⟨S = T⟩ - if (boundS.left == boundT.left) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(boundS.left, boundT.left)) return ConstraintTypeFormula.create(boundS.right, boundT.right, ReductionResult.SAME, boundS.isSoft||boundT.isSoft); // match against more shapes: @@ -649,25 +652,25 @@ class BoundSet { // α = S and T <: α imply ⟨T <: S⟩ InferenceVariable alpha = boundS.left; TypeBinding s = boundS.right; - if (alpha == boundT.left) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(alpha,boundT.left)) return ConstraintTypeFormula.create(s, boundT.right, boundT.relation, boundT.isSoft||boundS.isSoft); - if (alpha == boundT.right) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(alpha, boundT.right)) return ConstraintTypeFormula.create(boundT.right, s, boundT.relation, boundT.isSoft||boundS.isSoft); if (boundS.right instanceof InferenceVariable) { // reverse: alpha = (InferenceVariable) boundS.right; s = boundS.left; - if (alpha == boundT.left) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(alpha, boundT.left)) return ConstraintTypeFormula.create(s, boundT.right, boundT.relation, boundT.isSoft||boundS.isSoft); - if (alpha == boundT.right) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(alpha, boundT.right)) return ConstraintTypeFormula.create(boundT.right, s, boundT.relation, boundT.isSoft||boundS.isSoft); } // α = U and S <: T imply ⟨S[α:=U] <: T[α:=U]⟩ TypeBinding u = boundS.right; if (u.isProperType(true)) { - TypeBinding left = (alpha == boundT.left) ? u : boundT.left; //$IDENTITY-COMPARISON$ InferenceVariable + TypeBinding left = (TypeBinding.equalsEquals(alpha, boundT.left)) ? u : boundT.left; TypeBinding right = boundT.right.substituteInferenceVariable(alpha, u); return ConstraintTypeFormula.create(left, right, boundT.relation, boundT.isSoft||boundS.isSoft); } @@ -677,13 +680,13 @@ class BoundSet { private ConstraintTypeFormula combineSuperAndSub(TypeBound boundS, TypeBound boundT) { // permutations of: S <: α and α <: T imply ⟨S <: T⟩ InferenceVariable alpha = boundS.left; - if (alpha == boundT.left) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(alpha, boundT.left)) // α >: S and α <: T imply ⟨S <: T⟩ return ConstraintTypeFormula.create(boundS.right, boundT.right, ReductionResult.SUBTYPE, boundT.isSoft||boundS.isSoft); if (boundS.right instanceof InferenceVariable) { // try reverse: alpha = (InferenceVariable) boundS.right; - if (alpha == boundT.right) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(alpha, boundT.right)) // S :> α and T <: α imply ⟨S :> T⟩ return ConstraintTypeFormula.create(boundS.left, boundT.left, ReductionResult.SUPERTYPE, boundT.isSoft||boundS.isSoft); } @@ -692,10 +695,10 @@ class BoundSet { private ConstraintTypeFormula combineEqualSupers(TypeBound boundS, TypeBound boundT) { // more permutations of: S <: α and α <: T imply ⟨S <: T⟩ - if (boundS.left == boundT.right) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(boundS.left, boundT.right)) // came in as: α REL S and T REL α imply ⟨T REL S⟩ return ConstraintTypeFormula.create(boundT.left, boundS.right, boundS.relation, boundT.isSoft||boundS.isSoft); - if (boundS.right == boundT.left) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(boundS.right, boundT.left)) // came in as: S REL α and α REL T imply ⟨S REL T⟩ return ConstraintTypeFormula.create(boundS.left, boundT.right, boundS.relation, boundT.isSoft||boundS.isSoft); return null; @@ -710,7 +713,7 @@ class BoundSet { */ if (boundS.relation != ReductionResult.SUBTYPE || boundT.relation != ReductionResult.SUBTYPE) return null; - if (boundS.left != boundT.left) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.notEquals(boundS.left, boundT.left)) return null; TypeBinding[] supers = superTypesWithCommonGenericType(boundS.right, boundT.right); if (supers != null) @@ -776,13 +779,15 @@ class BoundSet { * Does this bound set define a direct dependency between the two given inference variables? */ public boolean dependsOnResolutionOf(InferenceVariable alpha, InferenceVariable beta) { + alpha = alpha.prototype(); + beta = beta.prototype(); Iterator<Map.Entry<ParameterizedTypeBinding, ParameterizedTypeBinding>> captureIter = this.captures.entrySet().iterator(); boolean betaIsInCaptureLhs = false; while (captureIter.hasNext()) { // TODO: optimization: consider separate index structure (by IV) Entry<ParameterizedTypeBinding, ParameterizedTypeBinding> entry = captureIter.next(); ParameterizedTypeBinding g = entry.getKey(); for (int i = 0; i < g.arguments.length; i++) { - if (g.arguments[i] == alpha) { //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(g.arguments[i], alpha)) { // An inference variable α appearing on the left-hand side of a bound of the form G<..., α, ...> = capture(G<...>) // depends on the resolution of every other inference variable mentioned in this bound (on both sides of the = sign). ParameterizedTypeBinding captured = entry.getValue(); @@ -790,7 +795,7 @@ class BoundSet { return true; if (g.mentionsAny(new TypeBinding[]{beta}, i)) // exclude itself return true; - } else if (g.arguments[i] == beta) { //$IDENTITY-COMPARISON$ InferenceVariable + } else if (TypeBinding.equalsEquals(g.arguments[i], beta)) { betaIsInCaptureLhs = true; } } @@ -840,7 +845,7 @@ class BoundSet { * Answer all upper bounds for the given inference variable as defined by any bounds in this set. */ public TypeBinding[] upperBounds(InferenceVariable variable, boolean onlyProper) { - ThreeSets three = this.boundsPerVariable.get(variable); + ThreeSets three = this.boundsPerVariable.get(variable.prototype()); if (three == null || three.subBounds == null) return Binding.NO_TYPES; return three.upperBounds(onlyProper, variable); @@ -853,7 +858,7 @@ class BoundSet { * Answer all lower bounds for the given inference variable as defined by any bounds in this set. */ TypeBinding[] lowerBounds(InferenceVariable variable, boolean onlyProper) { - ThreeSets three = this.boundsPerVariable.get(variable); + ThreeSets three = this.boundsPerVariable.get(variable.prototype()); if (three == null || three.superBounds == null) return Binding.NO_TYPES; return three.lowerBounds(onlyProper, variable); @@ -881,7 +886,7 @@ class BoundSet { } public TypeBinding findWrapperTypeBound(InferenceVariable variable) { - ThreeSets three = this.boundsPerVariable.get(variable); + ThreeSets three = this.boundsPerVariable.get(variable.prototype()); if (three == null) return null; return three.findSingleWrapperType(); } @@ -892,7 +897,7 @@ class BoundSet { // i) B2 contains a bound of one of the forms α = S or S <: α, where S is a wildcard-parameterized type, or ... if (targetType.isBaseType()) return false; if (InferenceContext18.parameterizedWithWildcard(targetType) != null) return false; - ThreeSets ts = this.boundsPerVariable.get(alpha); + ThreeSets ts = this.boundsPerVariable.get(alpha.prototype()); if (ts.sameBounds != null) { Iterator<TypeBound> bounds = ts.sameBounds.iterator(); while (bounds.hasNext()) { @@ -933,7 +938,7 @@ class BoundSet { // where there exists no type of the form G<...> that is a supertype of S, but the raw type G is a supertype of S. if (!targetType.isParameterizedType()) return false; TypeBinding g = targetType.original(); - ThreeSets ts = this.boundsPerVariable.get(alpha); + ThreeSets ts = this.boundsPerVariable.get(alpha.prototype()); 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 a64e7ebad..c3c30a220 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 @@ -11,7 +11,6 @@ * Stephan Herrmann - Contribution for * Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec) * Bug 429384 - [1.8][null] implement conformance rules for null-annotated lower / upper type bounds - * Bug 434044 - Java 8 generics thinks single method is ambiguous *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -198,14 +197,8 @@ public class CaptureBinding extends TypeVariableBinding { } else { int length = substitutedVariableInterfaces.length; System.arraycopy(substitutedVariableInterfaces, 0, substitutedVariableInterfaces = new ReferenceBinding[length+1], 1, length); - // to properly support glb, perform capture *after* glb, so restart from the original bound: - substitutedVariableInterfaces[0] = (ReferenceBinding) originalWildcardBound; - ReferenceBinding[] glb = Scope.greaterLowerBound(substitutedVariableInterfaces); - if (glb != null) { - for (int i = 0; i < glb.length; i++) - glb[i] = (ReferenceBinding) glb[i].capture(scope, this.position); - } - this.setSuperInterfaces(glb); + substitutedVariableInterfaces[0] = (ReferenceBinding) capturedWildcardBound; + this.setSuperInterfaces(Scope.greaterLowerBound(substitutedVariableInterfaces)); } } else { // the wildcard bound should be a subtype of variable superclass diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java index 499021160..00bf7252d 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExceptionFormula.java @@ -104,7 +104,7 @@ public class ConstraintExceptionFormula extends ConstraintFormula { result.add(ConstraintTypeFormula.create(ePrime[i], e[j], SUBTYPE)); } for (int j = 0; j < n; j++) - inferenceContext.currentBounds.inThrows.add(e[j]); + inferenceContext.currentBounds.inThrows.add(e[j].prototype()); return result.toArray(new ConstraintFormula[result.size()]); } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java index 7b40ba482..f8f3f81e5 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintExpressionFormula.java @@ -435,7 +435,8 @@ class ConstraintExpressionFormula extends ConstraintFormula { if (sam.returnType != TypeBinding.VOID) { // ii) final TypeBinding r = sam.returnType; - Statement body = lambda.body(); + LambdaExpression resolved = lambda.getResolvedCopyForInferenceTargeting(this.right); + Statement body = resolved != null ? resolved.body() : lambda.body(); if (body instanceof Expression) { variables.addAll(new ConstraintExpressionFormula((Expression) body, r, COMPATIBLE).inputVariables(context)); } else { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java index c97efeaa0..8b6b04496 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java @@ -84,8 +84,11 @@ public class ImplicitNullAnnotationVerifier { return; // SH} long sourceLevel = scope.compilerOptions().sourceLevel; - boolean needToApplyNonNullDefault = currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter|Binding.DefaultLocationReturnType, - sourceLevel >= ClassFileConstants.JDK1_8); + boolean needToApplyReturnNonNullDefault = + currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationReturnType, sourceLevel >= ClassFileConstants.JDK1_8); + boolean needToApplyParameterNonNullDefault = + currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter, sourceLevel >= ClassFileConstants.JDK1_8); + boolean needToApplyNonNullDefault = needToApplyReturnNonNullDefault | needToApplyParameterNonNullDefault; // compatibility & inheritance do not consider constructors / static methods: boolean isInstanceMethod = !currentMethod.isConstructor() && !currentMethod.isStatic(); complain &= isInstanceMethod; @@ -118,7 +121,7 @@ public class ImplicitNullAnnotationVerifier { // recurse to prepare currentSuper checkImplicitNullAnnotations(currentSuper, null, false, scope); // TODO (stephan) complain=true if currentSuper is source method?? } - checkNullSpecInheritance(currentMethod, srcMethod, needToApplyNonNullDefault, complain, currentSuper, scope, inheritedNonNullnessInfos); + checkNullSpecInheritance(currentMethod, srcMethod, needToApplyReturnNonNullDefault, needToApplyParameterNonNullDefault, complain, currentSuper, scope, inheritedNonNullnessInfos); needToApplyNonNullDefault = false; } @@ -218,7 +221,8 @@ public class ImplicitNullAnnotationVerifier { * The main algorithm in this class. * @param currentMethod focus method * @param srcMethod AST of 'currentMethod' if present - * @param hasNonNullDefault is a @NonNull default applicable at the site of currentMethod? + * @param hasReturnNonNullDefault is a @NonNull default applicable for the return type of currentMethod? + * @param hasParameterNonNullDefault is a @NonNull default applicable for parameters of currentMethod? * @param shouldComplain should we report any errors found? * (see also comment about flows into this method, below). * @param inheritedMethod one overridden method from a super type @@ -228,7 +232,7 @@ public class ImplicitNullAnnotationVerifier { * Index position 0 is used for the return type, positions i+1 for argument i. */ void checkNullSpecInheritance(MethodBinding currentMethod, AbstractMethodDeclaration srcMethod, - boolean hasNonNullDefault, boolean shouldComplain, + boolean hasReturnNonNullDefault, boolean hasParameterNonNullDefault, boolean shouldComplain, MethodBinding inheritedMethod, Scope scope, InheritedNonNullnessInfo[] inheritedNonNullnessInfos) { // Note that basically two different flows lead into this method: @@ -259,7 +263,7 @@ public class ImplicitNullAnnotationVerifier { // unspecified, may fill in either from super or from default if (shouldInherit) { if (inheritedNullnessBits != 0) { - if (hasNonNullDefault) { + if (hasReturnNonNullDefault) { // both inheritance and default: check for conflict? if (shouldComplain && inheritedNullnessBits == TagBits.AnnotationNullable) scope.problemReporter().conflictingNullAnnotations(currentMethod, ((MethodDeclaration) srcMethod).returnType, inheritedMethod); @@ -275,7 +279,7 @@ public class ImplicitNullAnnotationVerifier { break returnType; // compatible by construction, skip complain phase below } } - if (hasNonNullDefault) { // conflict with inheritance already checked + if (hasReturnNonNullDefault && currentMethod.returnType.acceptsNonNullDefault()) { // conflict with inheritance already checked currentNullnessBits = TagBits.AnnotationNonNull; applyReturnNullBits(currentMethod, currentNullnessBits); } @@ -301,7 +305,10 @@ public class ImplicitNullAnnotationVerifier { substituteReturnType = substitute.returnType; } if (NullAnnotationMatching.analyse(inheritedMethod.returnType, currentMethod.returnType, substituteReturnType, 0, CheckMode.OVERRIDE).isAnyMismatch()) { - scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, useTypeAnnotations); + if (srcMethod != null) + scope.problemReporter().illegalReturnRedefinition(srcMethod, inheritedMethod, null); + else + scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, useTypeAnnotations); return; } } @@ -342,7 +349,7 @@ public class ImplicitNullAnnotationVerifier { // unspecified, may fill in either from super or from default if (inheritedNonNullNess != null) { if (shouldInherit) { - if (hasNonNullDefault) { + if (hasParameterNonNullDefault) { // both inheritance and default: check for conflict? if (shouldComplain && inheritedNonNullNess == Boolean.FALSE @@ -365,12 +372,14 @@ public class ImplicitNullAnnotationVerifier { continue; // compatible by construction, skip complain phase below } } - if (hasNonNullDefault) { // conflict with inheritance already checked + if (hasParameterNonNullDefault) { // conflict with inheritance already checked currentNonNullNess = Boolean.TRUE; if (!useTypeAnnotations) recordArgNonNullness(currentMethod, length, i, currentArgument, Boolean.TRUE); - else + else if (currentMethod.parameters[i].acceptsNonNullDefault()) recordArgNonNullness18(currentMethod, i, currentArgument, Boolean.TRUE, this.environment); + else + currentNonNullNess = null; // cancel if parameter doesn't accept the default } } if (shouldComplain) { @@ -416,9 +425,13 @@ public class ImplicitNullAnnotationVerifier { } } if (useTypeAnnotations) { + TypeBinding inheritedParameter = inheritedMethod.parameters[i]; TypeBinding substituteParameter = substituteParameters != null ? substituteParameters[i] : null; - if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedMethod.parameters[i], substituteParameter, 0, CheckMode.OVERRIDE).isAnyMismatch()) { - scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); + if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedParameter, substituteParameter, 0, CheckMode.OVERRIDE).isAnyMismatch()) { + if (currentArgument != null) + scope.problemReporter().illegalParameterRedefinition(currentArgument, inheritedMethod.declaringClass, inheritedParameter); + else + scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false); } } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java index a0df8bcb7..5d01de1a2 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java @@ -292,7 +292,8 @@ public class InferenceContext18 { } } if (checkVararg && varArgsType instanceof ArrayBinding) { - TypeBinding thetaF = substitute(((ArrayBinding) varArgsType).elementsType()); + varArgsType = ((ArrayBinding)varArgsType).elementsType(); + TypeBinding thetaF = substitute(varArgsType); for (int i = len; i < this.invocationArguments.length; i++) { if (this.invocationArguments[i].isPertinentToApplicability(varArgsType, method)) { this.initialConstraints[numConstraints++] = new ConstraintExpressionFormula(this.invocationArguments[i], thetaF, ReductionResult.COMPATIBLE, ARGUMENT_CONSTRAINTS_ARE_SOFT); @@ -330,22 +331,26 @@ public class InferenceContext18 { public InferenceVariable[] addTypeVariableSubstitutions(TypeBinding[] typeVariables) { int len2 = typeVariables.length; InferenceVariable[] newVariables = new InferenceVariable[len2]; + InferenceVariable[] toAdd = new InferenceVariable[len2]; + int numToAdd = 0; for (int i = 0; i < typeVariables.length; i++) { if (typeVariables[i] instanceof InferenceVariable) newVariables[i] = (InferenceVariable) typeVariables[i]; // prevent double substitution of an already-substituted inferenceVariable else - newVariables[i] = new InferenceVariable(typeVariables[i], this.variableCount++, this.currentInvocation, this.environment, this.object); + toAdd[numToAdd++] = + newVariables[i] = new InferenceVariable(typeVariables[i], this.variableCount++, this.currentInvocation, this.environment, this.object); } - - int start = 0; - if (this.inferenceVariables != null) { - int len1 = this.inferenceVariables.length; - System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables = new InferenceVariable[len1+len2], 0, len1); - start = len1; - } else { - this.inferenceVariables = new InferenceVariable[len2]; + if (numToAdd > 0) { + int start = 0; + if (this.inferenceVariables != null) { + int len1 = this.inferenceVariables.length; + System.arraycopy(this.inferenceVariables, 0, this.inferenceVariables = new InferenceVariable[len1+numToAdd], 0, len1); + start = len1; + } else { + this.inferenceVariables = new InferenceVariable[numToAdd]; + } + System.arraycopy(toAdd, 0, this.inferenceVariables, start, numToAdd); } - System.arraycopy(newVariables, 0, this.inferenceVariables, start, len2); return newVariables; } @@ -355,7 +360,7 @@ public class InferenceContext18 { TypeBinding parameter = parameters[i]; for (int j = 0; j < thrownExceptions.length; j++) { if (TypeBinding.equalsEquals(parameter, thrownExceptions[j])) { - this.currentBounds.inThrows.add(variables[i]); + this.currentBounds.inThrows.add(variables[i].prototype()); break; } } @@ -413,7 +418,8 @@ public class InferenceContext18 { } InferenceVariable[] variablesArray = allInputs.toArray(new InferenceVariable[allInputs.size()]); // ... is resolved - this.currentBounds.incorporate(this); + if (!this.currentBounds.incorporate(this)) + return null; BoundSet solution = resolve(variablesArray); // in rare cases resolving just one set of variables doesn't suffice, // don't bother with finding the necessary superset, just resolve all: @@ -955,7 +961,7 @@ public class InferenceContext18 { } else { TypeBinding[] upperBounds = tmpBoundSet.upperBounds(variable, true/*onlyProper*/); // check exception bounds: - if (tmpBoundSet.inThrows.contains(variable) && tmpBoundSet.hasOnlyTrivialExceptionBounds(variable, upperBounds)) { + if (tmpBoundSet.inThrows.contains(variable.prototype()) && tmpBoundSet.hasOnlyTrivialExceptionBounds(variable, upperBounds)) { TypeBinding runtimeException = this.scope.getType(TypeConstants.JAVA_LANG_RUNTIMEEXCEPTION, 3); tmpBoundSet.addBound(new TypeBound(variable, runtimeException, ReductionResult.SAME), this.environment); } else { @@ -1002,7 +1008,7 @@ public class InferenceContext18 { } public TypeBinding substitute(TypeVariableBinding typeVariable) { for (int j = 0; j < numVars; j++) - if (variables[j] == typeVariable) //$IDENTITY-COMPARISON$ InferenceVariable does not participate in type annotation encoding + if (TypeBinding.equalsEquals(variables[j], typeVariable)) return zs[j]; return typeVariable; } @@ -1039,7 +1045,7 @@ public class InferenceContext18 { ParameterizedTypeBinding key = captureKeys.next(); int len = key.arguments.length; for (int i = 0; i < len; i++) { - if (key.arguments[i] == variable) { //$IDENTITY-COMPARISON$ + if (TypeBinding.equalsEquals(key.arguments[i], variable)) { toRemove.add(key); break; } @@ -1137,7 +1143,7 @@ public class InferenceContext18 { if (!variableSet.add(currentVariable)) return true; // already present for (int j = 0; j < this.inferenceVariables.length; j++) { InferenceVariable nextVariable = this.inferenceVariables[j]; - if (nextVariable == currentVariable) continue; //$IDENTITY-COMPARISON$ Inference variables + if (TypeBinding.equalsEquals(nextVariable, currentVariable)) continue; if (boundSet.dependsOnResolutionOf(currentVariable, nextVariable)) if (!addDependencies(boundSet, variableSet, nextVariable, min)) return false; // abort traversal: no improvement diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java index eb5b260d0..a6a5b0923 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java @@ -22,6 +22,7 @@ public class InferenceVariable extends TypeVariableBinding { InvocationSite site; TypeBinding typeParameter; long nullHints; + private InferenceVariable prototype; public InferenceVariable(TypeBinding typeParameter, int variableRank, InvocationSite site, LookupEnvironment environment, ReferenceBinding object) { super(CharOperation.concat(typeParameter.shortReadableName(), Integer.toString(variableRank).toCharArray(), '#'), @@ -40,6 +41,20 @@ public class InferenceVariable extends TypeVariableBinding { } } this.superclass = object; + this.prototype = this; + } + + @Override + public TypeBinding clone(TypeBinding enclosingType) { + InferenceVariable clone = new InferenceVariable(this.typeParameter, this.rank, this.site, this.environment, this.superclass); + clone.tagBits = this.tagBits; + clone.nullHints = this.nullHints; + clone.prototype = this; + return clone; + } + + public InferenceVariable prototype() { + return this.prototype; } public char[] constantPoolName() { @@ -65,7 +80,7 @@ public class InferenceVariable extends TypeVariableBinding { protected // SH} TypeBinding substituteInferenceVariable(InferenceVariable var, TypeBinding substituteType) { - if (this == var) //$IDENTITY-COMPARISON$ InferenceVariable + if (TypeBinding.equalsEquals(this, var)) return substituteType; return this; } 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 ab058a8ec..356768613 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 @@ -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 @@ -8,7 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Stephan Herrmann - Contribution for - * bug 384380 - False positive on a « Potential null pointer access » after a continue + * bug 384380 - False positive on a "Potential null pointer access" after a continue * Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec) *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; 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 903c634e1..12aa5e4c6 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 @@ -26,6 +26,9 @@ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. * Bug 416190 - [1.8][null] detect incompatible overrides due to null type annotations * Bug 424624 - [1.8][null] if a static-object with annotation @NonNull is used, a warning is shown + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables + * Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type + * Bug 434602 - Possible error with inferred null annotations leading to contradictory null annotations *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -111,7 +114,7 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants { private int lastCompletedUnitIndex = -1; private int lastUnitIndex = -1; - private TypeSystem typeSystem; + TypeSystem typeSystem; public INameEnvironment nameEnvironment; public CompilerOptions globalOptions; @@ -1575,7 +1578,7 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean i AnnotationBinding [][] annotationsOnDimensions = null; if (dimension > 0 && walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) { for (int i = 0; i < dimension; i++) { - AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames); if (annotations != Binding.NO_ANNOTATIONS) { if (annotationsOnDimensions == null) annotationsOnDimensions = new AnnotationBinding[dimension][]; @@ -1660,7 +1663,7 @@ private TypeBinding annotateType(TypeBinding binding, TypeAnnotationWalker walke } AnnotationBinding [][] annotations = null; for (int i = 0; i < depth; i++) { - AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(binding.id), this, missingTypeNames); if (annots != null && annots.length > 0) { if (annotations == null) annotations = new AnnotationBinding[depth][]; @@ -1705,7 +1708,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab AnnotationBinding [][] annotationsOnDimensions = null; if (dimension > 0 && walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) { for (int i = 0; i < dimension; i++) { - AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames); if (annotations != Binding.NO_ANNOTATIONS) { if (annotationsOnDimensions == null) annotationsOnDimensions = new AnnotationBinding[dimension][]; @@ -1750,7 +1753,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab if (actualEnclosing != null) { // convert needed if read some static member type actualEnclosing = (ReferenceBinding) convertToRawType(actualEnclosing, false /*do not force conversion of enclosing types*/); } - AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(actualType.id), this, missingTypeNames); TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType, missingTypeNames, walker); ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, actualEnclosing, annotations); @@ -1764,7 +1767,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab if (memberType == null) this.problemReporter.corruptedSignature(parameterizedType, wrapper.signature, memberStart); // aborts walker = walker.toNextNestedType(); - annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(memberType.id), this, missingTypeNames); if (wrapper.signature[wrapper.start] == '<') { wrapper.start++; // skip '<' typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType, missingTypeNames, walker); @@ -1778,7 +1781,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab } private TypeBinding getTypeFromTypeVariable(TypeVariableBinding typeVariableBinding, int dimension, AnnotationBinding [][] annotationsOnDimensions, TypeAnnotationWalker walker, char [][][] missingTypeNames) { - AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames); if (annotations != null && annotations != Binding.NO_ANNOTATIONS) typeVariableBinding = (TypeVariableBinding) createAnnotatedType(typeVariableBinding, new AnnotationBinding [][] { annotations }); @@ -1805,18 +1808,18 @@ TypeBinding getTypeFromVariantTypeSignature( // ? super aType wrapper.start++; TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker.toWildcardBound()); - AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames); return this.typeSystem.getWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.SUPER, annotations); case '+' : // ? extends aType wrapper.start++; bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker.toWildcardBound()); - annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames); return this.typeSystem.getWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.EXTENDS, annotations); case '*' : // ? wrapper.start++; - annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames); + annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0), this, missingTypeNames); return this.typeSystem.getWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND, annotations); default : return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker); @@ -1943,4 +1946,27 @@ public TypeBinding getUnannotatedType(TypeBinding typeBinding) { public TypeBinding[] getAnnotatedTypes(TypeBinding type) { return this.typeSystem.getAnnotatedTypes(type); } + +public AnnotationBinding[] filterNullTypeAnnotations(AnnotationBinding[] typeAnnotations) { + if (typeAnnotations.length == 0) + return typeAnnotations; + AnnotationBinding[] filtered = new AnnotationBinding[typeAnnotations.length]; + int count = 0; + for (int i = 0; i < typeAnnotations.length; i++) { + AnnotationBinding typeAnnotation = typeAnnotations[i]; + if (typeAnnotation == null) { + count++; // sentinel in annotation sequence for array dimensions + } else { + int id = typeAnnotation.type.id; + if (id != TypeIds.T_ConfiguredAnnotationNonNull && id != TypeIds.T_ConfiguredAnnotationNullable) + filtered[count++] = typeAnnotation; + } + } + if (count == 0) + return Binding.NO_ANNOTATIONS; + if (count == typeAnnotations.length) + return typeAnnotations; + System.arraycopy(filtered, 0, filtered = new AnnotationBinding[count], 0, count); + return filtered; +} } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java index b0ede4a0d..2ba813598 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java @@ -22,6 +22,8 @@ * Bug 425152 - [1.8] [compiler] Lambda Expression not resolved but flow analyzed leading to NPE. * Bug 423505 - [1.8] Implement "18.5.4 More Specific Method Inference" * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault + * Bug 438012 - [1.8][null] Bogus Warning: The nullness annotation is redundant with a default that applies to this location + * Bug 440759 - [1.8][null] @NonNullByDefault should never affect wildcards and uses of a type variable * Jesper Steen Moller - Contributions for * Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing *******************************************************************************/ @@ -35,6 +37,7 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.LambdaExpression; +import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.codegen.ConstantPool; @@ -939,7 +942,7 @@ protected void fillInDefaultNonNullness18(AbstractMethodDeclaration sourceMethod int length = this.parameters.length; for (int i = 0; i < length; i++) { TypeBinding parameter = this.parameters[i]; - if (parameter.isBaseType()) + if (!parameter.acceptsNonNullDefault()) continue; long existing = parameter.tagBits & TagBits.AnnotationNullMASK; if (existing == 0L) { @@ -949,7 +952,8 @@ protected void fillInDefaultNonNullness18(AbstractMethodDeclaration sourceMethod if (sourceMethod != null) sourceMethod.arguments[i].binding.type = this.parameters[i]; } - } else if (sourceMethod != null && (parameter.tagBits & TagBits.AnnotationNonNull) != 0) { + } else if (sourceMethod != null && (parameter.tagBits & TagBits.AnnotationNonNull) != 0 + && sourceMethod.arguments[i].hasNullTypeAnnotation()) { sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i); } } @@ -957,9 +961,10 @@ protected void fillInDefaultNonNullness18(AbstractMethodDeclaration sourceMethod this.tagBits |= TagBits.HasParameterAnnotations; } if (this.returnType != null && hasNonNullDefaultFor(DefaultLocationReturnType, true)) { - if (!this.returnType.isBaseType() && (this.returnType.tagBits & TagBits.AnnotationNullMASK) == 0) { + if (this.returnType.acceptsNonNullDefault() && (this.returnType.tagBits & TagBits.AnnotationNullMASK) == 0) { this.returnType = env.createAnnotatedType(this.returnType, new AnnotationBinding[]{env.getNonNullAnnotation()}); - } else if (sourceMethod != null && (this.returnType.tagBits & TagBits.AnnotationNonNull) != 0) { + } else if (sourceMethod instanceof MethodDeclaration && (this.returnType.tagBits & TagBits.AnnotationNonNull) != 0 + && ((MethodDeclaration)sourceMethod).hasNullTypeAnnotation()) { sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/); } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java index 8ba482283..56960dd1d 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java @@ -29,6 +29,7 @@ * Bug 410325 - [1.7][compiler] Generified method override different between javac and eclipse compiler * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault * Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE. + * Bug 440773 - [1.8][null]DefaultLocation.RETURN_TYPE erroneously affects method parameters in @NonNullByDefault *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -90,8 +91,9 @@ void checkConcreteInheritedMethod(MethodBinding concreteMethod, MethodBinding[] if (analyseNullAnnotations && this.type.equals(concreteMethod.declaringClass)) // is currentMethod from the current type? srcMethod = concreteMethod.sourceMethod(); boolean useTypeAnnotations = this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8; - boolean hasNonNullDefault = analyseNullAnnotations && - concreteMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter|Binding.DefaultLocationReturnType, useTypeAnnotations); + boolean hasReturnNonNullDefault = analyseNullAnnotations && concreteMethod.hasNonNullDefaultFor(Binding.DefaultLocationReturnType, useTypeAnnotations); + boolean hasParameterNonNullDefault = analyseNullAnnotations && concreteMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter, useTypeAnnotations); + for (int i = 0, l = abstractMethods.length; i < l; i++) { MethodBinding abstractMethod = abstractMethods[i]; if (concreteMethod.isVarargs() != abstractMethod.isVarargs()) @@ -113,7 +115,7 @@ void checkConcreteInheritedMethod(MethodBinding concreteMethod, MethodBinding[] this.type.addSyntheticBridgeMethod(originalInherited, concreteMethod.original()); } if (analyseNullAnnotations && !concreteMethod.isStatic() && !abstractMethod.isStatic()) { - checkNullSpecInheritance(concreteMethod, srcMethod, hasNonNullDefault, true, abstractMethod, this.type.scope, null); + checkNullSpecInheritance(concreteMethod, srcMethod, hasReturnNonNullDefault, hasParameterNonNullDefault, true, abstractMethod, this.type.scope, null); } } } @@ -413,18 +415,19 @@ void checkAgainstInheritedMethods(MethodBinding currentMethod, MethodBinding[] m if (this.type.equals(currentMethod.declaringClass)) // is currentMethod from the current type? srcMethod = currentMethod.sourceMethod(); boolean useTypeAnnotations = options.sourceLevel >= ClassFileConstants.JDK1_8; - boolean hasNonNullDefault = currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter|Binding.DefaultLocationReturnType, useTypeAnnotations); + boolean hasReturnNonNullDefault = currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationReturnType, useTypeAnnotations); + boolean hasParameterNonNullDefault = currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter, useTypeAnnotations); for (int i = length; --i >= 0;) if (!currentMethod.isStatic() && !methods[i].isStatic()) - checkNullSpecInheritance(currentMethod, srcMethod, hasNonNullDefault, true, methods[i], this.type.scope, null); + checkNullSpecInheritance(currentMethod, srcMethod, hasReturnNonNullDefault, hasParameterNonNullDefault, true, methods[i], this.type.scope, null); } } void checkNullSpecInheritance(MethodBinding currentMethod, AbstractMethodDeclaration srcMethod, - boolean hasNonNullDefault, boolean complain, MethodBinding inheritedMethod, Scope scope, InheritedNonNullnessInfo[] inheritedNonNullnessInfos) + boolean hasReturnNonNullDefault, boolean hasParameterNonNullDefault, boolean complain, MethodBinding inheritedMethod, Scope scope, InheritedNonNullnessInfo[] inheritedNonNullnessInfos) { complain &= !currentMethod.isConstructor(); - if (!hasNonNullDefault && !complain && !this.environment.globalOptions.inheritNullAnnotations) { + if (!hasReturnNonNullDefault && !hasParameterNonNullDefault && !complain && !this.environment.globalOptions.inheritNullAnnotations) { // nothing to be done, take the shortcut currentMethod.tagBits |= TagBits.IsNullnessKnown; return; @@ -435,7 +438,7 @@ void checkNullSpecInheritance(MethodBinding currentMethod, AbstractMethodDeclara { this.buddyImplicitNullAnnotationsVerifier.checkImplicitNullAnnotations(currentMethod, srcMethod, complain, scope); } - super.checkNullSpecInheritance(currentMethod, srcMethod, hasNonNullDefault, complain, inheritedMethod, scope, inheritedNonNullnessInfos); + super.checkNullSpecInheritance(currentMethod, srcMethod, hasReturnNonNullDefault, hasParameterNonNullDefault, complain, inheritedMethod, scope, inheritedNonNullnessInfos); } void reportRawReferences() { @@ -1057,7 +1060,7 @@ public boolean isMethodSubsignature(MethodBinding method, MethodBinding inherite boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { // called when currentMethod's return type is NOT compatible with inheritedMethod's return type - // JLS 3 �8.4.5: more are accepted, with an unchecked conversion + // JLS 3 §8.4.5: more are accepted, with an unchecked conversion if (TypeBinding.equalsEquals(currentMethod.returnType, inheritedMethod.returnType.erasure())) { TypeBinding[] currentParams = currentMethod.parameters; TypeBinding[] inheritedParams = inheritedMethod.parameters; diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NullTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NullTypeBinding.java index 5880f4677..49eb52c1f 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NullTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NullTypeBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 IBM Corporation and others. + * Copyright (c) 2013, 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 @@ -7,6 +7,8 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -25,7 +27,7 @@ public class NullTypeBinding extends BaseTypeBinding { return; // reject misguided attempt. } - public TypeBinding unannotated() { + public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { return this; } }
\ No newline at end of file diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java index e04f9fa9e..74f6d8102 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java @@ -20,6 +20,7 @@ * Bug 418743 - [1.8][null] contradictory annotations on invocation of generic method not reported * Bug 416182 - [1.8][compiler][null] Contradictory null annotations not rejected * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault + * Bug 434602 - Possible error with inferred null annotations leading to contradictory null annotations *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -813,7 +814,7 @@ public class ParameterizedGenericMethodBinding extends ParameterizedMethodBindin // check this variable can be substituted given parameterized type if (originalVariable.rank < length && TypeBinding.equalsEquals(variables[originalVariable.rank], originalVariable)) { TypeBinding substitute = this.typeArguments[originalVariable.rank]; - return originalVariable.hasTypeAnnotations() ? this.environment.createAnnotatedType(substitute, originalVariable.getTypeAnnotations()) : substitute; + return originalVariable.combineTypeAnnotations(substitute); } return originalVariable; } 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 ae8db169b..45b85d059 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 @@ -34,6 +34,8 @@ * Bug 428294 - [1.8][compiler] Type mismatch: cannot convert from List<Object> to Collection<Object[]> * Bug 427199 - [1.8][resource] avoid resource leak warnings on Streams that have no resource * Bug 416182 - [1.8][compiler][null] Contradictory null annotations not rejected + * 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. *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -966,8 +968,27 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi return isRawType(); } - public TypeBinding unannotated() { - return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this; + public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { + if (!hasTypeAnnotations()) + return this; + if (removeOnlyNullAnnotations && !hasNullTypeAnnotations()) + return this; + if (removeOnlyNullAnnotations) { + ReferenceBinding unannotatedGenericType = (ReferenceBinding) this.environment.getUnannotatedType(this.type); + AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations); + TypeBinding[] newArguments = null; + if (this.arguments != null) { + newArguments = new TypeBinding[this.arguments.length]; + for (int i = 0; i < this.arguments.length; i++) { + newArguments[i] = this.arguments[i].unannotated(removeOnlyNullAnnotations); + } + } + ReferenceBinding newEnclosing = null; + if (this.enclosingType != null) + newEnclosing = (ReferenceBinding)this.enclosingType.unannotated(removeOnlyNullAnnotations); + return this.environment.createParameterizedType(unannotatedGenericType, newArguments, newEnclosing, newAnnotations); + } + return this.environment.getUnannotatedType(this); } public int kind() { @@ -1360,7 +1381,7 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi return originalVariable; } TypeBinding substitute = currentType.arguments[originalVariable.rank]; - return originalVariable.hasTypeAnnotations() ? this.environment.createAnnotatedType(substitute, originalVariable.getTypeAnnotations()) : substitute; + return originalVariable.combineTypeAnnotations(substitute); } } // recurse on enclosing type, as it may hold more substitutions to perform diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java index 9be376cc1..78eff9faf 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java @@ -13,6 +13,7 @@ * Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables * Bug 423504 - [1.8] Implement "18.5.3 Functional Interface Parameterization Inference" * Bug 425783 - An internal error occurred during: "Requesting Java AST from selection". java.lang.StackOverflowError + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -79,6 +80,22 @@ public class RawTypeBinding extends ParameterizedTypeBinding { return new RawTypeBinding(this.actualType(), (ReferenceBinding) outerType, this.environment); } + public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { + if (!hasTypeAnnotations()) + return this; + if (removeOnlyNullAnnotations && !hasNullTypeAnnotations()) + return this; + if (removeOnlyNullAnnotations) { + ReferenceBinding unannotatedGenericType = (ReferenceBinding) this.environment.getUnannotatedType(this.genericType()); + AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations); + ReferenceBinding newEnclosing = null; + if (this.enclosingType() != null) + newEnclosing = (ReferenceBinding)this.enclosingType().unannotated(removeOnlyNullAnnotations); + return this.environment.createRawType(unannotatedGenericType, newEnclosing, newAnnotations); + } + return this.environment.getUnannotatedType(this); + } + /** * @see org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding#createParameterizedMethod(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) */ @@ -228,6 +245,9 @@ public class RawTypeBinding extends ParameterizedTypeBinding { } return this.singleAbstractMethod[index]; } + public boolean mentionsAny(TypeBinding[] parameters, int idx) { + return false; + } /** * @see org.eclipse.jdt.internal.compiler.lookup.Binding#readableName() */ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index 01233df1e..cbfe59e20 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -33,6 +33,7 @@ * Bug 418743 - [1.8][null] contradictory annotations on invocation of generic method not reported * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault * Bug 431581 - Eclipse compiles what it should not + * Bug 440759 - [1.8][null] @NonNullByDefault should never affect wildcards and uses of a type variable * Jesper S Moller - Contributions for * bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable @@ -1411,6 +1412,10 @@ int getNullDefault() { return 0; } +public boolean acceptsNonNullDefault() { + return true; +} + public final boolean hasRestrictedAccess() { return (this.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0; } 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 9105cb756..d305327f8 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 @@ -1412,7 +1412,7 @@ public abstract class Scope { if (methodVerifier.areMethodsCompatible(concreteMatch, compatibleMethod)) continue; // can skip this method since concreteMatch overrides it } - if (sourceLevel18) { + if (sourceLevel18 || !(compatibleMethod.isVarargs() && compatibleMethod instanceof ParameterizedGenericMethodBinding)) { for (int j = 0; j < startFoundSize; j++) { MethodBinding classMethod = (MethodBinding) found.elementAt(j); if (classMethod != null && methodVerifier.areMethodsCompatible(classMethod, compatibleMethod)) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index 2133ad4e5..93bc35be3 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -26,7 +26,6 @@ * bug 391376 - [1.8] check interaction of default methods with bridge methods and generics * Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis * Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099 - * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations * Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled * Bug 416172 - [1.8][compiler][null] null type annotation not evaluated on method return type * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings. @@ -34,6 +33,8 @@ * Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault * Bug 432348 - [1.8] Internal compiler error (NPE) after upgrade to 1.8 + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables + * Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E" * Jesper S Moller <jesper@selskabet.org> - Contributions for * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable * Till Brychcy - Contributions for @@ -2307,7 +2308,7 @@ public FieldBinding resolveTypeFor(FieldBinding field) { Annotation [] annotations = fieldDecl.annotations; if (annotations != null && annotations.length != 0) { ASTNode.copySE8AnnotationsToType(initializationScope, field, annotations, - fieldDecl.getKind() != AbstractVariableDeclaration.ENUM_CONSTANT); // type annotation is illegal on enum constant + fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT); // type annotation is illegal on enum constant } Annotation.isTypeUseCompatible(fieldDecl.type, this.scope, annotations); } @@ -2459,7 +2460,7 @@ public MethodBinding resolveTypesFor(MethodBinding method, boolean fromSynthetic if ((resolvedExceptionType.tagBits & TagBits.HasMissingType) != 0) { method.tagBits |= TagBits.HasMissingType; } - if (resolvedExceptionType.hasNullTypeAnnotations()) { + if (exceptionTypes[i].hasNullTypeAnnotation()) { methodDecl.scope.problemReporter().nullAnnotationUnsupportedLocation(exceptionTypes[i]); } method.modifiers |= (resolvedExceptionType.modifiers & ExtraCompilerModifiers.AccGenericSignature); @@ -2657,7 +2658,7 @@ public MethodBinding resolveTypesFor(MethodBinding method, boolean fromSynthetic if (sourceLevel >= ClassFileConstants.JDK1_8 && !method.isVoidMethod()) { Annotation [] annotations = methodDecl.annotations; if (annotations != null && annotations.length != 0) { - ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, methodDecl.annotations, true); + ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, methodDecl.annotations, false); } Annotation.isTypeUseCompatible(returnType, this.scope, methodDecl.annotations); } @@ -3532,7 +3533,14 @@ void verifyMethods(MethodVerifier verifier) { // SH} } -public TypeBinding unannotated() { +public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { + if (removeOnlyNullAnnotations) { + if (!hasNullTypeAnnotations()) + return this; + AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations); + if (newAnnotations.length > 0) + return this.environment.createAnnotatedType(this.prototype, newAnnotations); + } return this.prototype; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticFactoryMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticFactoryMethodBinding.java index 349c0a3db..93849cd01 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticFactoryMethodBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticFactoryMethodBinding.java @@ -36,6 +36,11 @@ public class SyntheticFactoryMethodBinding extends MethodBinding { for (MethodBinding parameterizedMethod : parameterizedType.methods()) { if (parameterizedMethod.original() == this.staticFactoryFor) return (ParameterizedMethodBinding) parameterizedMethod; + if (parameterizedMethod instanceof ProblemMethodBinding) { + MethodBinding closestMatch = ((ProblemMethodBinding)parameterizedMethod).closestMatch; + if (closestMatch instanceof ParameterizedMethodBinding && closestMatch.original() == this.staticFactoryFor) + return (ParameterizedMethodBinding) closestMatch; + } } throw new IllegalArgumentException("Type doesn't have its own method?"); //$NON-NLS-1$ } 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 142a156d1..29da06df1 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 @@ -26,6 +26,8 @@ * Bug 427626 - [1.8] StackOverflow while typing new ArrayList<String>().toArray( and asking for code completion * Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation. * Bug 435962 - [RC2] StackOverFlowError when building + * 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 * Jesper S Moller <jesper@selskabet.org> - Contributions for * bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression *******************************************************************************/ @@ -724,6 +726,13 @@ public boolean isParameterizedType() { public boolean hasNullTypeAnnotations() { return (this.tagBits & TagBits.HasNullTypeAnnotation) != 0; } +/** + * Used to implement this sentence from o.e.j.annotation.DefaultLocation: + * "Wildcards and the use of type variables are always excluded from NonNullByDefault." + */ +public boolean acceptsNonNullDefault() { + return false; +} public boolean isIntersectionCastType() { return false; @@ -1461,16 +1470,17 @@ public TypeBinding original() { case Binding.PARAMETERIZED_TYPE : case Binding.RAW_TYPE : case Binding.ARRAY_TYPE : - return erasure().unannotated(); + return erasure().unannotated(false); default : - return this.unannotated(); + return this.unannotated(false); } } /** * Return this type minus its type annotations + * @param removeOnlyNullAnnotations if true only null type annotations are removed, otherwise all type annotations. */ -public TypeBinding unannotated() { +public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { return this; } 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 59845e32d..ad520b73f 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 @@ -65,7 +65,7 @@ public class TypeBound extends ReductionResult { public boolean equals(Object obj) { if (obj instanceof TypeBound) { TypeBound other = (TypeBound) obj; - return this.left == other.left && TypeBinding.equalsEquals(this.right, other.right) && this.relation == other.relation; //$IDENTITY-COMPARISON$ InferenceVariable + return TypeBinding.equalsEquals(this.left, other.left) && TypeBinding.equalsEquals(this.right, other.right) && this.relation == other.relation; } 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 01da4f297..749f421f5 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 @@ -7,6 +7,8 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for + * Bug 434602 - Possible error with inferred null annotations leading to contradictory null annotations *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -425,6 +427,22 @@ public class TypeSystem { } return cacheDerivedType(keyType, new IntersectionCastTypeBinding(intersectingTypes, this.environment)); } + + /** + * If a TVB was created with a dummy declaring element and needs to be fixed now, + * make sure that this update affects all early clones, too. + */ + public void fixTypeVariableDeclaringElement(TypeVariableBinding var, Binding declaringElement) { + int id = var.id; + if (id < this.typeid && this.types[id] != null) { + for (TypeBinding t : this.types[id]) { + if (t instanceof TypeVariableBinding) + ((TypeVariableBinding)t).declaringElement = declaringElement; + } + } else { + var.declaringElement = declaringElement; + } + } //{ObjectTeams: compare role types: boolean isRoleTypeMatch(ITeamAnchor teamAnchor, int valueParamPosition, TypeBinding cachedType) { 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 b853a8a54..6ae69c83d 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 @@ -24,6 +24,11 @@ * Bug 431269 - [1.8][compiler][null] StackOverflow in nullAnnotatedReadableName * Bug 431408 - Java 8 (1.8) generics bug * Bug 435962 - [RC2] StackOverFlowError when building + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables + * Bug 438250 - [1.8][null] NPE trying to report bogus null annotation conflict + * Bug 438179 - [1.8][null] 'Contradictory null annotations' error on type variable with explicit null-annotation. + * Bug 440143 - [1.8][null] one more case of contradictory null annotations regarding type variables + * Bug 440759 - [1.8][null] @NonNullByDefault should never affect wildcards and uses of a type variable *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -829,7 +834,16 @@ public class TypeVariableBinding extends ReferenceBinding { } public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNullAnnotations) { - this.environment.getUnannotatedType(this); // exposes original TVB/capture to type system for id stamping purposes. + if (getClass() == TypeVariableBinding.class) { + // TVB only: if the declaration already carries type annotations, + // clone the unannotated binding first to ensure TypeSystem.getUnnanotatedType() will see it at position 0: + TypeBinding unannotated = clone(null); + this.environment.getUnannotatedType(unannotated); // register unannotated + this.id = unannotated.id; // transfer fresh id + this.environment.typeSystem.cacheDerivedType(this, unannotated, this); // register this + } else { + this.environment.getUnannotatedType(this); // exposes original TVB/capture to type system for id stamping purposes. + } super.setTypeAnnotations(annotations, evalNullAnnotations); } /** @@ -909,9 +923,19 @@ public class TypeVariableBinding extends ReferenceBinding { return readableName; } - // May still carry declaration site annotations. - public TypeBinding unannotated() { - return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this; + public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { + if (!hasTypeAnnotations()) + return this; + if (removeOnlyNullAnnotations && !hasNullTypeAnnotations()) + return this; + TypeBinding unannotated = this.environment.getUnannotatedType(this); + if (removeOnlyNullAnnotations) { + AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(this.typeAnnotations); + if (newAnnotations.length > 0) + return this.environment.createAnnotatedType(unannotated, newAnnotations); + // FIXME: selectively keep type annotations on bounds + } + return unannotated; } /** * Upper bound doesn't perform erasure @@ -931,11 +955,7 @@ public class TypeVariableBinding extends ReferenceBinding { if (nullTagBits == 0L) { nullTagBits |= superNullTagBits; } else if (superNullTagBits != nullTagBits) { - // not finding either bound or ann should be considered a compiler bug - TypeReference bound = findBound(this.firstBound, parameter); - Annotation ann = bound.findAnnotation(superNullTagBits); - scope.problemReporter().contradictoryNullAnnotationsOnBounds(ann, nullTagBits); - this.tagBits &= ~TagBits.AnnotationNullMASK; + this.firstBound = nullMismatchOnBound(parameter, this.firstBound, superNullTagBits, nullTagBits, scope); } } } @@ -949,11 +969,7 @@ public class TypeVariableBinding extends ReferenceBinding { if (nullTagBits == 0L) { nullTagBits |= superNullTagBits; } else if (superNullTagBits != nullTagBits) { - // not finding either bound or ann should be considered a compiler bug - TypeReference bound = findBound(this.firstBound, parameter); - Annotation ann = bound.findAnnotation(superNullTagBits); - scope.problemReporter().contradictoryNullAnnotationsOnBounds(ann, nullTagBits); - this.tagBits &= ~TagBits.AnnotationNullMASK; + interfaces[i] = (ReferenceBinding) nullMismatchOnBound(parameter, resolveType, superNullTagBits, nullTagBits, scope); } } interfaces[i] = resolveType; @@ -962,6 +978,20 @@ public class TypeVariableBinding extends ReferenceBinding { if (nullTagBits != 0) this.tagBits |= nullTagBits | TagBits.HasNullTypeAnnotation; } + private TypeBinding nullMismatchOnBound(TypeParameter parameter, TypeBinding boundType, long superNullTagBits, long nullTagBits, Scope scope) { + // not finding bound should be considered a compiler bug + TypeReference bound = findBound(boundType, parameter); + Annotation ann = bound.findAnnotation(superNullTagBits); + if (ann != null) { + // explicit annotation: error + scope.problemReporter().contradictoryNullAnnotationsOnBounds(ann, nullTagBits); + this.tagBits &= ~TagBits.AnnotationNullMASK; + } else { + // implicit annotation: let the new one override + return boundType.unannotated(true); + } + return boundType; + } private TypeReference findBound(TypeBinding bound, TypeParameter parameter) { if (parameter.type != null && TypeBinding.equalsEquals(parameter.type.resolvedType, bound)) return parameter.type; @@ -1019,4 +1049,38 @@ public class TypeVariableBinding extends ReferenceBinding { } return superInterfaces; } + + public TypeBinding combineTypeAnnotations(TypeBinding substitute) { + if (hasTypeAnnotations()) { + // may need to merge annotations from the original variable and from substitution: + if (hasRelevantTypeUseNullAnnotations()) { + // explicit type use null annotation overrides any annots on type parameter and concrete type arguments + substitute = substitute.unannotated(true); + } + if (this.typeAnnotations != Binding.NO_ANNOTATIONS) + return this.environment.createAnnotatedType(substitute, this.typeAnnotations); + // annots on originalVariable not relevant, and substitute has annots, keep substitute unmodified: + } + return substitute; + } + + private boolean hasRelevantTypeUseNullAnnotations() { + TypeVariableBinding[] parameters; + if (this.declaringElement instanceof ReferenceBinding) { + parameters = ((ReferenceBinding)this.declaringElement).original().typeVariables(); + } else if (this.declaringElement instanceof MethodBinding) { + parameters = ((MethodBinding)this.declaringElement).original().typeVariables; + } else { + throw new IllegalStateException("Unexpected declaring element:"+String.valueOf(this.declaringElement.readableName())); //$NON-NLS-1$ + } + TypeVariableBinding parameter = parameters[this.rank]; + // recognize explicit annots by their effect on null tag bits, if there's no effect, then the annot is not considered relevant + long currentNullBits = this.tagBits & TagBits.AnnotationNullMASK; + long declarationNullBits = parameter.tagBits & TagBits.AnnotationNullMASK; + return (currentNullBits & ~declarationNullBits) != 0; + } + + public boolean acceptsNonNullDefault() { + return false; + } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VoidTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VoidTypeBinding.java index 5fdbc1a01..3ad8be42c 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VoidTypeBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/VoidTypeBinding.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2013 IBM Corporation and others. + * Copyright (c) 2013, 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 @@ -7,6 +7,8 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Stephan Herrmann - Contribution for + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -25,7 +27,7 @@ public class VoidTypeBinding extends BaseTypeBinding { return; // reject misguided attempt. } - public TypeBinding unannotated() { + public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { return this; } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java index ef9484cf9..7d2cce697 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java @@ -19,6 +19,8 @@ * Bug 427411 - [1.8][generics] JDT reports type mismatch when using method that returns generic type * Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation. * Bug 435962 - [RC2] StackOverFlowError when building + * 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 *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -933,8 +935,24 @@ public class WildcardBinding extends ReferenceBinding { return this.typeVariable; } - public TypeBinding unannotated() { - return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this; + public TypeBinding unannotated(boolean removeOnlyNullAnnotations) { + if (!hasTypeAnnotations()) + return this; + if (removeOnlyNullAnnotations && !hasNullTypeAnnotations()) + return this; + ReferenceBinding unannotatedGenericType = (ReferenceBinding) this.genericType.unannotated(removeOnlyNullAnnotations); + if (removeOnlyNullAnnotations) { + // cf. structure of uncapture(): + TypeBinding unannotatedBound = this.bound != null ? this.bound.unannotated(removeOnlyNullAnnotations) : null; + int length = 0; + TypeBinding [] unannotatedOtherBounds = this.otherBounds == null ? null : new TypeBinding[length = this.otherBounds.length]; + for (int i = 0; i < length; i++) { + unannotatedOtherBounds[i] = this.otherBounds[i] == null ? null : this.otherBounds[i].unannotated(removeOnlyNullAnnotations); + } + AnnotationBinding[] newAnnotations = this.environment.filterNullTypeAnnotations(getTypeAnnotations()); + return this.environment.createWildcard(unannotatedGenericType, this.rank, unannotatedBound, unannotatedOtherBounds, this.boundKind, newAnnotations); + } + return unannotatedGenericType; } @Override public TypeBinding uncapture(Scope scope) { @@ -961,15 +979,26 @@ public class WildcardBinding extends ReferenceBinding { } @Override public boolean mentionsAny(TypeBinding[] parameters, int idx) { - if (super.mentionsAny(parameters, idx)) - return true; - if (this.bound != null && this.bound.mentionsAny(parameters, -1)) - return true; - if (this.otherBounds != null) { - for (int i = 0, length = this.otherBounds.length; i < length; i++) - if (this.otherBounds[i].mentionsAny(parameters, -1)) - return true; + if (this.inRecursiveFunction) + return false; + this.inRecursiveFunction = true; + try { + if (super.mentionsAny(parameters, idx)) + return true; + if (this.bound != null && this.bound.mentionsAny(parameters, -1)) + return true; + if (this.otherBounds != null) { + for (int i = 0, length = this.otherBounds.length; i < length; i++) + if (this.otherBounds[i].mentionsAny(parameters, -1)) + return true; + } + } finally { + this.inRecursiveFunction = false; } return false; } + + public boolean acceptsNonNullDefault() { + return false; + } } 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 b62c2d496..bebcdc31c 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 @@ -10120,6 +10120,11 @@ protected void consumeLambdaExpression() { } this.referenceContext.compilationResult().hasFunctionalTypes = true; markEnclosingMemberWithLocalOrFunctionalType(LocalTypeKind.LAMBDA); + if (lexp.compilationResult.getCompilationUnit() == null) { + // unit built out of model. Stash a textual representation of lambda to enable LE.copy(). + int length = lexp.sourceEnd - lexp.sourceStart + 1; + System.arraycopy(this.scanner.getSource(), lexp.sourceStart, lexp.text = new char [length], 0, length); + } } protected Argument typeElidedArgument() { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java index 5a85fd6ca..81466874a 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/RecoveredElement.java @@ -15,7 +15,7 @@ package org.eclipse.jdt.internal.compiler.parser; /** * Internal structure for parsing recovery */ -import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; 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 a5f398391..fbda4b7b0 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 @@ -52,6 +52,9 @@ * Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE. * Bug 430150 - [1.8][null] stricter checking against type variables * Bug 434600 - Incorrect null analysis error reporting on type parameters + * Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type + * Bug 438467 - [compiler][null] Better error position for "The method _ cannot implement the corresponding method _ due to incompatible nullness constraints" + * Bug 439298 - [null] "Missing code implementation in the compiler" when using @NonNullByDefault in package-info.java * Jesper S Moller <jesper@selskabet.org> - Contributions for * bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression * bug 382721 - [1.8][compiler] Effectively final variables needs special treatment @@ -288,6 +291,7 @@ public static int getIrritant(int problemID) { return CompilerOptions.UnusedLocalVariable; case IProblem.ArgumentIsNeverUsed : + case IProblem.ExceptionParameterIsNeverUsed: return CompilerOptions.UnusedArgument; case IProblem.NoImplicitStringConversionForCharArrayExpression : @@ -4038,6 +4042,10 @@ public void invalidConstructor(Statement statement, MethodBinding targetConstruc statement.sourceStart, statement.sourceEnd); return; + case ProblemReasons.ContradictoryNullAnnotations: + problemConstructor = (ProblemMethodBinding) targetConstructor; + contradictoryNullAnnotationsInferred(problemConstructor.closestMatch, statement); + return; case ProblemReasons.NoError : // 0 default : needImplementation(statement); // want to fail to see why we were here... @@ -8454,6 +8462,14 @@ public void typeHiding(TypeParameter typeParam, Binding hidden) { typeParam.sourceStart, typeParam.sourceEnd); } +public void notAnnotationType(TypeBinding actualType, ASTNode location) { + this.handle( + IProblem.NotAnnotationType, + new String[] {new String(actualType.leafComponentType().readableName())}, + new String[] {new String(actualType.leafComponentType().shortReadableName())}, + location.sourceStart, + location.sourceEnd); +} public void typeMismatchError(TypeBinding actualType, TypeBinding expectedType, ASTNode location, ASTNode expectingLocation) { if (this.options.sourceLevel < ClassFileConstants.JDK1_5) { // don't expose type variable names, complain on erased types if (actualType instanceof TypeVariableBinding) @@ -9253,6 +9269,18 @@ public void unusedArgument(LocalDeclaration localDecl) { localDecl.sourceStart, localDecl.sourceEnd); } +public void unusedExceptionParameter(LocalDeclaration exceptionParameter) { + int severity = computeSeverity(IProblem.ExceptionParameterIsNeverUsed); + if (severity == ProblemSeverities.Ignore) return; + String[] arguments = new String[] {new String(exceptionParameter.name)}; + this.handle( + IProblem.ExceptionParameterIsNeverUsed, + arguments, + arguments, + severity, + exceptionParameter.sourceStart, + exceptionParameter.sourceEnd); +} public void unusedDeclaredThrownException(ReferenceBinding exceptionType, AbstractMethodDeclaration method, ASTNode location) { boolean isConstructor = method.isConstructor(); int severity = computeSeverity(isConstructor ? IProblem.UnusedConstructorDeclaredThrownException : IProblem.UnusedMethodDeclaredThrownException); @@ -13661,7 +13689,28 @@ public void parameterLackingNonnullAnnotation(Argument argument, ReferenceBindin sourceStart, sourceEnd); } +public void illegalParameterRedefinition(Argument argument, ReferenceBinding declaringClass, TypeBinding inheritedParameter) { + int sourceStart = argument.type.sourceStart; + if (argument.annotations != null) { + for (int i=0; i<argument.annotations.length; i++) { + Annotation annotation = argument.annotations[i]; + if ( annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNullable + || annotation.resolvedType.id == TypeIds.T_ConfiguredAnnotationNonNull) + { + sourceStart = annotation.sourceStart; + break; + } + } + } + this.handle( + IProblem.IllegalParameterNullityRedefinition, + new String[] { new String(argument.name), new String(declaringClass.readableName()), new String(inheritedParameter.nullAnnotatedReadableName(this.options, false)) }, + new String[] { new String(argument.name), new String(declaringClass.shortReadableName()), new String(inheritedParameter.nullAnnotatedReadableName(this.options, true)) }, + sourceStart, + argument.type.sourceEnd); +} public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDecl, MethodBinding inheritedMethod, char[][] nonNullAnnotationName) { + // nonNullAnnotationName is not used in 1.8-mode MethodDeclaration methodDecl = (MethodDeclaration) abstractMethodDecl; StringBuffer methodSignature = new StringBuffer(); methodSignature @@ -13680,12 +13729,31 @@ public void illegalReturnRedefinition(AbstractMethodDeclaration abstractMethodDe if (annotation != null) { sourceStart = annotation.sourceStart; } + TypeBinding inheritedReturnType = inheritedMethod.returnType; + String[] arguments; + String[] argumentsShort; + if (this.options.complianceLevel < ClassFileConstants.JDK1_8) { + StringBuilder returnType = new StringBuilder(); + returnType.append('@').append(CharOperation.concatWith(nonNullAnnotationName, '.')); + returnType.append(' ').append(inheritedReturnType.readableName()); + arguments = new String[] { methodSignature.toString(), returnType.toString() }; + + returnType = new StringBuilder(); + returnType.append('@').append(nonNullAnnotationName[nonNullAnnotationName.length-1]); + returnType.append(' ').append(inheritedReturnType.shortReadableName()); + argumentsShort = new String[] { shortSignature.toString(), returnType.toString() }; + } else { + arguments = new String[] { methodSignature.toString(), + String.valueOf(inheritedReturnType.nullAnnotatedReadableName(this.options, false))}; + argumentsShort = new String[] { shortSignature.toString(), + String.valueOf(inheritedReturnType.nullAnnotatedReadableName(this.options, true))}; + } this.handle( - IProblem.IllegalReturnNullityRedefinition, - new String[] { methodSignature.toString(), CharOperation.toString(nonNullAnnotationName)}, - new String[] { shortSignature.toString(), new String(nonNullAnnotationName[nonNullAnnotationName.length-1])}, - sourceStart, - methodDecl.returnType.sourceEnd); + IProblem.IllegalReturnNullityRedefinition, + arguments, + argumentsShort, + sourceStart, + methodDecl.returnType.sourceEnd); } public void referenceExpressionArgumentNullityMismatch(ReferenceExpression location, TypeBinding requiredType, TypeBinding providedType, MethodBinding descriptorMethod, int idx, NullAnnotationMatching status) { @@ -14159,6 +14227,13 @@ public void nullityMismatchTypeArgument(TypeBinding typeVariable, TypeBinding ty location.sourceEnd); } +public void implicitObjectBoundNoNullDefault(TypeReference reference) { + this.handle(IProblem.ImplicitObjectBoundNoNullDefault, + NoArgument, NoArgument, + ProblemSeverities.Warning, + reference.sourceStart, reference.sourceEnd); +} + public void dereferencingNullableExpression(Expression expression) { if (expression instanceof MessageSend) { MessageSend send = (MessageSend) expression; 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 0d8f5b753..07f258500 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 @@ -41,6 +41,8 @@ # Bug 392245 - [1.8][compiler][null] Define whether / how @NonNullByDefault applies to TYPE_USE locations # Bug 430150 - [1.8][null] stricter checking against type variables # Bug 434600 - Incorrect null analysis error reporting on type parameters +# Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type +# Bug 438467 - [compiler][null] Better error position for "The method _ cannot implement the corresponding method _ due to incompatible nullness constraints" # Jesper S Moller <jesper@selskabet.org> - Contributions for # bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression # bug 384567 - [1.5][compiler] Compiler accepts illegal modifiers on package declaration @@ -76,6 +78,7 @@ 31 = The member enum {0} can only be defined inside a top-level class or interface or in a static context 32 = The member enum {0} must be defined inside a static member type 33 = The type {0} is hiding the type {1} +34 = {0} is not an annotation type 50 = {0} cannot be resolved 51 = The local variable {0} may not have been initialized @@ -112,6 +115,7 @@ 82 = The final field {0} may already have been assigned 83 = {0} cannot be resolved to a variable 84 = This static method of interface {0} can only be accessed as {0}.{1} +85 = The value of the exception parameter {0} is not used 90 = The local variable {0} is hiding another local variable defined in an enclosing scope 91 = The local variable {0} is hiding a field from type {1} @@ -773,7 +777,7 @@ 911 = Null type mismatch: required ''{0}'' but the provided value is inferred as @{1} 912 = Null type safety: The expression of type ''{0}'' needs unchecked conversion to conform to ''{1}'' 913 = A default nullness annotation has not been specified for the package {0} -914 = The return type is incompatible with the @{1} return from {0} +914 = The return type is incompatible with ''{1}'' returned from {0} (mismatching null constraints) 915 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as @{2} 916 = Illegal redefinition of parameter {0}, inherited method from {1} does not constrain this parameter 917 = Missing non-null annotation: inherited method from {0} specifies this parameter as @{1} @@ -823,6 +827,8 @@ #968 temporary warning has been removed 969 = Null type mismatch (type annotations): ''null'' is not compatible to the free type variable ''{0}'' 970 = Null type mismatch (type annotations): required ''{0}'' but this expression has type ''{1}'', where ''{0}'' is a free type variable +971 = The explicit type bound 'Object' is not affected by the nullness default for DefaultLocation.TYPE_BOUND. +972 = Illegal redefinition of parameter {0}, inherited method from {1} declares this parameter as ''{2}'' (mismatching null constraints) # Java 8 1001 = Syntax error, modifiers and annotations are not allowed for the lambda parameter {0} as its type is elided diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java index c1c23b493..6235afe0e 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java @@ -9,6 +9,8 @@ * IBM Corporation - initial API and implementation * Fraunhofer FIRST - extended API and implementation * Technical University Berlin - extended API and implementation + * Stephan Herrmann - Contribution for + * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables *******************************************************************************/ package org.eclipse.jdt.core.dom; @@ -27,6 +29,7 @@ import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding; import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; +import org.eclipse.jdt.internal.compiler.lookup.IntersectionCastTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodBinding; import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; @@ -532,7 +535,7 @@ class TypeBinding implements ITypeBinding { public ITypeBinding getTypeDeclaration() { if (this.binding instanceof ParameterizedTypeBinding) return this.resolver.getTypeBinding(((ParameterizedTypeBinding)this.binding).genericType()); - return this.resolver.getTypeBinding(this.binding.unannotated()); + return this.resolver.getTypeBinding(this.binding.unannotated(false)); } /* (non-Javadoc) @@ -796,6 +799,10 @@ class TypeBinding implements ITypeBinding { buffer.append(brackets); return String.valueOf(buffer); + case Binding.INTERSECTION_CAST_TYPE : + // just use the first bound for now (same kludge as in IntersectionCastTypeBinding#constantPoolName()) + return new String(((IntersectionCastTypeBinding) this.binding).getIntersectingTypes()[0].sourceName()); + default : if (isPrimitive() || isNullType()) { BaseTypeBinding baseTypeBinding = (BaseTypeBinding) this.binding; @@ -1293,7 +1300,7 @@ class TypeBinding implements ITypeBinding { return false; } org.eclipse.jdt.internal.compiler.lookup.TypeBinding otherBinding = ((TypeBinding) other).binding; - if (org.eclipse.jdt.internal.compiler.lookup.TypeBinding.equalsEquals(otherBinding.unannotated(), this.binding.unannotated())) { + if (org.eclipse.jdt.internal.compiler.lookup.TypeBinding.equalsEquals(otherBinding.unannotated(false), this.binding.unannotated(false))) { return true; } // check return type diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/SourceRangeVerifier.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/SourceRangeVerifier.java index edcbde688..f13a31bd3 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/SourceRangeVerifier.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/SourceRangeVerifier.java @@ -18,7 +18,7 @@ import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
-@SuppressWarnings("rawtypes") +@SuppressWarnings("rawtypes")
public class SourceRangeVerifier extends ASTVisitor {
public static boolean DEBUG = false;
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java index 096876ef5..1023e418a 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/core/formatter/DefaultCodeFormatterConstants.java @@ -3625,7 +3625,7 @@ public class DefaultCodeFormatterConstants { * FORMATTER / Option to specify the length of the page. Beyond this length, the formatter will try to split the code * - option id: "org.eclipse.jdt.core.formatter.lineSplit" * - possible values: "<n>", where n is zero or a positive integer - * - default: "80" + * - default: "120" * </pre> * @since 3.0 */ @@ -4036,7 +4036,9 @@ public class DefaultCodeFormatterConstants { * @since 3.0 */ public static Map getEclipse21Settings() { - return DefaultCodeFormatterOptions.getDefaultSettings().getMap(); + DefaultCodeFormatterOptions options = DefaultCodeFormatterOptions.getDefaultSettings(); + options.page_width = 80; // changed with bug 356841 + return options.getMap(); } /** diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java index 9a1a40500..da2d3cebd 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/DefaultCodeFormatterOptions.java @@ -2059,9 +2059,9 @@ public class DefaultCodeFormatterOptions { try { this.page_width = Integer.parseInt((String) pageWidthOption); } catch (NumberFormatException e) { - this.page_width = 80; + this.page_width = 120; } catch(ClassCastException e) { - this.page_width = 80; + this.page_width = 120; } } final Object useTabOption = settings.get(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR); @@ -2492,7 +2492,7 @@ public class DefaultCodeFormatterOptions { this.join_wrapped_lines = true; this.put_empty_statement_on_new_line = false; this.tab_size = 4; - this.page_width = 80; + this.page_width = 120; this.tab_char = TAB; // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=49081 this.use_tabs_only_for_leading_indentations = false; this.wrap_before_binary_operator = true; @@ -2787,7 +2787,7 @@ public class DefaultCodeFormatterOptions { this.join_wrapped_lines = true; this.put_empty_statement_on_new_line = true; this.tab_size = 8; - this.page_width = 80; + this.page_width = 120; this.tab_char = MIXED; this.use_tabs_only_for_leading_indentations = false; this.wrap_before_binary_operator = true; diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java index 5e612beba..7a10ac261 100644 --- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java +++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java @@ -1146,14 +1146,17 @@ public class Scribe implements IJavaDocTagConstants { if (linesCount > length) { System.arraycopy(this.newEmptyLines, 0, this.newEmptyLines = new String[linesCount+10], 0, length); } - String newLineString = this.newEmptyLines[linesCount-1]; - if (newLineString == null) { - this.tempBuffer.setLength(0); - for (int j=0; j<linesCount; j++) { - this.tempBuffer.append(this.lineSeparator); + String newLineString = Util.EMPTY_STRING; + if (linesCount > 0) { + newLineString = this.newEmptyLines[linesCount-1]; + if (newLineString == null) { + this.tempBuffer.setLength(0); + for (int j=0; j<linesCount; j++) { + this.tempBuffer.append(this.lineSeparator); + } + newLineString = this.tempBuffer.toString(); + this.newEmptyLines[linesCount-1] = newLineString; } - newLineString = this.tempBuffer.toString(); - this.newEmptyLines[linesCount-1] = newLineString; } return newLineString; } diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java index 1c871ba99..beed86a1e 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/TypeVector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2009 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 @@ -52,9 +52,25 @@ public void addAll(IType[] newElements) { this.size += newElements.length; } public boolean contains(IType element) { - for (int i = this.size; --i >= 0;) - if (element.equals(this.elements[i])) + for (int i = this.size; --i >= 0;) { + /* Note: When creating new subtypes of RST, need to check whether this code + * which gives special treatment to lambda needs modification or not - refer to bug 436139 + * An alternate could have been the following: + * if (element.equals(this.elements[i) && this.elements[i].equals(element)) return true; + * but the above has the issue of repeating the steps in most of the cases. + */ + IType firstElement = null; + IType secondElement = null; + if (element.isLambda()) { + firstElement = element; + secondElement = this.elements[i]; + } else { + firstElement = this.elements[i]; + secondElement = element; + } + if (firstElement.equals(secondElement)) return true; + } return false; } public TypeVector copy() { diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java index 4e67ba2ee..5db5a3852 100644 --- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java +++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java @@ -1575,14 +1575,14 @@ public class Disassembler extends ClassFileBytesDisassembler { private String bootstrapMethodDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool) { // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html // The BootstrapMethods attribute records bootstrap method specifiers referenced by invokedynamic instructions. - // The value of the bootstrap_method_ref item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_MethodHandle_info structure (�4.4.8). + // The value of the bootstrap_method_ref item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_MethodHandle_info structure (§4.4.8). // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8 // constantpoolentry.getKind() = IConstantPoolConstant.CONSTANT_MethodHandle ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPool.decodeEntry(entry.getBootstrapMethodReference()); // The reference_kind item of the CONSTANT_MethodHandle_info structure should have the value 6 (REF_invokeStatic) or 8 (REF_newInvokeSpecial) - // (�5.4.3.5) or else invocation of the bootstrap method handle during call site specifier resolution for an invokedynamic instruction will complete abruptly. + // (§5.4.3.5) or else invocation of the bootstrap method handle during call site specifier resolution for an invokedynamic instruction will complete abruptly. // If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), // or 9 (REF_invokeInterface), the name of the method represented by a CONSTANT_Methodref_info structure must not be <init> or <clinit>. @@ -1601,7 +1601,7 @@ public class Disassembler extends ClassFileBytesDisassembler { // Each entry in the bootstrap_arguments array must be a valid index into the constant_pool table. // The constant_pool entry at that index must be a CONSTANT_String_info, CONSTANT_Class_info, CONSTANT_Integer_info // CONSTANT_Long_info, CONSTANT_Float_info, CONSTANT_Double_info, CONSTANT_MethodHandle_info, or - // CONSTANT_MethodType_info structure (�4.4.3, �4.4.1, �4.4.4, �4.4.5), �4.4.8, �4.4.9). + // CONSTANT_MethodType_info structure (§4.4.3, §4.4.1, §4.4.4, §4.4.5), §4.4.8, §4.4.9). if (entry.getBootstrapArguments().length == 0) return null; int[] bootstrapArguments = entry.getBootstrapArguments(); @@ -1616,8 +1616,8 @@ public class Disassembler extends ClassFileBytesDisassembler { // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8 // If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), // 7 (REF_invokeSpecial), or 8 (REF_newInvokeSpecial), then the constant_pool entry at that - // index must be a CONSTANT_Methodref_info structure (�4.4.2) representing a class's method or - // constructor (�2.9) for which a method handle is to be created. + // index must be a CONSTANT_Methodref_info structure (§4.4.2) representing a class's method or + // constructor (§2.9) for which a method handle is to be created. ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPoolEntry; StringBuilder builder = new StringBuilder(10); switch(constantPoolEntry2.getReferenceKind()) { diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml index afab9ca37..b4dbbf6a5 100644 --- a/org.eclipse.jdt.core/pom.xml +++ b/org.eclipse.jdt.core/pom.xml @@ -14,11 +14,11 @@ <parent> <artifactId>eclipse.jdt.core</artifactId> <groupId>eclipse.jdt.core</groupId> - <version>4.4.0-SNAPSHOT</version> + <version>4.5.0-SNAPSHOT</version> </parent> <groupId>org.eclipse.jdt</groupId> <artifactId>org.eclipse.jdt.core</artifactId> - <version>3.10.0-SNAPSHOT</version> + <version>3.11.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <properties> @@ -39,7 +39,7 @@ <include name="org/eclipse/jdt/internal/compiler/batch/messages.properties"/> </replace> <replace token="bundle_version" value="${unqualifiedVersion}" dir="${project.build.directory}/classes"> - <include name="org/eclipse/jdt/internal/compiler/batch/messages.properties" /> + <include name="org/eclipse/jdt/internal/compiler/batch/messages.properties"/> </replace> </tasks> </configuration> diff --git a/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF index 46955781b..2fa22c5f5 100644 --- a/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Eclipse Compiler for Java(TM) Bundle-SymbolicName: org.eclipse.jdt.core.compiler.batch -Bundle-Version: 3.10.0.qualifier +Bundle-Version: 3.11.0.qualifier Bundle-ClassPath: . Bundle-Vendor: Eclipse.org Export-Package: org.eclipse.jdt.core, diff --git a/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF index d50abcb82..783aecc66 100644 --- a/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF +++ b/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF @@ -1,7 +1,6 @@ Bundle-ManifestVersion: 2 Bundle-Name: Source of Eclipse Compiler for Java(TM) Bundle-SymbolicName: org.eclipse.jdt.core.compiler.batch.source -Bundle-Version: 3.10.0.qualifier -Main-Class: org.eclipse.jdt.internal.compiler.batch.Main +Bundle-Version: 3.11.0.qualifier Bundle-Vendor: Eclipse.org -Eclipse-SourceBundle: org.eclipse.jdt.core.compiler.batch;version="3.10.0.${buildQualifier}";roots:="." +Eclipse-SourceBundle: org.eclipse.jdt.core.compiler.batch;version="3.11.0.${buildQualifier}";roots:="." diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java index 6eedd419a..a79d15bbc 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/DiskIndex.java @@ -62,6 +62,7 @@ private static final int DELETED = -2; private static final int CHUNK_SIZE = 100; private static final SimpleSetOfCharArray INTERNED_CATEGORY_NAMES = new SimpleSetOfCharArray(20); +private static final String TMP_EXT = ".tmp"; //$NON-NLS-1$ static class IntList { @@ -254,6 +255,7 @@ private void cacheDocumentNames() throws IOException { throw e; } finally { stream.close(); + this.indexLocation.close(); this.streamBuffer = null; BUFFER_READ_SIZE = DEFAULT_BUFFER_SIZE; } @@ -400,6 +402,7 @@ void initialize(boolean reuseExistingFile) throws IOException { } } finally { stream.close(); + this.indexLocation.close(); } return; } @@ -526,8 +529,16 @@ DiskIndex mergeWith(MemoryIndex memoryIndex) throws IOException { newDiskIndex.initialize(false); return newDiskIndex; } + boolean usingTmp = false; File oldIndexFile = this.indexLocation.getIndexFile(); - DiskIndex newDiskIndex = new DiskIndex(new FileIndexLocation(new File(oldIndexFile.getPath() + ".tmp"))); //$NON-NLS-1$ + String indexFilePath = oldIndexFile.getPath(); + if (indexFilePath.endsWith(TMP_EXT)) { // the tmp file could not be renamed last time + indexFilePath = indexFilePath.substring(0, indexFilePath.length()-TMP_EXT.length()); + usingTmp = true; + } else { + indexFilePath += TMP_EXT; + } + DiskIndex newDiskIndex = new DiskIndex(new FileIndexLocation(new File(indexFilePath))); File newIndexFile = newDiskIndex.indexLocation.getIndexFile(); try { newDiskIndex.initializeFrom(this, newIndexFile); @@ -568,10 +579,18 @@ DiskIndex mergeWith(MemoryIndex memoryIndex) throws IOException { System.out.println("mergeWith - Failed to delete " + this.indexLocation); //$NON-NLS-1$ throw new IOException("Failed to delete index file " + this.indexLocation); //$NON-NLS-1$ } - if (!newIndexFile.renameTo(oldIndexFile)) { - if (DEBUG) - System.out.println("mergeWith - Failed to rename " + this.indexLocation); //$NON-NLS-1$ - throw new IOException("Failed to rename index file " + this.indexLocation); //$NON-NLS-1$ + if (!usingTmp && !newIndexFile.renameTo(oldIndexFile)) { + // try again after waiting for two milli secs + try { + Thread.sleep(2); + } catch (InterruptedException e) { + //ignore + } + if (!newIndexFile.renameTo(oldIndexFile)) { + if (DEBUG) + System.out.println("mergeWith - Failed to rename " + this.indexLocation); //$NON-NLS-1$ + usingTmp = true; + } } } catch (IOException e) { if (newIndexFile.exists() && !newIndexFile.delete()) @@ -580,7 +599,8 @@ DiskIndex mergeWith(MemoryIndex memoryIndex) throws IOException { throw e; } - newDiskIndex.indexLocation = this.indexLocation; + if (!usingTmp) // rename done, use the new file + newDiskIndex.indexLocation = this.indexLocation; return newDiskIndex; } private synchronized String[] readAllDocumentNames() throws IOException { @@ -601,6 +621,7 @@ private synchronized String[] readAllDocumentNames() throws IOException { return docNames; } finally { stream.close(); + this.indexLocation.close(); this.streamBuffer = null; } } @@ -689,6 +710,7 @@ private synchronized HashtableOfObject readCategoryTable(char[] categoryName, bo throw ioe; } finally { stream.close(); + this.indexLocation.close(); } if (matchingWords != null && count > 0) { @@ -705,6 +727,7 @@ private synchronized HashtableOfObject readCategoryTable(char[] categoryName, bo throw ioe; } finally { stream.close(); + this.indexLocation.close(); } } this.streamBuffer = null; @@ -758,6 +781,7 @@ synchronized String readDocumentName(int docNumber) throws IOException { throw ioe; } finally { file.close(); + this.indexLocation.close(); } int numberOfNames = isLastChunk ? this.sizeOfLastChunk : CHUNK_SIZE; chunk = new String[numberOfNames]; @@ -787,6 +811,7 @@ synchronized int[] readDocumentNumbers(Object arrayOffset) throws IOException { return readStreamDocumentArray(stream, readStreamInt(stream)); } finally { stream.close(); + this.indexLocation.close(); this.streamBuffer = null; } } diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java index a93a26498..8898670fd 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/index/JarIndexLocation.java @@ -59,6 +59,7 @@ public class JarIndexLocation extends IndexLocation { try { if (this.jarFile == null) { JarURLConnection connection = (JarURLConnection) this.localUrl.openConnection(); + connection.setUseCaches(false); JarFile file = connection.getJarFile(); if (file == null) return false; @@ -81,6 +82,7 @@ public class JarIndexLocation extends IndexLocation { InputStream getInputStream() throws IOException { if (this.jarFile == null) { JarURLConnection connection = (JarURLConnection) this.localUrl.openConnection(); + connection.setUseCaches(false); this.jarFile = connection.getJarFile(); this.jarEntry = connection.getJarEntry(); } diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java index 85d122266..24bd1c755 100644 --- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java +++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java @@ -448,7 +448,9 @@ protected void convertTypeAnchor(int annotationKind) { // SH} protected void consumeMemberValuePair() { super.consumeMemberValuePair(); - this.patternLocator.match((MemberValuePair) this.astStack[this.astPtr], this.nodeSet); + if ((this.patternFineGrain & ~IJavaSearchConstants.METHOD_REFERENCE_EXPRESSION) != 0) { + this.patternLocator.match((MemberValuePair) this.astStack[this.astPtr], this.nodeSet); + } } protected void consumeMethodHeaderName(boolean isAnnotationMethod) { |