diff options
author | Stephan Herrmann | 2017-04-09 21:54:18 +0000 |
---|---|---|
committer | Stephan Herrmann | 2017-04-11 13:05:21 +0000 |
commit | 8e7f77d85abf81407daed23fef4b3a32a6ec4955 (patch) | |
tree | 2f1c781648387af088ac48e1e653c9dff99b0b24 | |
parent | 7fde25559f0d9bae5414d15e552cebaf117cd858 (diff) | |
download | eclipse.jdt.core-8e7f77d85abf81407daed23fef4b3a32a6ec4955.tar.gz eclipse.jdt.core-8e7f77d85abf81407daed23fef4b3a32a6ec4955.tar.xz eclipse.jdt.core-8e7f77d85abf81407daed23fef4b3a32a6ec4955.zip |
Bug 514956: Don't warn about "unnecessary" cast that is used to avoidI20170411-2000
"unlikely argument type" warning
Change-Id: I22fc9861bbc8e7cd5e5807babe1488c36163783c
Signed-off-by: Stephan Herrmann <stephan.herrmann@berlin.de>
2 files changed, 98 insertions, 2 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java index 47ee79b629..29ed4e81c4 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ProgrammingProblemsTest.java @@ -3221,6 +3221,82 @@ public void testBug410218f() { true/*shouldFlushOutputDirectory*/, customOptions); } +public void testBug514956a() { + if (this.complianceLevel < ClassFileConstants.JDK1_5) + return; + Map customOptions = getCompilerOptions(); + customOptions.put(JavaCore.COMPILER_PB_UNLIKELY_COLLECTION_METHOD_ARGUMENT_TYPE, JavaCore.WARNING); + customOptions.put(JavaCore.COMPILER_PB_UNNECESSARY_TYPE_CHECK, JavaCore.ERROR); + runConformTest( + new String[] { + "Unlikely.java", + "import java.util.Map;\n" + + "\n" + + "interface MApplicationElement {}\n" + + "interface EObject {}\n" + + "public class Unlikely {\n" + + " void m(Map<MApplicationElement, MApplicationElement> map, EObject key) {\n" + + " map.get((MApplicationElement)key);\n" + + " }\n" + + "}\n" + }, + customOptions); +} +public void testBug514956b() { + Map customOptions = getCompilerOptions(); + customOptions.put(JavaCore.COMPILER_PB_UNLIKELY_EQUALS_ARGUMENT_TYPE, JavaCore.WARNING); + customOptions.put(JavaCore.COMPILER_PB_UNNECESSARY_TYPE_CHECK, JavaCore.ERROR); + runConformTest( + new String[] { + "Unlikely.java", + "interface EObject {}\n" + + "public class Unlikely {\n" + + " boolean m(EObject key) {\n" + + " return this.equals((Unlikely)key);\n" + + " }\n" + + "}\n" + }, + customOptions); +} +public void testBug514956c() { + Map customOptions = getCompilerOptions(); + customOptions.put(JavaCore.COMPILER_PB_UNLIKELY_EQUALS_ARGUMENT_TYPE, JavaCore.WARNING); + customOptions.put(JavaCore.COMPILER_PB_UNNECESSARY_TYPE_CHECK, JavaCore.ERROR); + runNegativeTest( + new String[] { + "Unlikely.java", + "interface I1 {}\n" + + "interface I2 {}\n" + + "interface I3 {}\n" + + "public class Unlikely implements I1 {\n" + + " boolean m1(I1 i1) {\n" + + " return i1.equals((I1)this);\n" + // not a downcast + " }\n" + + " boolean m2(I1 i1, I2 i2) {\n" + + " return i1.equals((I3)i2);\n" + // cast doesn't fix a problem + " }\n" + + "}\n" + }, + "----------\n" + + "1. ERROR in Unlikely.java (at line 6)\n" + + " return i1.equals((I1)this);\n" + + " ^^^^^^^^\n" + + "Unnecessary cast from Unlikely to I1\n" + + "----------\n" + + "2. ERROR in Unlikely.java (at line 9)\n" + + " return i1.equals((I3)i2);\n" + + " ^^^^^^\n" + + "Unnecessary cast from I2 to I3\n" + + "----------\n" + + "3. WARNING in Unlikely.java (at line 9)\n" + + " return i1.equals((I3)i2);\n" + + " ^^^^^^\n" + + "Unlikely argument type for equals(): I3 seems to be unrelated to I1\n" + + "----------\n", + null, // classlibs + false, // flush output dir + customOptions); +} // mixture of raw type an parametrized type public void testBug513310() { if (this.complianceLevel < ClassFileConstants.JDK1_5) diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java index 1c7dafb98c..0c12277070 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2015 IBM Corporation and others. + * Copyright (c) 2000, 2017 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 @@ -37,6 +37,7 @@ import org.eclipse.jdt.internal.compiler.flow.FlowContext; import org.eclipse.jdt.internal.compiler.flow.FlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.impl.IrritantSet; import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding; import org.eclipse.jdt.internal.compiler.lookup.Binding; import org.eclipse.jdt.internal.compiler.lookup.BlockScope; @@ -322,12 +323,31 @@ private static void checkAlternateBinding(BlockScope scope, Expression receiver, for (int i = 0; i < argumentLength; i++) { if (TypeBinding.notEquals(originalArgumentTypes[i], alternateArgumentTypes[i]) /*&& !originalArgumentTypes[i].needsUncheckedConversion(alternateArgumentTypes[i])*/) { - scope.problemReporter().unnecessaryCast((CastExpression)arguments[i]); + if (!preventsUnlikelyTypeWarning(originalArgumentTypes[i], alternateArgumentTypes[i], receiverType, binding, scope)) + scope.problemReporter().unnecessaryCast((CastExpression)arguments[i]); } } } } +private static boolean preventsUnlikelyTypeWarning(TypeBinding castedType, TypeBinding uncastedType, TypeBinding receiverType, MethodBinding binding, BlockScope scope) { + if (!scope.compilerOptions().isAnyEnabled(IrritantSet.UNLIKELY_ARGUMENT_TYPE)) + return false; + if (binding.isStatic() || binding.parameters.length != 1) + return false; + // would using the uncastedType be considered as dangerous? + UnlikelyArgumentCheck argumentChecks = UnlikelyArgumentCheck.determineCheckForNonStaticSingleArgumentMethod( + uncastedType, scope, binding.selector, receiverType, binding.parameters); + if (argumentChecks != null && argumentChecks.isDangerous(scope)) { + // does the cast help? + argumentChecks = UnlikelyArgumentCheck.determineCheckForNonStaticSingleArgumentMethod( + castedType, scope, binding.selector, receiverType, binding.parameters); + if (argumentChecks == null || !argumentChecks.isDangerous(scope)) + return true; + } + return false; +} + public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) { if (TypeBinding.equalsEquals(match, castType)) { if (!isNarrowing && TypeBinding.equalsEquals(match, this.resolvedType.leafComponentType()) // do not tag as unnecessary when recursing through upper bounds |