diff --git a/java/java-impl/src/META-INF/JavaPlugin.xml b/java/java-impl/src/META-INF/JavaPlugin.xml index 75e57e6ea70a..3994aefd5622 100644 --- a/java/java-impl/src/META-INF/JavaPlugin.xml +++ b/java/java-impl/src/META-INF/JavaPlugin.xml @@ -743,6 +743,10 @@ key="inspection.redundant.array.creation.display.name" groupKey="group.names.verbose.or.redundant.code.constructs" enabledByDefault="true" level="WARNING" cleanupTool="true" implementationClass="com.intellij.codeInspection.miscGenerics.RedundantArrayForVarargsCallInspection"/> + SUPPORTED_CHARSETS = + ContainerUtil.immutableSet("US-ASCII", "ISO-8859-1", "UTF-8", "UTF-16BE", "UTF-16LE", "UTF-16"); + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { + if (!PsiUtil.isLanguageLevel7OrHigher(holder.getFile())) return PsiElementVisitor.EMPTY_VISITOR; + return new JavaElementVisitor() { + @Override + public void visitCallExpression(PsiCallExpression call) { + CharsetMatch match = StreamEx.of(MATCHERS) + .map(matcher -> matcher.extractCharsetMatch(call)) + .nonNull() + .findFirst().orElse(null); + if (match == null) return; + String charsetString = getCharsetString(match.myStringCharset); + if (charsetString == null) return; + String constantName = "StandardCharsets." + charsetString.replace('-', '_'); + holder + .registerProblem(match.myStringCharset, InspectionsBundle.message("inspection.charset.object.can.be.used.message", constantName), + new CharsetObjectCanBeUsedFix(constantName)); + } + + @Nullable + private String getCharsetString(PsiExpression charsetExpression) { + charsetExpression = PsiUtil.skipParenthesizedExprDown(charsetExpression); + String charsetString = ObjectUtils.tryCast(ExpressionUtils.computeConstantExpression(charsetExpression), String.class); + if (charsetString == null || !SUPPORTED_CHARSETS.contains(charsetString)) return null; + if (charsetExpression instanceof PsiLiteralExpression) return charsetString; + if (charsetExpression instanceof PsiReferenceExpression) { + String name = ((PsiReferenceExpression)charsetExpression).getReferenceName(); + if (name == null) return null; + String baseName = name.replaceAll("[^A-Z0-9]", "").toLowerCase(Locale.ENGLISH); + String baseCharset = charsetString.replaceAll("[^A-Z0-9]", "").toLowerCase(Locale.ENGLISH); + // Do not report constants which name is not based on charset name (like "ENCODING", "DEFAULT_ENCODING", etc.) + // because replacement might not be well-suitable + if (!baseName.contains(baseCharset)) return null; + return charsetString; + } + return null; + } + }; + } + + abstract static class CharsetCallMatcher { + @NotNull final String myClassName; + @NotNull final String[] myParameters; + final int myCharsetParameterIndex; + + CharsetCallMatcher(@NotNull String className, @NotNull String... parameters) { + myClassName = className; + myParameters = parameters; + int index = -1; + for (int i = 0; i < parameters.length; i++) { + if (parameters[i].isEmpty()) { + if (index == -1) { + index = i; + } + else { + throw new IllegalArgumentException("Empty parameter type must be specified exactly once"); + } + } + } + if (index == -1) { + throw new IllegalArgumentException("No empty parameter type is specified"); + } + myCharsetParameterIndex = index; + } + + @Contract("null,_ -> false") + final boolean checkMethod(PsiMethod method, @NotNull String charsetType) { + if (method == null) return false; + PsiClass containingClass = method.getContainingClass(); + if (containingClass == null || !myClassName.equals(containingClass.getQualifiedName())) return false; + PsiParameterList list = method.getParameterList(); + if (list.getParametersCount() != myParameters.length) return false; + PsiParameter[] parameters = list.getParameters(); + for (int i = 0; i < myParameters.length; i++) { + PsiType parameterType = parameters[i].getType(); + if (!parameterType.equalsToText(myParameters[i].isEmpty() ? charsetType : myParameters[i])) return false; + } + return true; + } + + @Nullable + final CharsetMatch createMatch(PsiMethod method, PsiExpressionList arguments) { + PsiExpression argument = arguments.getExpressions()[myCharsetParameterIndex]; + PsiClass aClass = method.getContainingClass(); + if (aClass == null) return null; + + PsiMethod[] candidates = method.isConstructor() ? aClass.getConstructors() : aClass.findMethodsByName(method.getName(), false); + PsiMethod charsetMethod = Arrays.stream(candidates) + .filter(psiMethod -> checkMethod(psiMethod, "java.nio.charset.Charset")) + .findFirst().orElse(null); + if (charsetMethod == null) return null; + return new CharsetMatch(argument, method, charsetMethod); + } + + @Nullable + abstract CharsetMatch extractCharsetMatch(PsiCallExpression call); + } + + static class CharsetConstructorMatcher extends CharsetCallMatcher { + CharsetConstructorMatcher(@NotNull String className, @NotNull String... parameters) { + super(className, parameters); + } + + @Override + CharsetMatch extractCharsetMatch(PsiCallExpression call) { + if (!(call instanceof PsiNewExpression)) return null; + PsiNewExpression newExpression = (PsiNewExpression)call; + PsiExpressionList argumentList = newExpression.getArgumentList(); + if (argumentList == null || argumentList.getExpressionCount() != myParameters.length) return null; + PsiMethod method = call.resolveMethod(); + if (!checkMethod(method, JAVA_LANG_STRING) || !method.isConstructor()) return null; + return createMatch(method, argumentList); + } + } + + static class CharsetMethodMatcher extends CharsetCallMatcher { + @NotNull private final String myMethodName; + + CharsetMethodMatcher(@NotNull String className, @NotNull String methodName, @NotNull String... parameters) { + super(className, parameters); + myMethodName = methodName; + } + + @Override + CharsetMatch extractCharsetMatch(PsiCallExpression call) { + if (!(call instanceof PsiMethodCallExpression)) return null; + PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)call; + if (!myMethodName.equals(methodCallExpression.getMethodExpression().getReferenceName())) return null; + PsiExpressionList argumentList = methodCallExpression.getArgumentList(); + if (argumentList.getExpressionCount() != myParameters.length) return null; + PsiMethod method = call.resolveMethod(); + if (!checkMethod(method, JAVA_LANG_STRING)) return null; + return createMatch(method, argumentList); + } + } + + static class CharsetMatch { + @NotNull final PsiExpression myStringCharset; + @NotNull final PsiMethod myStringMethod; + @NotNull final PsiMethod myCharsetMethod; + + CharsetMatch(@NotNull PsiExpression charset, @NotNull PsiMethod stringMethod, @NotNull PsiMethod charsetMethod) { + myStringCharset = charset; + myStringMethod = stringMethod; + myCharsetMethod = charsetMethod; + } + } + + static class CharsetObjectCanBeUsedFix implements LocalQuickFix { + private final String myConstantName; + + public CharsetObjectCanBeUsedFix(String constantName) { + myConstantName = constantName; + } + + @Nls + @NotNull + @Override + public String getName() { + return InspectionsBundle.message("inspection.charset.object.can.be.used.fix.name", myConstantName); + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return InspectionsBundle.message("inspection.charset.object.can.be.used.fix.family.name"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + PsiExpression expression = ObjectUtils.tryCast(descriptor.getStartElement(), PsiExpression.class); + if (expression == null) return; + PsiElement anchor = PsiTreeUtil.getParentOfType(expression, PsiCallExpression.class); + if (anchor == null) return; + CommentTracker ct = new CommentTracker(); + JavaCodeStyleManager.getInstance(project) + .shortenClassReferences(ct.replaceAndRestoreComments(expression, "java.nio.charset." + myConstantName)); + while (true) { + PsiTryStatement tryStatement = + PsiTreeUtil.getParentOfType(anchor, PsiTryStatement.class, true, PsiMember.class, PsiLambdaExpression.class); + if (tryStatement == null) break; + PsiCodeBlock tryBlock = tryStatement.getTryBlock(); + if (PsiTreeUtil.isAncestor(tryBlock, anchor, true)) { + for (PsiParameter parameter : tryStatement.getCatchBlockParameters()) { + List typeElements = PsiUtil.getParameterTypeElements(parameter); + for (PsiTypeElement element : typeElements) { + PsiType type = element.getType(); + if (type.equalsToText("java.io.UnsupportedEncodingException") || + type.equalsToText("java.io.IOException")) { + Collection unhandledExceptions = ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock); + if(unhandledExceptions.stream().noneMatch(ue -> ue.isAssignableFrom(type) || type.isAssignableFrom(ue))) { + if(parameter.getType() instanceof PsiDisjunctionType) { + DeleteMultiCatchFix.deleteCaughtExceptionType(element); + } else { + DeleteCatchFix.deleteCatch(parameter); + } + } + return; + } + if (type.equalsToText(JAVA_LANG_EXCEPTION) || type.equalsToText(JAVA_LANG_THROWABLE)) { + return; + } + } + } + } + anchor = tryStatement; + } + } + } +} diff --git a/java/java-impl/src/inspectionDescriptions/CharsetObjectCanBeUsed.html b/java/java-impl/src/inspectionDescriptions/CharsetObjectCanBeUsed.html new file mode 100644 index 000000000000..3ceb82126be1 --- /dev/null +++ b/java/java-impl/src/inspectionDescriptions/CharsetObjectCanBeUsed.html @@ -0,0 +1,10 @@ + + +Reports methods and constructors where constant charset String literal is used (like "UTF-8") which could be replaced with +a predefined Charset object like StandardCharsets.UTF_8. This may work a little bit faster, because charset lookup becomes +unnecessary. Also catching UnsupportedEncodingException may become unnecessary as well. In this case the catch block will +be removed automatically. + +

New in 2018.2

+ + \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterGetBytesMultiCatch.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterGetBytesMultiCatch.java new file mode 100644 index 000000000000..9fcd567eaeb7 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterGetBytesMultiCatch.java @@ -0,0 +1,17 @@ +// "Replace with 'StandardCharsets.US_ASCII'" "true" +import java.io.*; + +class Test { + void test(String s) { + byte[] bytes = null; + try { + string = s.getBytes(java.nio.charset.StandardCharsets.US_ASCII); + } + catch (StackOverflowError exception) { + exception.printStackTrace(); + } + if(bytes[0] == 'a') { + System.out.println("A-a-a!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringThrow.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringThrow.java new file mode 100644 index 000000000000..3eb67a5c60a3 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringThrow.java @@ -0,0 +1,11 @@ +// "Replace with 'StandardCharsets.ISO_8859_1'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + void test(byte[] bytes) throws UnsupportedEncodingException { + String string = new String(bytes, 0, 100, java.nio.charset.StandardCharsets.ISO_8859_1); + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEE.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEE.java new file mode 100644 index 000000000000..d06f27cda108 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEE.java @@ -0,0 +1,14 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + static final String UTF16 = "UTF-16"; + + void test(byte[] bytes) { + String string = null; + string = new String(bytes, java.nio.charset.StandardCharsets.UTF_16); + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEE2.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEE2.java new file mode 100644 index 000000000000..5815202cbb63 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEE2.java @@ -0,0 +1,22 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + static final String UTF16 = "UTF-16"; + + void test(byte[] bytes) { + String string = null; + String string2 = null; + try { + string = new String(bytes, java.nio.charset.StandardCharsets.UTF_16); + string2 = new String(bytes, "UTF-8"); + } + // catch is still necessary after the single replacement + catch (UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEEDoubleCatch.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEEDoubleCatch.java new file mode 100644 index 000000000000..9d2a92d3f601 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEEDoubleCatch.java @@ -0,0 +1,16 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + void test(byte[] bytes) { + String string = null; + try { + string = new String(bytes, java.nio.charset.StandardCharsets.UTF_16); + } catch (Throwable t) { + return; + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEENestedTry.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEENestedTry.java new file mode 100644 index 000000000000..2fe65c60cd67 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEENestedTry.java @@ -0,0 +1,15 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +class Test { + void test(byte[] bytes) { + String string = null; + try { + string = new String(bytes, java.nio.charset.StandardCharsets.UTF_16); + } + catch (NullPointerException exception) { + System.out.println("ex1"); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEENestedTry2.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEENestedTry2.java new file mode 100644 index 000000000000..f421d4ac0aca --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/afterStringUEENestedTry2.java @@ -0,0 +1,21 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +class Test { + void test(byte[] bytes) { + String string = null; + try { + try { + string = new String(bytes, java.nio.charset.StandardCharsets.UTF_16); + } + catch (Exception exception) { + System.out.println("ex1"); + } + } + // this catch is already unnecessary, so don't remove it + catch (java.io.UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeGetBytesMultiCatch.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeGetBytesMultiCatch.java new file mode 100644 index 000000000000..98cf59b51542 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeGetBytesMultiCatch.java @@ -0,0 +1,17 @@ +// "Replace with 'StandardCharsets.US_ASCII'" "true" +import java.io.*; + +class Test { + void test(String s) { + byte[] bytes = null; + try { + string = s.getBytes("US-ASCII"); + } + catch (UnsupportedEncodingException | StackOverflowError exception) { + exception.printStackTrace(); + } + if(bytes[0] == 'a') { + System.out.println("A-a-a!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringThrow.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringThrow.java new file mode 100644 index 000000000000..60571918c64e --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringThrow.java @@ -0,0 +1,11 @@ +// "Replace with 'StandardCharsets.ISO_8859_1'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + void test(byte[] bytes) throws UnsupportedEncodingException { + String string = new String(bytes, 0, 100, "ISO-8859-1"); + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEE.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEE.java new file mode 100644 index 000000000000..be8e8f4e0845 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEE.java @@ -0,0 +1,19 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + static final String UTF16 = "UTF-16"; + + void test(byte[] bytes) { + String string = null; + try { + string = new String(bytes, UTF16); + } + catch (UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEE2.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEE2.java new file mode 100644 index 000000000000..e948828c0fd0 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEE2.java @@ -0,0 +1,22 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + static final String UTF16 = "UTF-16"; + + void test(byte[] bytes) { + String string = null; + String string2 = null; + try { + string = new String(bytes, UTF16); + string2 = new String(bytes, "UTF-8"); + } + // catch is still necessary after the single replacement + catch (UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEECustomConstant.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEECustomConstant.java new file mode 100644 index 000000000000..aa282a7154c3 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEECustomConstant.java @@ -0,0 +1,20 @@ +// "Replace with 'StandardCharsets.UTF_16'" "false" +import java.io.UnsupportedEncodingException; + +class Test { + static final String MY_ENCODING = "UTF-16"; + + void test(byte[] bytes) { + String string = null; + try { + // Do not suggest the replacement as "MY_ENCODING" could be a tuneable constant + string = new String(bytes, MY_ENCODING); + } + catch (UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEEDoubleCatch.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEEDoubleCatch.java new file mode 100644 index 000000000000..bd9713d732d9 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEEDoubleCatch.java @@ -0,0 +1,20 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +import java.io.UnsupportedEncodingException; + +class Test { + void test(byte[] bytes) { + String string = null; + try { + string = new String(bytes, "UTF-16"); + } + catch (UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + catch (Throwable t) { + return; + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEENestedTry.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEENestedTry.java new file mode 100644 index 000000000000..004125d55db4 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEENestedTry.java @@ -0,0 +1,20 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +class Test { + void test(byte[] bytes) { + String string = null; + try { + try { + string = new String(bytes, "UTF-16"); + } + catch (NullPointerException exception) { + System.out.println("ex1"); + } + } + catch (java.io.UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEENestedTry2.java b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEENestedTry2.java new file mode 100644 index 000000000000..a1dab5763ac5 --- /dev/null +++ b/java/java-tests/testData/inspection/charsetObjectCanBeUsed/beforeStringUEENestedTry2.java @@ -0,0 +1,21 @@ +// "Replace with 'StandardCharsets.UTF_16'" "true" +class Test { + void test(byte[] bytes) { + String string = null; + try { + try { + string = new String(bytes, "UTF-16"); + } + catch (Exception exception) { + System.out.println("ex1"); + } + } + // this catch is already unnecessary, so don't remove it + catch (java.io.UnsupportedEncodingException exception) { + exception.printStackTrace(); + } + if(string.startsWith("Foo")) { + System.out.println("It's a foo!"); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/CharsetObjectCanBeUsedInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/CharsetObjectCanBeUsedInspectionTest.java new file mode 100644 index 000000000000..e8e76197dbb9 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/CharsetObjectCanBeUsedInspectionTest.java @@ -0,0 +1,27 @@ +// Copyright 2000-2018 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.intellij.java.codeInspection; + +import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase; +import com.intellij.codeInspection.CharsetObjectCanBeUsedInspection; +import com.intellij.codeInspection.LocalInspectionTool; +import org.jetbrains.annotations.NotNull; + +/** + * @author Tagir Valeev + */ +public class CharsetObjectCanBeUsedInspectionTest extends LightQuickFixParameterizedTestCase { + @NotNull + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[]{new CharsetObjectCanBeUsedInspection()}; + } + + public void test() { + doAllTests(); + } + + @Override + protected String getBasePath() { + return "/inspection/charsetObjectCanBeUsed/"; + } +} diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index fa41e2cb71d9..ec81807052b7 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -956,3 +956,8 @@ inspection.redundant.explicit.close=Redundant close inspection.redundant.explicit.close.fix.name=Remove redundant close inspection.fold.expression.into.stream.display.name=Expression can be folded into Stream chain inspection.fold.expression.into.stream.fix.name=Fold expression into Stream chain + +inspection.charset.object.can.be.used.display.name=Standard Charset object can be used +inspection.charset.object.can.be.used.message={0} can be used instead +inspection.charset.object.can.be.used.fix.family.name=Use Charset constant +inspection.charset.object.can.be.used.fix.name=Replace with ''{0}'' \ No newline at end of file