From e207c2686d9ecd807b861fcab7131e100ad84186 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 18 Jul 2012 13:07:44 +0200 Subject: [PATCH] new "String literal concatenation missing whitespace" inspection --- .../InspectionGadgets/src/META-INF/plugin.xml | 44 +++++++ .../siyeh/InspectionGadgetsBundle.properties | 7 +- ...catenationMissingWhitespaceInspection.java | 123 ++++++++++++++++++ .../StringConcatenationMissingWhitespace.html | 15 +++ .../Concatenations.java | 11 ++ .../expected.xml | 16 +++ ...nationMissingWhitespaceInspectionTest.java | 10 ++ 7 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java create mode 100644 plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/expected.xml create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspectionTest.java diff --git a/plugins/InspectionGadgets/src/META-INF/plugin.xml b/plugins/InspectionGadgets/src/META-INF/plugin.xml index 7dbfac0d2287..0b8b5b3f5540 100644 --- a/plugins/InspectionGadgets/src/META-INF/plugin.xml +++ b/plugins/InspectionGadgets/src/META-INF/plugin.xml @@ -11,6 +11,7 @@ + @@ -78,6 +79,7 @@ groupBundle="messages.InspectionsBundle" groupKey="group.names.abstraction.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.abstraction.TypeMayBeWeakenedInspection"/> + + + + + @@ -490,6 +499,7 @@ groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.classlayout.MethodReturnAlwaysConstantInspection"/> + + + @@ -715,6 +727,7 @@ groupKey="group.names.control.flow.issues" enabledByDefault="true" level="WARNING" implementationClass="com.siyeh.ig.controlflow.UnnecessaryReturnInspection"/> + + + @@ -801,6 +816,7 @@ groupBundle="messages.InspectionsBundle" groupKey="group.names.encapsulation.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.encapsulation.UseOfAnotherObjectsPrivateFieldInspection"/> + + + @@ -933,6 +951,7 @@ groupBundle="messages.InspectionsBundle" groupKey="group.names.imports" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.imports.UnusedImportInspection"/> + + + @@ -1083,6 +1104,7 @@ groupKey="group.names.internationalization.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.internationalization.AbsoluteAlignmentInUserInterfaceInspection"/> + + + + + @@ -1254,6 +1280,7 @@ groupKey="group.names.java.language.level.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.jdk.VarargParameterInspection"/> + + @@ -1398,6 +1426,7 @@ groupKey="group.names.logging.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.logging.PublicMethodWithoutLoggingInspection"/> + + @@ -1435,6 +1465,7 @@ groupBundle="messages.InspectionsBundle" groupKey="group.names.memory.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.memory.ZeroLengthArrayInitializationInspection"/> + + + + @@ -1707,6 +1741,7 @@ groupKey="group.names.numeric.issues" enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.numeric.UnpredictableBigDecimalConstructorCallInspection"/> + + + + + + + + + + diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 7ca486417e2c..ebfdfd0397cb 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1958,7 +1958,10 @@ string.builder.replaceable.by.string.quickfix=Replace 'StringBuilder' with 'Stri string.buffer.replaceable.by.string.quickfix=Replace 'StringBuffer' with 'String' add.0.to.ignore.if.annotated.by.list.quickfix=Add ''{0}'' to ''Ignore if annotated by'' list non.final.field.in.enum.display.name=Non-'final' field in enum -non.final.field.in.enum.problem.descriptor=non-''final'' field #ref in enum ''{0}'' +non.final.field.in.enum.problem.descriptor=non-''final'' field #ref in enum ''{0}'' #loc externalizable.without.public.no.arg.constructor.display.name=Externalizable class without public no-arg constructor -externalizable.without.public.no.arg.constructor.problem.descriptor=Externalizable class #ref has no public no-arg constructor +externalizable.without.public.no.arg.constructor.problem.descriptor=Externalizable class #ref has no public no-arg constructor #loc make.constructor.public=Make constructor 'public' +string.concatenation.missing.whitespace.display.name=String literal concatenation missing whitespace +string.concatenation.missing.whitespace.problem.descriptor=String literal concatenation missing whitespace #loc +string.concatenation.missing.whitespace.option=Ignore when not both sides are string literals diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java new file mode 100644 index 000000000000..345f6da292a4 --- /dev/null +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspection.java @@ -0,0 +1,123 @@ +/* + * Copyright 2000-2012 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.ui.SingleCheckboxOptionsPanel; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.BaseInspection; +import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.psiutils.ParenthesesUtils; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * @author Bas Leijdekkers + */ +public class StringConcatenationMissingWhitespaceInspection extends BaseInspection { + + @SuppressWarnings("PublicField") + public boolean ignoreNonStringLiterals = false; + + @NotNull + @Override + protected String buildErrorString(Object... infos) { + return InspectionGadgetsBundle.message("string.concatenation.missing.whitespace.problem.descriptor"); + } + + @Override + public JComponent createOptionsPanel() { + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("string.concatenation.missing.whitespace.option"), + this, "ignoreNonStringLiterals"); + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new StringConcatenationMissingWhitespaceVisitor(); + } + + private class StringConcatenationMissingWhitespaceVisitor extends BaseInspectionVisitor { + + @Override + public void visitPolyadicExpression(PsiPolyadicExpression expression) { + super.visitPolyadicExpression(expression); + final IElementType tokenType = expression.getOperationTokenType(); + if (!JavaTokenType.PLUS.equals(tokenType) || !hasStringType(expression)) { + return; + } + final PsiExpression[] operands = expression.getOperands(); + PsiExpression lhs = operands[0]; + for (int i = 1; i < operands.length; i++) { + final PsiExpression rhs = operands[i]; + if (isMissingWhitespace(lhs, rhs)) { + final PsiJavaToken token = expression.getTokenBeforeOperand(rhs); + if (token != null) { + registerError(token); + } + } + lhs = rhs; + } + } + + private boolean isMissingWhitespace(PsiExpression lhs, PsiExpression rhs) { + if (isLiteral(lhs) && hasStringType(lhs)) { + final PsiLiteralExpression literalExpression = (PsiLiteralExpression)lhs; + final String value = (String)literalExpression.getValue(); + if (value == null) { + return false; + } + final int length = value.length(); + if (length == 0) { + return false; + } + final char c = value.charAt(length - 1); + if (Character.isWhitespace(c) || !Character.isLetterOrDigit(c)) { + return false; + } + } + else if (ignoreNonStringLiterals || !isLiteral(rhs) || hasStringType(lhs)) { + return false; + } + if (isLiteral(rhs) && hasStringType(rhs)) { + final PsiLiteralExpression literalExpression = (PsiLiteralExpression)rhs; + final String value = (String)literalExpression.getValue(); + if ((value == null) || (value.length() == 0)) { + return false; + } + final char c = value.charAt(0); + if (Character.isWhitespace(c) || !Character.isLetterOrDigit(c)) { + return false; + } + } + else if (ignoreNonStringLiterals || hasStringType(rhs)) { + return false; + } + return true; + } + + private boolean isLiteral(PsiExpression expression) { + expression = ParenthesesUtils.stripParentheses(expression); + return expression instanceof PsiLiteralExpression; + } + + private boolean hasStringType(PsiExpression expression) { + final PsiType type = expression.getType(); + return (type != null) && type.equalsToText(CommonClassNames.JAVA_LANG_STRING); + } + } +} diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html new file mode 100644 index 000000000000..b879ca34e3f3 --- /dev/null +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenationMissingWhitespace.html @@ -0,0 +1,15 @@ + + +This inspection reports string concatenations where the left literal does not +end with whitespace and the right literal does not start with whitespace. For example: +

