Java Type Migration: care about precedence when casting and improve long literals (IJ-CR-107436)

GitOrigin-RevId: e4288f6aaf2c322b981f2eedfdd940abf7eb1c72
This commit is contained in:
Bas Leijdekkers
2023-06-05 16:33:56 +02:00
committed by intellij-monorepo-bot
parent bd06356746
commit 78776e0ef8
5 changed files with 26 additions and 10 deletions

View File

@@ -7,6 +7,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiPrecedenceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
@@ -197,8 +198,13 @@ public class ThreadLocalConversionRule extends TypeConversionRule {
if (from instanceof PsiPrimitiveType) {
final PsiPrimitiveType unboxed = PsiPrimitiveType.getUnboxedType(to.getParameters()[0]);
if (unboxed != null && !from.equals(unboxed)) {
return context instanceof PsiLiteralExpression && PsiTypes.longType().equals(unboxed)
? replaceByArg + "L"
if (PsiTypes.longType().equals(unboxed)) {
String result = longLiteralText(context, replaceByArg);
if (result != null) return result;
}
return context instanceof PsiExpression expression &&
PsiPrecedenceUtil.getPrecedence(expression) > PsiPrecedenceUtil.TYPE_CAST_PRECEDENCE
? "(" + unboxed.getCanonicalText() + ")(" + replaceByArg + ")"
: "(" + unboxed.getCanonicalText() + ")" + replaceByArg;
}
}
@@ -209,6 +215,16 @@ public class ThreadLocalConversionRule extends TypeConversionRule {
: replaceByArg;
}
private static String longLiteralText(PsiElement context, String text) {
if (context instanceof PsiLiteralExpression) {
return text + "L";
}
else if (context instanceof PsiPrefixExpression expression) {
return longLiteralText(expression.getOperand(), text);
}
return null;
}
private static @NonNls String getBoxedWrapper(PsiType from,
PsiClassType to,
@NotNull @NonNls String arg,

View File

@@ -1,10 +1,10 @@
// "Convert to 'ThreadLocal'" "true"
class T {
private static final ThreadLocal<Long> l = ThreadLocal.withInitial(() -> 1L); // choose "Convert to ThreadLocal" intention
private static final ThreadLocal<Long> l = ThreadLocal.withInitial(() -> -1L); // choose "Convert to ThreadLocal" intention
static {
int i = 1;
l.set((long) i);
l.set((long) (i + 5));
long z = l.get();
}
}

View File

@@ -1,10 +1,10 @@
// "Convert to 'ThreadLocal'" "true"
class T {
private static final long <caret>l = 1; // choose "Convert to ThreadLocal" intention
private static final long <caret>l = -1; // choose "Convert to ThreadLocal" intention
static {
int i = 1;
l = i;
l = i + 5;
long z = l;
}
}

View File

@@ -3,13 +3,13 @@ class T {
private static final ThreadLocal<Long> l = new ThreadLocal<Long>() {
@Override
protected Long initialValue() {
return 1L;
return -1L;
}
};
static {
int i = 1;
l.set((long) i);
l.set((long) (i + 5));
long z = l.get();
}
}

View File

@@ -1,10 +1,10 @@
// "Convert to 'ThreadLocal'" "true"
class T {
private static final long <caret>l = 1;
private static final long <caret>l = -1;
static {
int i = 1;
l = i;
l = i + 5;
long z = l;
}
}