diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java index 2bf512ceb91b..07279e9b2c1a 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java @@ -30,7 +30,12 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.TypeUtils; -import org.jetbrains.annotations.*; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.stream.Stream; /** * @author Bas Leijdekkers @@ -55,29 +60,58 @@ public class ImplicitDefaultCharsetUsageInspection extends BaseInspection { } } - private static final Key HAS_CHARSET_OVERLOAD = Key.create("Method has Charset overload"); + enum CharsetOverload { + EXIST, EXIST_WITH_FALSE, NONE; - @Contract("null -> false") - private static boolean hasCharsetOverload(PsiMethod method) { - if (method == null) return false; - Boolean hasCharsetOverload = method.getUserData(HAS_CHARSET_OVERLOAD); - if (hasCharsetOverload == null) { + InspectionGadgetsFix createFix() { + return this == NONE ? null : new AddUtf8CharsetFix(this); + } + + Stream additionalArguments() { + switch (this) { + case EXIST: + return Stream.of("java.nio.charset.StandardCharsets.UTF_8"); + case EXIST_WITH_FALSE: + return Stream.of("false", "java.nio.charset.StandardCharsets.UTF_8"); + default: + throw new IllegalStateException(this.toString()); + } + } + } + + private static final Key HAS_CHARSET_OVERLOAD = Key.create("Method has Charset overload"); + + @NotNull + private static CharsetOverload getCharsetOverload(PsiMethod method) { + if (method == null) return CharsetOverload.NONE; + + CharsetOverload charsetOverload = method.getUserData(HAS_CHARSET_OVERLOAD); + if (charsetOverload == null) { PsiMethod methodWithCharsetArgument = null; PsiClass aClass = method.getContainingClass(); + charsetOverload = CharsetOverload.EXIST; if (aClass != null) { MethodSignature signature = method.getSignature(PsiSubstitutor.EMPTY); PsiType charsetType = JavaPsiFacade.getElementFactory(method.getProject()).createTypeByFQClassName("java.nio.charset.Charset", method.getResolveScope()); + PsiType[] parameterTypes = signature.getParameterTypes(); + if (method.isConstructor() && "java.io.PrintWriter".equals(aClass.getQualifiedName()) && parameterTypes.length == 1 && + parameterTypes[0].equalsToText("java.io.OutputStream")) { + parameterTypes = ArrayUtil.append(parameterTypes, PsiType.BOOLEAN); + charsetOverload = CharsetOverload.EXIST_WITH_FALSE; + } MethodSignature newSignature = MethodSignatureUtil - .createMethodSignature(signature.getName(), ArrayUtil.append(signature.getParameterTypes(), charsetType), + .createMethodSignature(signature.getName(), ArrayUtil.append(parameterTypes, charsetType), signature.getTypeParameters(), signature.getSubstitutor(), signature.isConstructor() ); methodWithCharsetArgument = MethodSignatureUtil.findMethodBySignature(aClass, newSignature, false); } - hasCharsetOverload = methodWithCharsetArgument != null; - method.putUserData(HAS_CHARSET_OVERLOAD, hasCharsetOverload); + if (methodWithCharsetArgument == null) { + charsetOverload = CharsetOverload.NONE; + } + method.putUserData(HAS_CHARSET_OVERLOAD, charsetOverload); } - return hasCharsetOverload; + return charsetOverload; } @Nullable @@ -86,7 +120,7 @@ public class ImplicitDefaultCharsetUsageInspection extends BaseInspection { PsiCallExpression call = (PsiCallExpression)infos[0]; if (!PsiUtil.isLanguageLevel7OrHigher(call)) return null; PsiMethod method = call.resolveMethod(); - return hasCharsetOverload(method) ? new AddUtf8CharsetFix() : null; + return getCharsetOverload(method).createFix(); } @Override @@ -194,15 +228,21 @@ public class ImplicitDefaultCharsetUsageInspection extends BaseInspection { } private static class AddUtf8CharsetFix extends InspectionGadgetsFix { + private final CharsetOverload myCharsetOverload; + + private AddUtf8CharsetFix(CharsetOverload charsetOverload) { + myCharsetOverload = charsetOverload; + } + @Override protected void doFix(Project project, ProblemDescriptor descriptor) { PsiCallExpression call = PsiTreeUtil.getParentOfType(descriptor.getStartElement(), PsiCallExpression.class); if (call == null) return; PsiExpressionList arguments = call.getArgumentList(); if (arguments == null) return; - PsiExpression charsetArg = - JavaPsiFacade.getElementFactory(project).createExpressionFromText("java.nio.charset.StandardCharsets.UTF_8", call); - JavaCodeStyleManager.getInstance(project).shortenClassReferences(arguments.add(charsetArg)); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + myCharsetOverload.additionalArguments().map(arg -> factory.createExpressionFromText(arg, call)).forEach(arguments::add); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(arguments); } @Nls(capitalization = Nls.Capitalization.Sentence)