diff options
author | Stephan Herrmann | 2013-11-03 15:07:28 +0000 |
---|---|---|
committer | Stephan Herrmann | 2013-11-03 15:07:28 +0000 |
commit | 7941b7c4269f2a90459634e65c6a88cd0889897f (patch) | |
tree | b67fd7be1a8e160a24a74d10b5908c9edf0c119d /org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler | |
parent | bceeef60c17b90b133b5935ea20d307681775a38 (diff) | |
download | org.eclipse.objectteams-7941b7c4269f2a90459634e65c6a88cd0889897f.tar.gz org.eclipse.objectteams-7941b7c4269f2a90459634e65c6a88cd0889897f.tar.xz org.eclipse.objectteams-7941b7c4269f2a90459634e65c6a88cd0889897f.zip |
Update jdt.core & tests to I20131030-2000 for 4.4M3
Diffstat (limited to 'org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler')
17 files changed, 259 insertions, 242 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java index 2b634b2aa..9d5b485b8 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 @@ -234,8 +234,8 @@ public abstract class ASTNode implements TypeConstants, TypeIds { // for if statement public static final int IsElseIfStatement = Bit30; public static final int ThenExit = Bit31; - public static final int IsElseStatementUnreachable = Bit8; - public static final int IsThenStatementUnreachable = Bit9; + public static final int IsElseStatementUnreachable = Bit8; // as computed by control flow analysis or null analysis. + public static final int IsThenStatementUnreachable = Bit9; // as computed by control flow analysis or null analysis // for type reference public static final int IsSuperType = Bit5; 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 8159393e8..46fc8ea1f 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 @@ -20,6 +20,7 @@ * bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null" * bug 388996 - [compiler][resource] Incorrect 'potential resource leak' * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking + * Bug 418235 - [compiler][null] Unreported nullness error when using generic * Jesper S Moller <jesper@selskabet.org> - Contributions for * bug 378674 - "The method can be declared as static" is wrong * Till Brychcy - Contributions for @@ -540,12 +541,7 @@ public TypeBinding resolveType(BlockScope scope) { } final CompilerOptions compilerOptions = scope.compilerOptions(); if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) { -//{ObjectTeams: added 2nd arg: -/* orig: - new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations) - :giro */ - new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations, scope.environment()) -// SH} + new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations) .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope); } //{ObjectTeams: may need to wrap the resolved type diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java index 0a8475c11..85f7c4ecb 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java @@ -836,8 +836,12 @@ public class EqualExpression extends BinaryExpression { return null; } + final CompilerOptions compilerOptions = scope.compilerOptions(); + if (compilerOptions.complainOnUninternedIdentityComparison && originalRightType.hasTypeBit(TypeIds.BitUninternedType) && originalLeftType.hasTypeBit(TypeIds.BitUninternedType)) + scope.problemReporter().uninternedIdentityComparison(this, originalLeftType, originalRightType); + // autoboxing support - boolean use15specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5; + boolean use15specifics = compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5; TypeBinding leftType = originalLeftType, rightType = originalRightType; if (use15specifics) { if (leftType != TypeBinding.NULL && leftType.isBaseType()) { diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java index 912d2abbd..c20ea5a76 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java @@ -29,6 +29,7 @@ * bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking * Bug 405569 - Resource leak check false positive when using DbUtils.closeQuietly + * Bug 418235 - [compiler][null] Unreported nullness error when using generic * Jesper S Moller - Contributions for * Bug 378674 - "The method can be declared as static" is wrong *******************************************************************************/ @@ -1083,9 +1084,7 @@ public TypeBinding resolveType(BlockScope scope) { if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) { // not interested in reporting problems against this.binding: -//{ObjectTeams: added 2nd arg: - new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations, scope.environment()) -// SH} + new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations) .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope); } 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 2fade8c7f..3fd2fd422 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 @@ -20,6 +20,7 @@ * bug 395977 - [compiler][resource] Resource leak warning behavior possibly incorrect for anonymous inner class * bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking * Bug 416267 - NPE in QualifiedAllocationExpression.resolveType + * Bug 418235 - [compiler][null] Unreported nullness error when using generic * Jesper S Moller <jesper@selskabet.org> - Contributions for * bug 378674 - "The method can be declared as static" is wrong * Till Brychcy - Contributions for @@ -346,12 +347,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc if(result != null && this.binding != null) { final CompilerOptions compilerOptions = scope.compilerOptions(); if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) { -//{ObjectTeams: added 2nd arg: -/* orig: - new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations) - :giro */ - new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations, scope.environment()) -// SH} + new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations) .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope); } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java index 5729c8440..c7cbf5750 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java @@ -544,7 +544,11 @@ public static UnconditionalFlowInfo mergedOptimizedBranchesIfElse( // if a variable is only initialized in one branch and not initialized in the other, // then we need to cast a doubt on its initialization in the merged info mergedInfo.definiteInits &= initsWhenFalse.unconditionalCopy().definiteInits; - + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=415997, classify unreachability precisely, IsElseStatementUnreachable could be due to null analysis + if ((mergedInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0 && (initsWhenFalse.tagBits & FlowInfo.UNREACHABLE) == FlowInfo.UNREACHABLE_BY_NULLANALYSIS) { + mergedInfo.tagBits &= ~UNREACHABLE_OR_DEAD; + mergedInfo.tagBits |= UNREACHABLE_BY_NULLANALYSIS; + } } else if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) == 0 && (ifStatement.bits & ASTNode.IsThenStatementUnreachable) != 0 && initsWhenTrue != FlowInfo.DEAD_END @@ -560,6 +564,11 @@ public static UnconditionalFlowInfo mergedOptimizedBranchesIfElse( // if a variable is only initialized in one branch and not initialized in the other, // then we need to cast a doubt on its initialization in the merged info mergedInfo.definiteInits &= initsWhenTrue.unconditionalCopy().definiteInits; + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=415997, classify unreachability precisely, IsThenStatementUnreachable could be due to null analysis + if ((mergedInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0 && (initsWhenTrue.tagBits & FlowInfo.UNREACHABLE) == FlowInfo.UNREACHABLE_BY_NULLANALYSIS) { + mergedInfo.tagBits &= ~UNREACHABLE_OR_DEAD; + mergedInfo.tagBits |= UNREACHABLE_BY_NULLANALYSIS; + } } else { mergedInfo = initsWhenTrue. diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java index 129ad7f9d..2cae1d9bf 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java @@ -241,6 +241,7 @@ public class CompilerOptions { public static final String OPTION_NullableAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nullable"; //$NON-NLS-1$ public static final String OPTION_NonNullAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnull"; //$NON-NLS-1$ public static final String OPTION_NonNullByDefaultAnnotationName = "org.eclipse.jdt.core.compiler.annotation.nonnullbydefault"; //$NON-NLS-1$ + public static final String OPTION_ReportUninternedIdentityComparison = "org.eclipse.jdt.core.compiler.problem.uninternedIdentityComparison"; //$NON-NLS-1$ // defaults for the above: static final char[][] DEFAULT_NULLABLE_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.Nullable".toCharArray()); //$NON-NLS-1$ static final char[][] DEFAULT_NONNULL_ANNOTATION_NAME = CharOperation.splitOn('.', "org.eclipse.jdt.annotation.NonNull".toCharArray()); //$NON-NLS-1$ @@ -555,6 +556,8 @@ public class CompilerOptions { /** Should immediate null-check for fields be considered during null analysis (syntactical match)? */ public boolean enableSyntacticNullAnalysisForFields; + public boolean complainOnUninternedIdentityComparison; + // keep in sync with warningTokenToIrritant and warningTokenFromIrritant public final static String[] warningTokens = { "all", //$NON-NLS-1$ @@ -1474,6 +1477,7 @@ public class CompilerOptions { optionsMap.put(OPTION_SyntacticNullAnalysisForFields, this.enableSyntacticNullAnalysisForFields ? ENABLED : DISABLED); optionsMap.put(OPTION_InheritNullAnnotations, this.inheritNullAnnotations ? ENABLED : DISABLED); optionsMap.put(OPTION_ReportNonnullParameterAnnotationDropped, getSeverityString(NonnullParameterAnnotationDropped)); + optionsMap.put(OPTION_ReportUninternedIdentityComparison, this.complainOnUninternedIdentityComparison ? ENABLED : DISABLED); return optionsMap; } @@ -1639,6 +1643,8 @@ public class CompilerOptions { this.analyseResourceLeaks = true; this.reportMissingEnumCaseDespiteDefault = false; + + this.complainOnUninternedIdentityComparison = false; } public void set(Map optionsMap) { @@ -2139,6 +2145,13 @@ public class CompilerOptions { this.storeAnnotations = false; } } + if ((optionValue = optionsMap.get(OPTION_ReportUninternedIdentityComparison)) != null) { + if (ENABLED.equals(optionValue)) { + this.complainOnUninternedIdentityComparison = true; + } else if (DISABLED.equals(optionValue)) { + this.complainOnUninternedIdentityComparison = false; + } + } } public String toString() { StringBuffer buf = new StringBuffer("CompilerOptions:"); //$NON-NLS-1$ 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 beef97c36..1f8a5ad76 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 @@ -47,22 +47,21 @@ public class ImplicitNullAnnotationVerifier { // can be 'this', but is never a MethodVerifier (to avoid infinite recursion). ImplicitNullAnnotationVerifier buddyImplicitNullAnnotationsVerifier; private boolean inheritNullAnnotations; - private LookupEnvironment environment; + protected LookupEnvironment environment; -//{ObjectTeams: added 2nd arg: - public ImplicitNullAnnotationVerifier(boolean inheritNullAnnotations, LookupEnvironment environment) { - this.environment = environment; -// SH} + + public ImplicitNullAnnotationVerifier(LookupEnvironment environment, boolean inheritNullAnnotations) { this.buddyImplicitNullAnnotationsVerifier = this; this.inheritNullAnnotations = inheritNullAnnotations; + this.environment = environment; } // for sub-classes: -//{ObjectTeams: added 2nd arg: - ImplicitNullAnnotationVerifier(CompilerOptions options, LookupEnvironment environment) { - this.buddyImplicitNullAnnotationsVerifier = new ImplicitNullAnnotationVerifier(options.inheritNullAnnotations, environment); -// SH} + ImplicitNullAnnotationVerifier(LookupEnvironment environment) { + CompilerOptions options = environment.globalOptions; + this.buddyImplicitNullAnnotationsVerifier = new ImplicitNullAnnotationVerifier(environment, options.inheritNullAnnotations); this.inheritNullAnnotations = options.inheritNullAnnotations; + this.environment = environment; } /** @@ -176,7 +175,7 @@ public class ImplicitNullAnnotationVerifier { MethodBinding currentMethod = ifcMethods[i]; if (currentMethod.isStatic()) continue; - if (areParametersEqual(original, currentMethod.original())) { + if (doesMethodOverride(original, currentMethod)) { result.add(currentMethod); return; // at most one method is overridden from any supertype } @@ -220,7 +219,6 @@ public class ImplicitNullAnnotationVerifier { long currentBits = currentMethod.tagBits; long currentNullnessBits = currentBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable); - LookupEnvironment environment = scope.environment(); boolean shouldInherit = this.inheritNullAnnotations; // return type: @@ -257,7 +255,7 @@ public class ImplicitNullAnnotationVerifier { { if (srcMethod != null) { scope.problemReporter().illegalReturnRedefinition(srcMethod, inheritedMethod, - environment.getNonNullAnnotationName()); + this.environment.getNonNullAnnotationName()); } else { scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod); return; @@ -319,9 +317,9 @@ public class ImplicitNullAnnotationVerifier { if (shouldComplain) { char[][] annotationName; if (inheritedNonNullNess == Boolean.TRUE) { - annotationName = environment.getNonNullAnnotationName(); + annotationName = this.environment.getNonNullAnnotationName(); } else { - annotationName = environment.getNullableAnnotationName(); + annotationName = this.environment.getNullableAnnotationName(); } if (inheritedNonNullNess != Boolean.TRUE // super parameter is not restricted to @NonNull && currentNonNullNess == Boolean.TRUE) // current parameter is restricted to @NonNull @@ -331,7 +329,7 @@ public class ImplicitNullAnnotationVerifier { scope.problemReporter().illegalRedefinitionToNonNullParameter( currentArgument, inheritedMethod.declaringClass, - (inheritedNonNullNess == null) ? null : environment.getNullableAnnotationName()); + (inheritedNonNullNess == null) ? null : this.environment.getNullableAnnotationName()); } else { scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod); } @@ -512,4 +510,156 @@ public class ImplicitNullAnnotationVerifier { return false; } // SH} + public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { + return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod); + } + + protected boolean couldMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { + if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)) + return false; + if (method == inheritedMethod || method.isStatic() || inheritedMethod.isStatic()) +//{ObjectTeams: treat static pair of methods in role ifc/class as overriding: + if (!staticRoleMethodImpl(method, inheritedMethod)) +// SH} + return false; + if (inheritedMethod.isPrivate()) + return false; + if (inheritedMethod.isDefault() && method.declaringClass.getPackage() != inheritedMethod.declaringClass.getPackage()) + return false; + if (!method.isPublic()) { // inheritedMethod is either public or protected & method is less than public + if (inheritedMethod.isPublic()) + return false; + if (inheritedMethod.isProtected() && !method.isProtected()) + return false; + } + return true; + } + +//{ObjectTeams: is method the static implementation of a role ifc's abstract static? + private boolean staticRoleMethodImpl(MethodBinding method, MethodBinding inheritedMethod) + { + if (inheritedMethod.declaringClass.isSynthInterface()) + return method.isStatic() && inheritedMethod.isStatic(); + return false; + } +// SH} + + protected boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { + // use the original methods to test compatibility, but do not check visibility, etc + one = one.original(); + two = one.findOriginalInheritedMethod(two); + + if (two == null) + return false; // method's declaringClass does not inherit from inheritedMethod's + + return isParameterSubsignature(one, two); + } + + protected boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { + MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method); + return substitute != null && isSubstituteParameterSubsignature(method, substitute); + } + + protected MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { + if (inheritedMethod == null) return null; + //{ObjectTeams: use source-level params in case of enhanced callin methods: + /* orig: + if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match + :giro */ + if (currentMethod.getSourceParamLength() != inheritedMethod.getSourceParamLength()) return null; // no match + // SH} + + // due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved + if (currentMethod.declaringClass instanceof BinaryTypeBinding) + ((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod); + if (inheritedMethod.declaringClass instanceof BinaryTypeBinding) + ((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod); + + TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables; + int inheritedLength = inheritedTypeVariables.length; + if (inheritedLength == 0) return inheritedMethod; // no substitution needed + TypeVariableBinding[] typeVariables = currentMethod.typeVariables; + int length = typeVariables.length; + if (length == 0) + return inheritedMethod.asRawMethod(this.environment); + if (length != inheritedLength) + return inheritedMethod; // no match JLS 8.4.2 + + // interface I { <T> void foo(T t); } + // class X implements I { public <T extends I> void foo(T t) {} } + // for the above case, we do not want to answer the substitute method since its not a match + TypeVariableBinding[] arguments = new TypeVariableBinding[length]; + System.arraycopy(typeVariables, 0, arguments, 0, length); + ParameterizedGenericMethodBinding substitute = + this.environment.createParameterizedGenericMethod(inheritedMethod, arguments); + for (int i = 0; i < inheritedLength; i++) { + TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables[i]; + TypeVariableBinding typeVariable = arguments[i]; + if (typeVariable.firstBound == inheritedTypeVariable.firstBound) { + if (typeVariable.firstBound == null) + continue; // both are null + } else if (typeVariable.firstBound != null && inheritedTypeVariable.firstBound != null) { + if (typeVariable.firstBound.isClass() != inheritedTypeVariable.firstBound.isClass()) + return inheritedMethod; // not a match + } + if (Scope.substitute(substitute, inheritedTypeVariable.superclass) != typeVariable.superclass) + return inheritedMethod; // not a match + int interfaceLength = inheritedTypeVariable.superInterfaces.length; + ReferenceBinding[] interfaces = typeVariable.superInterfaces; + if (interfaceLength != interfaces.length) + return inheritedMethod; // not a match + next : for (int j = 0; j < interfaceLength; j++) { + TypeBinding superType = Scope.substitute(substitute, inheritedTypeVariable.superInterfaces[j]); + for (int k = 0; k < interfaceLength; k++) + if (superType == interfaces[k]) + continue next; + return inheritedMethod; // not a match + } + } + return substitute; + } + + protected boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod) { + if (!areParametersEqual(method, substituteMethod)) { + // method can still override substituteMethod in cases like : + // <U extends Number> void c(U u) {} + // @Override void c(Number n) {} + // but method cannot have a "generic-enabled" parameter type + if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod)) + return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method); + + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=279836 + if (method.declaringClass.isRawType() && substituteMethod.declaringClass.isRawType()) + if (method.hasSubstitutedParameters() && substituteMethod.hasSubstitutedParameters()) + return areMethodsCompatible(method, substituteMethod); + + return false; + } + + if (substituteMethod instanceof ParameterizedGenericMethodBinding) { + if (method.typeVariables != Binding.NO_TYPE_VARIABLES) + return !((ParameterizedGenericMethodBinding) substituteMethod).isRaw; + // since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does + return !hasGenericParameter(method); + } + + // if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod() + return method.typeVariables == Binding.NO_TYPE_VARIABLES; + } + + boolean hasGenericParameter(MethodBinding method) { + if (method.genericSignature() == null) return false; + + // may be only the return type that is generic, need to check parameters + TypeBinding[] params = method.parameters; + for (int i = 0, l = params.length; i < l; i++) { + TypeBinding param = params[i].leafComponentType(); + if (param instanceof ReferenceBinding) { + int modifiers = ((ReferenceBinding) param).modifiers; + if ((modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) + return true; + } + } + return false; + } } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java index 2614134e7..f42704780 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier.java @@ -15,6 +15,7 @@ * bug 395681 - [compiler] Improve simulation of javac6 behavior from bug 317719 after fixing bug 388795 * bug 406928 - computation of inherited methods seems damaged (affecting @Overrides) * bug 409473 - [compiler] JDT cannot compile against JRE 1.8 + * Bug 418235 - [compiler][null] Unreported nullness error when using generic *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -68,7 +69,6 @@ public abstract class MethodVerifier extends ImplicitNullAnnotationVerifier { SourceTypeBinding type; HashtableOfObject inheritedMethods; HashtableOfObject currentMethods; - LookupEnvironment environment; private boolean allowCompatibleReturnTypes; /* Binding creation is responsible for reporting all problems with types: @@ -88,9 +88,7 @@ Binding creation is responsible for reporting all problems with types: - defining an interface as a local type (local types can only be classes) */ MethodVerifier(LookupEnvironment environment) { -//{ObjectTeams: added 2nd arg: - super(environment.globalOptions, environment); -// SH} + super(environment); this.type = null; // Initialized with the public method verify(SourceTypeBinding) this.inheritedMethods = null; this.currentMethods = null; @@ -99,9 +97,6 @@ MethodVerifier(LookupEnvironment environment) { environment.globalOptions.complianceLevel >= ClassFileConstants.JDK1_5 && environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_5; } -boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { - return isParameterSubsignature(one, two) && areReturnTypesCompatible(one, two); -} boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) { //{ObjectTeams: consider enhanced callin signatures: /* orig: @@ -852,68 +847,6 @@ void computeMethods() { } } -MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { - if (inheritedMethod == null) return null; - if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match -//{ObjectTeams: copied from MethodVerifier15 and guarded with own condition: - if ( (currentMethod.declaringClass.isRole() && inheritedMethod.declaringClass.isRole()) - || (currentMethod.declaringClass.isTeam() && inheritedMethod.declaringClass.isTeam())) - { - // orig 15: - // due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved - if (currentMethod.declaringClass instanceof BinaryTypeBinding) - ((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod); - if (inheritedMethod.declaringClass instanceof BinaryTypeBinding) - ((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod); - // :giro - } -//SH} - return inheritedMethod; -} - -boolean couldMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { - if (!org.eclipse.jdt.core.compiler.CharOperation.equals(method.selector, inheritedMethod.selector)) - return false; - if (method == inheritedMethod || method.isStatic() || inheritedMethod.isStatic()) -//{ObjectTeams: treat static pair of methods in role ifc/class as overriding: - if (!staticRoleMethodImpl(method, inheritedMethod)) -// SH} - return false; - if (inheritedMethod.isPrivate()) - return false; - if (inheritedMethod.isDefault() && method.declaringClass.getPackage() != inheritedMethod.declaringClass.getPackage()) - return false; - if (!method.isPublic()) { // inheritedMethod is either public or protected & method is less than public - if (inheritedMethod.isPublic()) - return false; - if (inheritedMethod.isProtected() && !method.isProtected()) - return false; - } - return true; -} -//{ObjectTeams: is method the static implementation of a role ifc's abstract static? -private boolean staticRoleMethodImpl(MethodBinding method, MethodBinding inheritedMethod) -{ - if (inheritedMethod.declaringClass.isSynthInterface()) - return method.isStatic() && inheritedMethod.isStatic(); - return false; -} -// SH} -// Answer whether the method overrides the inheritedMethod -// Check the necessary visibility rules & inheritance from the inheritedMethod's declaringClass -// See isMethodSubsignature() for parameter comparisons -public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { - if (!couldMethodOverride(method, inheritedMethod)) - return false; - - inheritedMethod = inheritedMethod.original(); - TypeBinding match = method.declaringClass.findSuperTypeOriginatingFrom(inheritedMethod.declaringClass); - if (!(match instanceof ReferenceBinding)) - return false; // method's declaringClass does not inherit from inheritedMethod's - - return isParameterSubsignature(method, inheritedMethod); -} - SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) { return null; // noop in 1.4 } @@ -1020,10 +953,6 @@ public boolean isMethodSubsignature(MethodBinding method, MethodBinding inherite && isParameterSubsignature(method, inheritedMethod); } -boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { - return areParametersEqual(method, inheritedMethod); -} - boolean isSameClassOrSubclassOf(ReferenceBinding testClass, ReferenceBinding superclass) { do { if (testClass == superclass) return true; 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 4e70de288..2993e65be 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 @@ -18,6 +18,7 @@ * bug 395681 - [compiler] Improve simulation of javac6 behavior from bug 317719 after fixing bug 388795 * bug 409473 - [compiler] JDT cannot compile against JRE 1.8 * Bug 410325 - [1.7][compiler] Generified method override different between javac and eclipse compiler + * Bug 418235 - [compiler][null] Unreported nullness error when using generic *******************************************************************************/ package org.eclipse.jdt.internal.compiler.lookup; @@ -48,16 +49,6 @@ class MethodVerifier15 extends MethodVerifier { MethodVerifier15(LookupEnvironment environment) { super(environment); } -boolean areMethodsCompatible(MethodBinding one, MethodBinding two) { - // use the original methods to test compatibility, but do not check visibility, etc - one = one.original(); - two = one.findOriginalInheritedMethod(two); - - if (two == null) - return false; // method's declaringClass does not inherit from inheritedMethod's - - return isParameterSubsignature(one, two); -} boolean areReturnTypesCompatible(MethodBinding one, MethodBinding two) { //{ObjectTeams: consider enhanced callin signatures: /* orig: @@ -379,7 +370,7 @@ void checkNullSpecInheritance(MethodBinding currentMethod, AbstractMethodDeclara if (currentMethod.declaringClass != this.type && (currentMethod.tagBits & TagBits.IsNullnessKnown) == 0) { - this.buddyImplicitNullAnnotationsVerifier.checkImplicitNullAnnotations(currentMethod, srcMethod, complain, this.type.scope); + this.buddyImplicitNullAnnotationsVerifier.checkImplicitNullAnnotations(currentMethod, srcMethod, complain, scope); } super.checkNullSpecInheritance(currentMethod, srcMethod, hasNonNullDefault, complain, inheritedMethod, scope, inheritedNonNullnessInfos); } @@ -790,69 +781,6 @@ void checkTypeVariableMethods(TypeParameter typeParameter) { } } } -MethodBinding computeSubstituteMethod(MethodBinding inheritedMethod, MethodBinding currentMethod) { - if (inheritedMethod == null) return null; -//{ObjectTeams: use source-level params in case of enhanced callin methods: -/* orig: - if (currentMethod.parameters.length != inheritedMethod.parameters.length) return null; // no match - :giro */ - if (currentMethod.getSourceParamLength() != inheritedMethod.getSourceParamLength()) return null; // no match -// SH} - - // due to hierarchy & compatibility checks, we need to ensure these 2 methods are resolved - if (currentMethod.declaringClass instanceof BinaryTypeBinding) - ((BinaryTypeBinding) currentMethod.declaringClass).resolveTypesFor(currentMethod); - if (inheritedMethod.declaringClass instanceof BinaryTypeBinding) - ((BinaryTypeBinding) inheritedMethod.declaringClass).resolveTypesFor(inheritedMethod); - - TypeVariableBinding[] inheritedTypeVariables = inheritedMethod.typeVariables; - int inheritedLength = inheritedTypeVariables.length; - if (inheritedLength == 0) return inheritedMethod; // no substitution needed - TypeVariableBinding[] typeVariables = currentMethod.typeVariables; - int length = typeVariables.length; - if (length == 0) - return inheritedMethod.asRawMethod(this.environment); - if (length != inheritedLength) - return inheritedMethod; // no match JLS 8.4.2 - - // interface I { <T> void foo(T t); } - // class X implements I { public <T extends I> void foo(T t) {} } - // for the above case, we do not want to answer the substitute method since its not a match - TypeBinding[] arguments = new TypeBinding[length]; - System.arraycopy(typeVariables, 0, arguments, 0, length); - ParameterizedGenericMethodBinding substitute = - this.environment.createParameterizedGenericMethod(inheritedMethod, arguments); - for (int i = 0; i < inheritedLength; i++) { - TypeVariableBinding inheritedTypeVariable = inheritedTypeVariables[i]; - TypeBinding argument = arguments[i]; - if (argument instanceof TypeVariableBinding) { - TypeVariableBinding typeVariable = (TypeVariableBinding) argument; - if (typeVariable.firstBound == inheritedTypeVariable.firstBound) { - if (typeVariable.firstBound == null) - continue; // both are null - } else if (typeVariable.firstBound != null && inheritedTypeVariable.firstBound != null) { - if (typeVariable.firstBound.isClass() != inheritedTypeVariable.firstBound.isClass()) - return inheritedMethod; // not a match - } - if (Scope.substitute(substitute, inheritedTypeVariable.superclass) != typeVariable.superclass) - return inheritedMethod; // not a match - int interfaceLength = inheritedTypeVariable.superInterfaces.length; - ReferenceBinding[] interfaces = typeVariable.superInterfaces; - if (interfaceLength != interfaces.length) - return inheritedMethod; // not a match - next : for (int j = 0; j < interfaceLength; j++) { - TypeBinding superType = Scope.substitute(substitute, inheritedTypeVariable.superInterfaces[j]); - for (int k = 0; k < interfaceLength; k++) - if (superType == interfaces[k]) - continue next; - return inheritedMethod; // not a match - } - } else if (inheritedTypeVariable.boundCheck(substitute, argument, this.type.scope) != TypeConstants.OK) { - return inheritedMethod; - } - } - return substitute; -} boolean detectInheritedNameClash(MethodBinding inherited, MethodBinding otherInherited) { if (!inherited.areParameterErasuresEqual(otherInherited)) return false; @@ -913,9 +841,6 @@ boolean detectNameClash(MethodBinding current, MethodBinding inherited, boolean if (severity == ProblemSeverities.Warning) return false; return true; } -public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod) { - return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod); -} boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) { // one has type variables and substituteTwo did not pass bounds check in computeSubstituteMethod() return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding); @@ -989,21 +914,6 @@ SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBin } return copy; } -boolean hasGenericParameter(MethodBinding method) { - if (method.genericSignature() == null) return false; - - // may be only the return type that is generic, need to check parameters - TypeBinding[] params = method.parameters; - for (int i = 0, l = params.length; i < l; i++) { - TypeBinding param = params[i].leafComponentType(); - if (param instanceof ReferenceBinding) { - int modifiers = ((ReferenceBinding) param).modifiers; - if ((modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) - return true; - } - } - return false; -} boolean isAcceptableReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { // called when currentMethod's return type is compatible with inheritedMethod's return type @@ -1049,39 +959,6 @@ public boolean isMethodSubsignature(MethodBinding method, MethodBinding inherite MethodBinding inheritedOriginal = method.findOriginalInheritedMethod(inheritedMethod); return isParameterSubsignature(method, inheritedOriginal == null ? inheritedMethod : inheritedOriginal); } -boolean isParameterSubsignature(MethodBinding method, MethodBinding inheritedMethod) { - MethodBinding substitute = computeSubstituteMethod(inheritedMethod, method); - return substitute != null && isSubstituteParameterSubsignature(method, substitute); -} -// if method "overrides" substituteMethod then we can skip over substituteMethod while resolving a message send -// if it does not then a name clash error is likely -boolean isSubstituteParameterSubsignature(MethodBinding method, MethodBinding substituteMethod) { - if (!areParametersEqual(method, substituteMethod)) { - // method can still override substituteMethod in cases like : - // <U extends Number> void c(U u) {} - // @Override void c(Number n) {} - // but method cannot have a "generic-enabled" parameter type - if (substituteMethod.hasSubstitutedParameters() && method.areParameterErasuresEqual(substituteMethod)) - return method.typeVariables == Binding.NO_TYPE_VARIABLES && !hasGenericParameter(method); - - // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=279836 - if (method.declaringClass.isRawType() && substituteMethod.declaringClass.isRawType()) - if (method.hasSubstitutedParameters() && substituteMethod.hasSubstitutedParameters()) - return areMethodsCompatible(method, substituteMethod); - - return false; - } - - if (substituteMethod instanceof ParameterizedGenericMethodBinding) { - if (method.typeVariables != Binding.NO_TYPE_VARIABLES) - return !((ParameterizedGenericMethodBinding) substituteMethod).isRaw; - // since substituteMethod has substituted type variables, method cannot have a generic signature AND no variables -> its a name clash if it does - return !hasGenericParameter(method); - } - - // if method has its own variables, then substituteMethod failed bounds check in computeSubstituteMethod() - return method.typeVariables == Binding.NO_TYPE_VARIABLES; -} boolean isUnsafeReturnTypeOverride(MethodBinding currentMethod, MethodBinding inheritedMethod) { // called when currentMethod's return type is NOT compatible with inheritedMethod's return type 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 f9f60d045..134d27da9 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 @@ -970,6 +970,12 @@ public void computeId() { return; } break; + case 7 : + if (!CharOperation.equals(TypeConstants.JDT, this.compoundName[2]) || !CharOperation.equals(TypeConstants.TYPEBINDING, this.compoundName[6])) + return; + if (CharOperation.equals(TypeConstants.ORG_ECLIPSE_JDT_INTERNAL_COMPILER_LOOKUP_TYPEBINDING, this.compoundName)) + this.typeBits |= TypeIds.BitUninternedType; + break; } } @@ -1339,8 +1345,6 @@ boolean hasNonNullDefault() { public final boolean hasRestrictedAccess() { return (this.modifiers & ExtraCompilerModifiers.AccRestrictedAccess) != 0; } -/** Answer an additional bit characterizing this type, like {@link TypeIds#BitAutoCloseable}. */ -abstract public boolean hasTypeBit(int bit); //{ObjectTeams: support asymmetric comparison. // FIXME(SH): is this needed or is super-impl smart enough?? @Override 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 16f12924e..f6499edb2 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 @@ -23,6 +23,7 @@ * bug 388281 - [compiler][null] inheritance of null annotations as an option * bug 331649 - [compiler][null] consider null annotations for fields * bug 380896 - [compiler][null] Enum constants not recognised as being NonNull. + * Bug 418235 - [compiler][null] Unreported nullness error when using generic * Till Brychcy - Contributions for * bug 415269 - NonNullByDefault is not always inherited to nested classes *******************************************************************************/ @@ -2403,9 +2404,8 @@ private void createArgumentBindings(MethodBinding method, CompilerOptions compil methodDecl.createArgumentBindings(); // add implicit annotations (inherited(?) & default): if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) { -//{ObjectTeams: added 2nd ctor arg: - new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations, this.scope.environment()).checkImplicitNullAnnotations(method, methodDecl, true, this.scope); -// SH} + new ImplicitNullAnnotationVerifier(this.scope.environment(), compilerOptions.inheritNullAnnotations) + .checkImplicitNullAnnotations(method, methodDecl, true, this.scope); } } } 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 f5f61ef73..32e2ca5ca 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 @@ -1294,4 +1294,8 @@ public DependentTypeBinding asPlainDependentType() { return null; // is not a dependent type } // SH} +/** Answer an additional bit characterizing this type, like {@link TypeIds#BitAutoCloseable}. */ +public boolean hasTypeBit(int bit) { + return false; +} } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java index 6c801d9a3..b708a579b 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java @@ -95,7 +95,12 @@ public interface TypeConstants { char[] LANG3 = "lang3".toCharArray(); //$NON-NLS-1$ char[] COM = "com".toCharArray(); //$NON-NLS-1$ char[] GOOGLE = "google".toCharArray(); //$NON-NLS-1$ - + char[] JDT = "jdt".toCharArray(); //$NON-NLS-1$ + char[] INTERNAL = "internal".toCharArray(); //$NON-NLS-1$ + char[] COMPILER = "compiler".toCharArray(); //$NON-NLS-1$ + char[] LOOKUP = "lookup".toCharArray(); //$NON-NLS-1$ + char[] TYPEBINDING = "TypeBinding".toCharArray(); //$NON-NLS-1$ + // Constant compound names char[][] JAVA_LANG = {JAVA, LANG}; char[][] JAVA_IO = {JAVA, IO}; @@ -272,6 +277,7 @@ public interface TypeConstants { char[] VALIDATE_CLASS = "Validate".toCharArray(); //$NON-NLS-1$ char[][] ORG_APACHE_COMMONS_LANG_VALIDATE = new char[][] { ORG, APACHE, COMMONS, LANG, VALIDATE_CLASS }; char[][] ORG_APACHE_COMMONS_LANG3_VALIDATE = new char[][] { ORG, APACHE, COMMONS, LANG3, VALIDATE_CLASS }; + char[][] ORG_ECLIPSE_JDT_INTERNAL_COMPILER_LOOKUP_TYPEBINDING = new char[][] { ORG, ECLIPSE, JDT, INTERNAL, COMPILER, LOOKUP, TYPEBINDING }; // ... methods: char[] IS_TRUE = "isTrue".toCharArray(); //$NON-NLS-1$ char[] NOT_NULL = "notNull".toCharArray(); //$NON-NLS-1$ diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java index 5703e17c1..e19710ace 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java @@ -231,8 +231,9 @@ public interface TypeIds { */ final int BitResourceFreeCloseable = 8; + final int BitUninternedType = 16; /** * Set of type bits that should be inherited by any sub types. */ - final int InheritableBits = BitAutoCloseable | BitCloseable; + final int InheritableBits = BitAutoCloseable | BitCloseable | BitUninternedType; } 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 048c40680..ee856293f 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 @@ -13121,4 +13121,32 @@ public void missingNonNullByDefaultAnnotation(TypeDeclaration type) { compUnitDecl.currentPackage.sourceEnd); } } +public void uninternedIdentityComparison(EqualExpression expr, TypeBinding lhs, TypeBinding rhs) { + + char [] lhsName = lhs.sourceName(); + char [] rhsName = rhs.sourceName(); + + if (CharOperation.equals(lhsName, "VoidTypeBinding".toCharArray()) //$NON-NLS-1$ + || CharOperation.equals(lhsName, "NullTypeBinding".toCharArray()) //$NON-NLS-1$ + || CharOperation.equals(lhsName, "ProblemReferenceBinding".toCharArray())) //$NON-NLS-1$ + return; + + if (CharOperation.equals(rhsName, "VoidTypeBinding".toCharArray()) //$NON-NLS-1$ + || CharOperation.equals(rhsName, "NullTypeBinding".toCharArray()) //$NON-NLS-1$ + || CharOperation.equals(rhsName, "ProblemReferenceBinding".toCharArray())) //$NON-NLS-1$ + return; + + this.handle( + IProblem.UninternedIdentityComparison, + new String[] { + new String(lhs.readableName()), + new String(rhs.readableName()) + }, + new String[] { + new String(lhs.shortReadableName()), + new String(rhs.shortReadableName()) + }, + expr.sourceStart, + expr.sourceEnd); +} } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties index 92cdd61de..22d0da4f1 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 @@ -45,12 +45,12 @@ 23 = Illegal enclosing instance specification for type {0} 24 = Cannot define static initializer in inner type {0} 25 = Cannot refer to a non-final variable {0} inside an inner class defined in a different method -26 = The member interface {0} can only be defined inside a top-level class or interface +26 = The member interface {0} can only be defined inside a top-level class or interface or in a static context 27 = Cannot use an expression of the type {0} as a valid enclosing instance 28 = No enclosing instance of type {0} is available due to some intermediate constructor invocation 29 = An anonymous class cannot subclass the final class {0} -30 = The member annotation {0} can only be defined inside a top-level class or interface -31 = The member enum {0} can only be defined inside a top-level class or interface +30 = The member annotation {0} can only be defined inside a top-level class or interface or in a static context +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} @@ -396,6 +396,7 @@ 440 = 'assert' should not be used as an identifier, since it is a reserved keyword from source level 1.4 on 441 = 'enum' should not be used as an identifier, since it is a reserved keyword from source level 1.5 on 442 = Enum constants cannot be surrounded by parenthesis +443 = The uninterned types {0} and {1} should not be compared using ==/!= operators. 450 = {0}{1} |