IDEA-187211 Suggest using StandardCharsets.XYZ instead of "XYZ" where possible

This commit is contained in:
Tagir Valeev
2018-03-06 18:00:32 +07:00
parent 8568d85a4e
commit 35dff9c9a4
22 changed files with 606 additions and 15 deletions
@@ -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"/>
<localInspection groupPath="Java" language="JAVA" shortName="CharsetObjectCanBeUsed" bundle="messages.InspectionsBundle"
key="inspection.charset.object.can.be.used.display.name" groupKey="group.names.code.style.issues"
enabledByDefault="true" level="WARNING" cleanupTool="true"
implementationClass="com.intellij.codeInspection.CharsetObjectCanBeUsedInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="UnusedAssignment" displayName="Unused assignment" groupKey="group.names.probable.bugs" groupBundle="messages.InspectionsBundle" enabledByDefault="true"
level="WARNING" implementationClass="com.intellij.codeInspection.defUse.DefUseInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="ConstantConditions" bundle="messages.InspectionsBundle" key="inspection.data.flow.display.name"
@@ -55,7 +55,21 @@ public class DeleteCatchFix implements IntentionAction {
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) {
final PsiTryStatement tryStatement = ((PsiCatchSection)myCatchParameter.getDeclarationScope()).getTryStatement();
PsiElement previousElement = deleteCatch(myCatchParameter);
if (previousElement != null) {
//move caret to previous catch section
editor.getCaretModel().moveToOffset(previousElement.getTextRange().getEndOffset());
}
}
/**
* Deletes catch section
*
* @param catchParameter the catchParameter in the section to delete (must be a catch parameter)
* @return the physical element before the deleted catch section, if available. Can be used to position the editor cursor after deletion.
*/
public static PsiElement deleteCatch(PsiParameter catchParameter) {
final PsiTryStatement tryStatement = ((PsiCatchSection)catchParameter.getDeclarationScope()).getTryStatement();
if (tryStatement.getCatchBlocks().length == 1 && tryStatement.getFinallyBlock() == null && tryStatement.getResourceList() == null) {
// unwrap entire try statement
final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
@@ -80,15 +94,12 @@ public class DeleteCatchFix implements IntentionAction {
}
}
tryStatement.delete();
if (lastAddedStatement != null) {
editor.getCaretModel().moveToOffset(lastAddedStatement.getTextRange().getEndOffset());
}
return;
return lastAddedStatement;
}
// delete catch section
final PsiElement catchSection = myCatchParameter.getParent();
final PsiElement catchSection = catchParameter.getParent();
assert catchSection instanceof PsiCatchSection : catchSection;
//save previous element to move caret to
PsiElement previousElement = catchSection.getPrevSibling();
@@ -96,10 +107,7 @@ public class DeleteCatchFix implements IntentionAction {
previousElement = previousElement.getPrevSibling();
}
catchSection.delete();
if (previousElement != null) {
//move caret to previous catch section
editor.getCaretModel().moveToOffset(previousElement.getTextRange().getEndOffset());
}
return previousElement;
}
@Override
@@ -61,23 +61,27 @@ public class DeleteMultiCatchFix implements IntentionAction {
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
final PsiElement parentType = myTypeElement.getParent();
deleteCaughtExceptionType(myTypeElement);
}
public static void deleteCaughtExceptionType(@NotNull PsiTypeElement typeElement) {
final PsiElement parentType = typeElement.getParent();
if (!(parentType instanceof PsiTypeElement)) return;
final PsiElement first;
final PsiElement last;
final PsiElement right = PsiTreeUtil.skipWhitespacesAndCommentsForward(myTypeElement);
final PsiElement right = PsiTreeUtil.skipWhitespacesAndCommentsForward(typeElement);
if (PsiUtil.isJavaToken(right, JavaTokenType.OR)) {
first = myTypeElement;
first = typeElement;
last = right;
}
else if (right == null) {
final PsiElement left = PsiTreeUtil.skipWhitespacesAndCommentsBackward(myTypeElement);
final PsiElement left = PsiTreeUtil.skipWhitespacesAndCommentsBackward(typeElement);
if (!(left instanceof PsiJavaToken)) return;
final IElementType leftType = ((PsiJavaToken)left).getTokenType();
if (leftType != JavaTokenType.OR) return;
first = left;
last = myTypeElement;
last = typeElement;
}
else {
return;
@@ -0,0 +1,267 @@
// 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.codeInspection;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.DeleteCatchFix;
import com.intellij.codeInsight.daemon.impl.quickfix.DeleteMultiCatchFix;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ExpressionUtils;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import static com.intellij.psi.CommonClassNames.*;
public class CharsetObjectCanBeUsedInspection extends AbstractBaseJavaLocalInspectionTool implements CleanupLocalInspectionTool {
private static final CharsetCallMatcher[] MATCHERS = {
new CharsetConstructorMatcher("java.io.InputStreamReader", "java.io.InputStream", ""),
new CharsetConstructorMatcher("java.io.OutputStreamWriter", "java.io.OutputStream", ""),
new CharsetConstructorMatcher(JAVA_LANG_STRING, "byte[]", "int", "int", ""),
new CharsetConstructorMatcher(JAVA_LANG_STRING, "byte[]", ""),
new CharsetMethodMatcher(JAVA_LANG_STRING, "getBytes", ""),
// Java 10
new CharsetConstructorMatcher("java.util.Scanner", "java.io.InputStream", ""),
new CharsetConstructorMatcher("java.util.Scanner", JAVA_IO_FILE, ""),
new CharsetConstructorMatcher("java.util.Scanner", "java.nio.file.Path", ""),
new CharsetConstructorMatcher("java.util.Scanner", "java.nio.channels.ReadableByteChannel", ""),
new CharsetConstructorMatcher("java.io.PrintStream", "java.io.OutputStream", "boolean", ""),
new CharsetConstructorMatcher("java.io.PrintStream", JAVA_LANG_STRING, ""),
new CharsetConstructorMatcher("java.io.PrintStream", JAVA_IO_FILE, ""),
new CharsetConstructorMatcher("java.io.PrintWriter", "java.io.OutputStream", "boolean", ""),
new CharsetConstructorMatcher("java.io.PrintWriter", JAVA_LANG_STRING, ""),
new CharsetConstructorMatcher("java.io.PrintWriter", JAVA_IO_FILE, ""),
new CharsetMethodMatcher("java.io.ByteArrayOutputStream", "toString", ""),
new CharsetMethodMatcher("java.net.URLDecoder", "decode", JAVA_LANG_STRING, ""),
new CharsetMethodMatcher("java.net.URLEncoder", "encode", JAVA_LANG_STRING, ""),
new CharsetMethodMatcher("java.nio.channels.Channels", "newReader", "java.nio.channels.ReadableByteChannel", ""),
new CharsetMethodMatcher("java.nio.channels.Channels", "newWriter", "java.nio.channels.WritableByteChannel", ""),
new CharsetMethodMatcher(JAVA_UTIL_PROPERTIES, "storeToXML", "java.io.OutputStream", JAVA_LANG_STRING, ""),
};
private static final Set<String> 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<PsiTypeElement> typeElements = PsiUtil.getParameterTypeElements(parameter);
for (PsiTypeElement element : typeElements) {
PsiType type = element.getType();
if (type.equalsToText("java.io.UnsupportedEncodingException") ||
type.equalsToText("java.io.IOException")) {
Collection<PsiClassType> 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;
}
}
}
}
@@ -0,0 +1,10 @@
<html>
<body>
Reports methods and constructors where constant charset String literal is used (like <b>"UTF-8"</b>) which could be replaced with
a predefined Charset object like <b>StandardCharsets.UTF_8</b>. This may work a little bit faster, because charset lookup becomes
unnecessary. Also catching <b>UnsupportedEncodingException</b> may become unnecessary as well. In this case the catch block will
be removed automatically.
<!-- tooltip end -->
<p><small>New in 2018.2</small></p>
</body>
</html>
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -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!");
}
}
}
@@ -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-<caret>ASCII");
}
catch (UnsupportedEncodingException | StackOverflowError exception) {
exception.printStackTrace();
}
if(bytes[0] == 'a') {
System.out.println("A-a-a!");
}
}
}
@@ -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<caret>-1");
if(string.startsWith("Foo")) {
System.out.println("It's a foo!");
}
}
}
@@ -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, UTF<caret>16);
}
catch (UnsupportedEncodingException exception) {
exception.printStackTrace();
}
if(string.startsWith("Foo")) {
System.out.println("It's a foo!");
}
}
}
@@ -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, UTF<caret>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!");
}
}
}
@@ -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_ENCO<caret>DING);
}
catch (UnsupportedEncodingException exception) {
exception.printStackTrace();
}
if(string.startsWith("Foo")) {
System.out.println("It's a foo!");
}
}
}
@@ -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<caret>-16");
}
catch (UnsupportedEncodingException exception) {
exception.printStackTrace();
}
catch (Throwable t) {
return;
}
if(string.startsWith("Foo")) {
System.out.println("It's a foo!");
}
}
}
@@ -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<caret>-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!");
}
}
}
@@ -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<caret>-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!");
}
}
}
@@ -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/";
}
}
@@ -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}''