mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IG; new "'Optional.get()' without 'isPresent()' check" inspection
This commit is contained in:
@@ -328,6 +328,10 @@
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ObjectToString" bundle="com.siyeh.InspectionGadgetsBundle" key="default.tostring.call.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.ObjectToStringInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="OptionalGetWithoutIsPresent" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="optional.get.without.is.present.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.OptionalGetWithoutIsPresentInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="PrimitiveArrayArgumentToVarargsMethod" alternativeId="PrimitiveArrayArgumentToVariableArgMethod"
|
||||
shortName="PrimitiveArrayArgumentToVariableArgMethod" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="primitive.array.argument.to.var.arg.method.display.name" groupBundle="messages.InspectionsBundle"
|
||||
|
||||
+3
-1
@@ -2168,4 +2168,6 @@ lambda.unfriendly.method.overload.display.name=Lambda unfriendly method overload
|
||||
lambda.unfriendly.method.overload.problem.descriptor=Lambda unfriendly overload of method <code>#ref()</code>
|
||||
optional.contains.collection.display.name='Optional' contains array or collection
|
||||
optional.contains.collection.problem.descriptor='Optional' contains collection <code>#ref</code>
|
||||
optional.contains.array.problem.descriptor='Optional' contains array <code>#ref</code>
|
||||
optional.contains.array.problem.descriptor='Optional' contains array <code>#ref</code>
|
||||
optional.get.without.is.present.display.name='Optional.get()' without 'isPresent()' check
|
||||
optional.get.without.is.present.problem.descriptor=<code>{0}.#ref()</code> without ''isPresent()'' check
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class OptionalGetWithoutIsPresentInspection extends BaseInspection {
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message("optional.get.without.is.present.display.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String buildErrorString(Object... infos) {
|
||||
final PsiType type = (PsiType)infos[0];
|
||||
final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(type);
|
||||
return InspectionGadgetsBundle.message("optional.get.without.is.present.problem.descriptor", aClass.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new OptionalGetWithoutIsPresentVisitor();
|
||||
}
|
||||
|
||||
private static class OptionalGetWithoutIsPresentVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
|
||||
super.visitMethodCallExpression(expression);
|
||||
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
|
||||
final String name = methodExpression.getReferenceName();
|
||||
if (!"get".equals(name) && !"getAsDouble".equals(name) && !"getAsInt".equals(name) && !"getAsLong".equals(name)) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression qualifier = ParenthesesUtils.stripParentheses(methodExpression.getQualifierExpression());
|
||||
if (!(qualifier instanceof PsiReferenceExpression)) {
|
||||
return;
|
||||
}
|
||||
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
|
||||
final PsiType type = qualifier.getType();
|
||||
if (!TypeUtils.isOptional(type)) {
|
||||
return;
|
||||
}
|
||||
if (isSurroundedByIsPresentGuard(referenceExpression)) {
|
||||
return;
|
||||
}
|
||||
registerMethodCallError(expression, type);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSurroundedByIsPresentGuard(PsiReferenceExpression referenceExpression) {
|
||||
PsiElement element = referenceExpression;
|
||||
while (true) {
|
||||
final PsiIfStatement ifStatement = PsiTreeUtil.getParentOfType(element, PsiIfStatement.class, true,
|
||||
PsiMember.class, PsiLambdaExpression.class);
|
||||
if (ifStatement == null) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression condition = ifStatement.getCondition();
|
||||
if (isIsPresentCheck(condition, referenceExpression)) {
|
||||
return true;
|
||||
}
|
||||
element = ifStatement;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isIsPresentCheck(@Nullable PsiExpression expression, PsiReferenceExpression reference) {
|
||||
expression = ParenthesesUtils.stripParentheses(expression);
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
|
||||
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
|
||||
final String name = methodExpression.getReferenceName();
|
||||
if (!"isPresent".equals(name)) {
|
||||
return false;
|
||||
}
|
||||
final PsiExpression qualifier = methodExpression.getQualifierExpression();
|
||||
if (!(qualifier instanceof PsiReferenceExpression)) {
|
||||
return false;
|
||||
}
|
||||
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)qualifier;
|
||||
final PsiElement qTarget = referenceExpression.resolve();
|
||||
final PsiElement target = reference.resolve();
|
||||
return qTarget != null && qTarget.equals(target);
|
||||
}
|
||||
else if (expression instanceof PsiPolyadicExpression) {
|
||||
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
|
||||
final PsiExpression[] operands = polyadicExpression.getOperands();
|
||||
for (PsiExpression operand : operands) {
|
||||
if (isIsPresentCheck(operand, reference)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports calls to <b>java.util.Optional.get()</b> without first checking with a <b>isPresent()</b> call if a value is available.
|
||||
If the <b>Optional</b> does not contain a value, <b>get()</b> will throw an exception.
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
<small>New in 16</small>
|
||||
</body>
|
||||
</html>
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.siyeh.ig.LightInspectionTestCase;
|
||||
import junit.framework.TestCase;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Bas Leijdekkers
|
||||
*/
|
||||
public class OptionalGetWithoutIsPresentInspectionTest extends LightInspectionTestCase {
|
||||
|
||||
public void testSimple() {
|
||||
doTest("import java.util.Optional;" +
|
||||
"class X {" +
|
||||
" void a(Optional<String> o) {" +
|
||||
" System.out.println(o./*'Optional.get()' without 'isPresent()' check*/get/**/());" +
|
||||
" }" +
|
||||
"}");
|
||||
}
|
||||
|
||||
public void testOptionalDouble() {
|
||||
doTest("import java.util.OptionalDouble;" +
|
||||
"class X {" +
|
||||
" double a(OptionalDouble d) {" +
|
||||
" return d./*'OptionalDouble.getAsDouble()' without 'isPresent()' check*/getAsDouble/**/();" +
|
||||
" }" +
|
||||
"}");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionProfileEntry getInspection() {
|
||||
return new OptionalGetWithoutIsPresentInspection();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getEnvironmentClasses() {
|
||||
return new String[] {
|
||||
"package java.util;" +
|
||||
"public final class Optional<T> {" +
|
||||
" public T get() {" +
|
||||
" return null;" +
|
||||
" }" +
|
||||
" public boolean isPresent() {" +
|
||||
" return true;" +
|
||||
" }" +
|
||||
"}",
|
||||
|
||||
"package java.util;" +
|
||||
"public final class OptionalDouble {" +
|
||||
" public boolean isPresent() {" +
|
||||
" return true;" +
|
||||
" }" +
|
||||
" public double getAsDouble() {" +
|
||||
" return 0.0;" +
|
||||
" }" +
|
||||
"}"
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user