IG: reduce duplication

This commit is contained in:
Bas Leijdekkers
2017-11-09 22:30:52 +01:00
parent b2a7fc3ca2
commit a77ae11b0c
11 changed files with 236 additions and 324 deletions
@@ -1788,8 +1788,6 @@ cast.conflicts.with.instanceof.quickfix1=Replace ''{0}'' with ''{1}'' in cast
cast.conflicts.with.instanceof.quickfix2=Replace ''{0}'' with ''{1}'' in instanceof
double.checked.locking.quickfix=Make ''{0}'' volatile
double.literal.may.be.float.literal.display.name='double' literal cast to 'float' could be 'float' literal
double.literal.may.be.float.literal.problem.descriptor=<code>#ref</code> could be replaced with ''{0}'' #loc
double.literal.may.be.float.literal.quickfix=Replace with ''{0}''
multiple.declaration.option=Ignore 'for' loop declarations
simplifiable.annotation.display.name=Simplifiable annotation
simplifiable.annotation.problem.descriptor=Unnecessary <code>#ref</code> in annotation #loc
@@ -0,0 +1,134 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.siyeh.ig.numeric;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import org.jetbrains.annotations.NotNull;
/**
* @author Bas Leijdekkers
*/
abstract class CastedLiteralMaybeJustLiteralInspection extends BaseInspection {
@Override
@NotNull
protected final String buildErrorString(Object... infos) {
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)infos[0];
final StringBuilder replacementText = buildReplacementText(typeCastExpression, new StringBuilder());
return InspectionGadgetsBundle.message("int.literal.may.be.long.literal.problem.descriptor", replacementText);
}
@NotNull
abstract String getSuffix();
@NotNull
abstract PsiType getLiteralBeforeType();
@NotNull
abstract PsiType getCastType();
private StringBuilder buildReplacementText(PsiExpression expression, StringBuilder out) {
if (expression instanceof PsiLiteralExpression) {
out.append(expression.getText()).append(getSuffix());
}
else if (expression instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
out.append(prefixExpression.getOperationSign().getText());
return buildReplacementText(prefixExpression.getOperand(), out);
}
else if (expression instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)expression;
out.append('(');
buildReplacementText(parenthesizedExpression.getExpression(), out);
out.append(')');
}
else if (expression instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)expression;
buildReplacementText(typeCastExpression.getOperand(), out);
}
else {
assert false;
}
return out;
}
@Override
protected final InspectionGadgetsFix buildFix(Object... infos) {
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)infos[0];
final StringBuilder replacementText = buildReplacementText(typeCastExpression, new StringBuilder());
return new ReplaceCastedLiteralWithJustLiteralFix(replacementText.toString());
}
private class ReplaceCastedLiteralWithJustLiteralFix extends InspectionGadgetsFix {
private final String replacementString;
public ReplaceCastedLiteralWithJustLiteralFix(String replacementString) {
this.replacementString = replacementString;
}
@Override
@NotNull
public String getName() {
return InspectionGadgetsBundle.message("int.literal.may.be.long.literal.quickfix", replacementString);
}
@NotNull
@Override
public String getFamilyName() {
return "Replace with " + getCastType().getPresentableText() + " literal";
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PsiTypeCastExpression)) {
return;
}
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)element;
PsiReplacementUtil.replaceExpression(typeCastExpression, replacementString);
}
}
@Override
public final BaseInspectionVisitor buildVisitor() {
return new CastedLiteralMayBeJustLiteralVisitor();
}
private class CastedLiteralMayBeJustLiteralVisitor extends BaseInspectionVisitor {
@Override
public void visitLiteralExpression(PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
final PsiType type = expression.getType();
if (!getLiteralBeforeType().equals(type)) {
return;
}
PsiElement parent = expression.getParent();
while (parent instanceof PsiPrefixExpression || parent instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
}
if (!(parent instanceof PsiTypeCastExpression)) {
return;
}
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)parent;
final PsiType castType = typeCastExpression.getType();
if (!getCastType().equals(castType)) {
return;
}
final PsiType expectedType = ExpectedTypeUtils.findExpectedType(typeCastExpression, false);
if (expectedType != null && !getCastType().equals(expectedType)) {
// don't warn on red code.
return;
}
registerError(typeCastExpression, typeCastExpression);
}
}
}
@@ -1,162 +1,38 @@
/*
* Copyright 2010 Bas Leijdekkers
*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.siyeh.ig.numeric;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.PsiType;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class DoubleLiteralMayBeFloatLiteralInspection extends BaseInspection {
/**
* @author Bas Leijdekkers
*/
public class DoubleLiteralMayBeFloatLiteralInspection extends CastedLiteralMaybeJustLiteralInspection {
@Override
@Nls
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"double.literal.may.be.float.literal.display.name");
return InspectionGadgetsBundle.message("double.literal.may.be.float.literal.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)infos[0];
final StringBuilder replacementText =
buildReplacementText(typeCastExpression, new StringBuilder());
return InspectionGadgetsBundle.message(
"double.literal.may.be.float.literal.problem.descriptor",
replacementText);
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)infos[0];
final StringBuilder replacementText =
buildReplacementText(typeCastExpression, new StringBuilder());
return new DoubleLiteralMayBeFloatLiteralFix(replacementText.toString());
}
private static StringBuilder buildReplacementText(
PsiExpression expression, StringBuilder out) {
if (expression instanceof PsiLiteralExpression) {
out.append(expression.getText());
out.append('f');
}
else if (expression instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression =
(PsiPrefixExpression)expression;
final PsiJavaToken sign = prefixExpression.getOperationSign();
out.append(sign.getText());
return buildReplacementText(prefixExpression.getOperand(), out);
}
else if (expression instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression =
(PsiParenthesizedExpression)expression;
out.append('(');
buildReplacementText(parenthesizedExpression.getExpression(),
out);
out.append(')');
}
else if (expression instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)expression;
final PsiExpression operand = typeCastExpression.getOperand();
buildReplacementText(operand, out);
}
else {
assert false;
}
return out;
}
private static class DoubleLiteralMayBeFloatLiteralFix
extends InspectionGadgetsFix {
private final String replacementString;
public DoubleLiteralMayBeFloatLiteralFix(String replacementString) {
this.replacementString = replacementString;
}
@Override
@NotNull
public String getName() {
return InspectionGadgetsBundle.message(
"double.literal.may.be.float.literal.quickfix",
replacementString);
}
@NotNull
@Override
public String getFamilyName() {
return "Replace with 'float'";
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PsiTypeCastExpression)) {
return;
}
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)element;
PsiReplacementUtil.replaceExpression(typeCastExpression, replacementString);
}
String getSuffix() {
return "f";
}
@NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new DoubleLiteralMayBeFloatLiteralVisitor();
PsiType getLiteralBeforeType() {
return PsiType.DOUBLE;
}
private static class DoubleLiteralMayBeFloatLiteralVisitor
extends BaseInspectionVisitor {
@Override
public void visitLiteralExpression(PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
final PsiType type = expression.getType();
if (!PsiType.DOUBLE.equals(type)) {
return;
}
PsiElement parent = expression.getParent();
while (parent instanceof PsiPrefixExpression ||
parent instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
}
if (!(parent instanceof PsiTypeCastExpression)) {
return;
}
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)parent;
final PsiType castType = typeCastExpression.getType();
if (!PsiType.FLOAT.equals(castType)) {
return;
}
registerError(typeCastExpression, typeCastExpression);
}
@NotNull
@Override
PsiType getCastType() {
return PsiType.FLOAT;
}
}
@@ -1,162 +1,38 @@
/*
* Copyright 2009-2010 Bas Leijdekkers
*
* 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.
*/
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.siyeh.ig.numeric;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.PsiType;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class IntLiteralMayBeLongLiteralInspection extends BaseInspection {
/**
* @author Bas Leijdekkers
*/
public class IntLiteralMayBeLongLiteralInspection extends CastedLiteralMaybeJustLiteralInspection {
@Override
@Nls
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"int.literal.may.be.long.literal.display.name");
return InspectionGadgetsBundle.message("int.literal.may.be.long.literal.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)infos[0];
final StringBuilder replacementText =
buildReplacementText(typeCastExpression, new StringBuilder());
return InspectionGadgetsBundle.message(
"int.literal.may.be.long.literal.problem.descriptor",
replacementText);
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)infos[0];
final StringBuilder replacementText =
buildReplacementText(typeCastExpression, new StringBuilder());
return new IntLiteralMayBeLongLiteralFix(replacementText.toString());
}
private static StringBuilder buildReplacementText(
PsiExpression expression, StringBuilder out) {
if (expression instanceof PsiLiteralExpression) {
out.append(expression.getText());
out.append('L');
}
else if (expression instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression =
(PsiPrefixExpression)expression;
final PsiJavaToken sign = prefixExpression.getOperationSign();
out.append(sign.getText());
return buildReplacementText(prefixExpression.getOperand(), out);
}
else if (expression instanceof PsiParenthesizedExpression) {
final PsiParenthesizedExpression parenthesizedExpression =
(PsiParenthesizedExpression)expression;
out.append('(');
buildReplacementText(parenthesizedExpression.getExpression(),
out);
out.append(')');
}
else if (expression instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)expression;
final PsiExpression operand = typeCastExpression.getOperand();
buildReplacementText(operand, out);
}
else {
assert false;
}
return out;
}
private static class IntLiteralMayBeLongLiteralFix
extends InspectionGadgetsFix {
private final String replacementString;
public IntLiteralMayBeLongLiteralFix(String replacementString) {
this.replacementString = replacementString;
}
@Override
@NotNull
public String getName() {
return InspectionGadgetsBundle.message(
"int.literal.may.be.long.literal.quickfix",
replacementString);
}
@NotNull
@Override
public String getFamilyName() {
return "Replace with long literal";
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PsiTypeCastExpression)) {
return;
}
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)element;
PsiReplacementUtil.replaceExpression(typeCastExpression, replacementString);
}
String getSuffix() {
return "L";
}
@NotNull
@Override
public BaseInspectionVisitor buildVisitor() {
return new IntLiteralMayBeLongLiteralVisitor();
PsiType getLiteralBeforeType() {
return PsiType.INT;
}
private static class IntLiteralMayBeLongLiteralVisitor
extends BaseInspectionVisitor {
@Override
public void visitLiteralExpression(PsiLiteralExpression expression) {
super.visitLiteralExpression(expression);
final PsiType type = expression.getType();
if (!PsiType.INT.equals(type)) {
return;
}
PsiElement parent = expression.getParent();
while (parent instanceof PsiPrefixExpression ||
parent instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
}
if (!(parent instanceof PsiTypeCastExpression)) {
return;
}
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)parent;
final PsiType castType = typeCastExpression.getType();
if (!PsiType.LONG.equals(castType)) {
return;
}
registerError(typeCastExpression, typeCastExpression);
}
@NotNull
@Override
PsiType getCastType() {
return PsiType.LONG;
}
}
@@ -0,0 +1,12 @@
class DoubleLiteralMayBeFloatLiteral {
void literal() {
System.out.println(<warning descr="'(float)1.1' could be replaced with '1.1f'">(float)1.1</warning>);
System.out.println(<warning descr="'(float)-7.3' could be replaced with '-7.3f'">(float)-7.3</warning>);
System.out.println(<warning descr="'(float)-(-((4.2)))' could be replaced with '-(-((4.2f)))'">(float)-(-((4.2)))</warning>);
}
void error() {
<error descr="Incompatible types. Found: 'float', required: 'int'">int i = (float)6.66;</error>
}
}
@@ -1,10 +0,0 @@
package com.siyeh.igtest.numeric.int_literal_may_be_long;
public class IntLiteralMayBeLong {
void foo() {
System.out.println((long) 1);
System.out.println((long) -/*yes, minus*/1);
System.out.println((long)-(-(6)));
}
}
@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>IntLiteralMayBeLong.java</file>
<line>6</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">int literal cast to long could be long literal</problem_class>
<description>&lt;code&gt;(long) 1&lt;/code&gt; could be replaced with '1L' #loc</description>
</problem>
<problem>
<file>IntLiteralMayBeLong.java</file>
<line>7</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">int literal cast to long could be long literal</problem_class>
<description>&lt;code&gt;(long) -/*yes, minus*/1&lt;/code&gt; could be replaced with '-/*yes, minus*/1L' #loc</description>
</problem>
<problem>
<file>IntLiteralMayBeLong.java</file>
<line>8</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">int literal cast to long could be long literal</problem_class>
<description>&lt;code&gt;(long)-(-(6))&lt;/code&gt; could be replaced with '-(-(6L))' #loc</description>
</problem>
</problems>
@@ -0,0 +1,14 @@
package com.siyeh.igtest.numeric.int_literal_may_be_long;
public class IntLiteralMayBeLongLiteral {
void foo() {
System.out.println(<warning descr="'(long) 1' could be replaced with '1L'">(long) 1</warning>);
System.out.println(<warning descr="'(long) -/*yes, minus*/1' could be replaced with '-1L'">(long) -/*yes, minus*/1</warning>);
System.out.println(<warning descr="'(long)-(-(6))' could be replaced with '-(-(6L))'">(long)-(-(6))</warning>);
}
void error() {
<error descr="Incompatible types. Found: 'long', required: 'int'">int answer = (long)42;</error>
}
}
@@ -0,0 +1,22 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.siyeh.ig.numeric;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class DoubleLiteralMayBeFloatLiteralInspectionTest extends LightInspectionTestCase {
public void testDoubleLiteralMayBeFloatLiteral() {
doTest();
}
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new DoubleLiteralMayBeFloatLiteralInspection();
}
}
@@ -1,11 +0,0 @@
package com.siyeh.ig.numeric;
import com.siyeh.ig.IGInspectionTestCase;
public class IntLiteralMayBeLongInspectionTest extends IGInspectionTestCase {
public void test() {
doTest("com/siyeh/igtest/numeric/int_literal_may_be_long",
new IntLiteralMayBeLongLiteralInspection());
}
}
@@ -0,0 +1,22 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.siyeh.ig.numeric;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class IntLiteralMayBeLongLiteralInspectionTest extends LightInspectionTestCase {
public void testIntLiteralMayBeLongLiteral() {
doTest();
}
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new IntLiteralMayBeLongLiteralInspection();
}
}