+  String sql = "SELECT column" +
+               "FROM table";
+
+ +

+Use the checkbox below to have this inspection only report when both the left and right side of the concatenation are string literals. +

+New in 12, Powered by InspectionGadgets + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java new file mode 100644 index 000000000000..22f32e5eb3f4 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/Concatenations.java @@ -0,0 +1,11 @@ +package com.siyeh.igtest.bugs.string_concatenation_missing_whitespace; + +class Concatenations { + + void foo(int i) { + System.out.println("SELECT column" + + "FROM table"); + System.out.println("no:" + i); + System.out.println("i" + i); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/expected.xml new file mode 100644 index 000000000000..5d357b03b8d2 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/string_concatenation_missing_whitespace/expected.xml @@ -0,0 +1,16 @@ + + + + Concatenations.java + 6 + String literal concatenation missing whitespace + String literal concatenation missing whitespace #loc + + + + Concatenations.java + 9 + String literal concatenation missing whitespace + String literal concatenation missing whitespace #loc + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspectionTest.java new file mode 100644 index 000000000000..38f9760d2925 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StringConcatenationMissingWhitespaceInspectionTest.java @@ -0,0 +1,10 @@ +package com.siyeh.ig.bugs; + +import com.siyeh.ig.IGInspectionTestCase; + +public class StringConcatenationMissingWhitespaceInspectionTest extends IGInspectionTestCase { + + public void test() throws Exception { + doTest("com/siyeh/igtest/bugs/string_concatenation_missing_whitespace", new StringConcatenationMissingWhitespaceInspection()); + } +} \ No newline at end of file