Fixes IDEA-198701 The Default Charset inspection doesn't offer quick fix for PrintWriter in Java 10 or later

This commit is contained in:
Tagir Valeev
2018-09-12 15:51:43 +07:00
parent 7d699169e3
commit 831b7e44b1
@@ -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<Boolean> 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<String> 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<CharsetOverload> 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)