i18n: try choice format when ternary is used in concatenation (IDEA-246848)

GitOrigin-RevId: 2f4592ad2ee277075a72b2debc71d3e470084d0b
This commit is contained in:
Anna Kozlova
2020-07-29 10:43:44 +00:00
committed by intellij-monorepo-bot
parent 5dbb404e84
commit 2022bfbf66
5 changed files with 72 additions and 3 deletions
@@ -0,0 +1,5 @@
class MyTest {
void f(boolean prefix){
String s = "Not a valid java identifier<caret> part in " + (prefix ? "prefix" : "suffix");
}
}
@@ -28,8 +28,11 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.uast.UExpression;
import org.jetbrains.uast.expressions.UInjectionHost;
import org.jetbrains.uast.expressions.UStringConcatenationsFacade;
import org.junit.Assert;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
/**
@@ -94,4 +97,15 @@ public class I18nizeTest extends LightJavaCodeInsightTestCase {
public void testShortenClassReferences() {
doTest("p.MyBundle.message(\"key\")");
}
public void testGeneratedChoicePattern() {
configureByFile(getBasePath() + "/before" + getTestName(false) + "." + "java");
UInjectionHost enclosingStringLiteral = I18nizeAction.getEnclosingStringLiteral(getFile(), getEditor());
UStringConcatenationsFacade concatenation = UStringConcatenationsFacade.createFromTopConcatenation(enclosingStringLiteral);
assertNotNull(concatenation);
ArrayList<UExpression> args = new ArrayList<>();
Assert.assertEquals("Not a valid java identifier part in {0, choice, 0#prefix|1#suffix}", JavaI18nUtil.buildUnescapedFormatString(concatenation, args, getProject()));
assertSize(1, args);
assertEquals("prefix ? 0 : 1", args.get(0).getSourcePsi().getText());
}
}
@@ -77,7 +77,7 @@ public class I18nizeBatchQuickFix extends I18nizeQuickFix implements BatchQuickF
}
else if (distinct.add(concatenation.getRootUExpression().getSourcePsi())) {
ArrayList<UExpression> args = new ArrayList<>();
String value = JavaI18nUtil.buildUnescapedFormatString(concatenation, args);
String value = JavaI18nUtil.buildUnescapedFormatString(concatenation, args, project);
String key = ObjectUtils.notNull(suggestKeyByPlace(concatenation.getRootUExpression()),
I18nizeQuickFixDialog.suggestUniquePropertyKey(value, null, null));
HardcodedStringContextData contextData = new HardcodedStringContextData(
@@ -70,7 +70,7 @@ public class I18nizeConcatenationQuickFix extends I18nizeQuickFix {
protected JavaI18nizeQuickFixDialog createDialog(final Project project, final PsiFile context, final UInjectionHost literalExpression) {
final List<UExpression> args = new ArrayList<>();
String formatString = JavaI18nUtil
.buildUnescapedFormatString(Objects.requireNonNull(UStringConcatenationsFacade.createFromTopConcatenation(literalExpression)), args);
.buildUnescapedFormatString(Objects.requireNonNull(UStringConcatenationsFacade.createFromTopConcatenation(literalExpression)), args, project);
return new JavaI18nizeQuickFixDialog(project, context, literalExpression, formatString, getCustomization(formatString), true, true) {
@Override
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.uast.*;
import org.jetbrains.uast.expressions.UStringConcatenationsFacade;
import org.jetbrains.uast.generate.UastCodeGenerationPlugin;
import org.jetbrains.uast.util.UastExpressionUtils;
import java.text.ChoiceFormat;
@@ -437,16 +438,24 @@ public final class JavaI18nUtil extends I18nUtil {
return paramsCount;
}
static String buildUnescapedFormatString(UStringConcatenationsFacade cf, List<? super UExpression> formatParameters) {
public static String buildUnescapedFormatString(UStringConcatenationsFacade cf,
List<? super UExpression> formatParameters,
@NotNull Project project) {
StringBuilder result = new StringBuilder();
int elIndex = 0;
for (UExpression expression : SequencesKt.asIterable(cf.getUastOperands())) {
while (expression instanceof UParenthesizedExpression) {
expression = ((UParenthesizedExpression)expression).getExpression();
}
if (expression instanceof ULiteralExpression) {
Object value = ((ULiteralExpression)expression).getValue();
if (value != null) {
result.append(PsiConcatenationUtil.formatString(value.toString(), false));
}
}
else if (expression instanceof UIfExpression && addChoicePattern(expression, formatParameters, project, result, elIndex)) {
elIndex++;
}
else {
result.append("{").append(elIndex++).append("}");
formatParameters.add(expression);
@@ -455,6 +464,47 @@ public final class JavaI18nUtil extends I18nUtil {
return result.toString();
}
private static boolean addChoicePattern(UExpression expression,
List<? super UExpression> formatParameters,
@NotNull Project project,
StringBuilder result,
int elIndex) {
PsiElement sourcePsi = expression.getSourcePsi();
if (sourcePsi == null) return false;
UastCodeGenerationPlugin generationPlugin = UastCodeGenerationPlugin.byLanguage(sourcePsi.getLanguage());
if (generationPlugin == null) return false;
UExpression thenExpression = ((UIfExpression)expression).getThenExpression();
UExpression elseExpression = ((UIfExpression)expression).getElseExpression();
if (!(thenExpression instanceof ULiteralExpression) ||
!(elseExpression instanceof ULiteralExpression)) return false;
Object thenValue = ((ULiteralExpression)thenExpression).getValue();
Object elseValue = ((ULiteralExpression)elseExpression).getValue();
if (thenValue == null ||
elseValue == null) return false;
result.append("{")
.append(elIndex)
.append(", choice, 0#").append(PsiConcatenationUtil.formatString(thenValue.toString(), false))
.append("|1#").append(PsiConcatenationUtil.formatString(elseValue.toString(), false))
.append("}");
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
UIfExpression exCopy = UastContextKt.toUElement(sourcePsi.copy(), UIfExpression.class);
assert exCopy != null;
generationPlugin.replace(Objects.requireNonNull(exCopy.getThenExpression()),
Objects.requireNonNull(UastContextKt.toUElement(elementFactory.createExpressionFromText("0", null), ULiteralExpression.class)),
ULiteralExpression.class);
generationPlugin.replace(Objects.requireNonNull(exCopy.getElseExpression()),
Objects.requireNonNull(UastContextKt.toUElement(elementFactory.createExpressionFromText("1", null), ULiteralExpression.class)),
ULiteralExpression.class);
formatParameters.add(exCopy);
return true;
}
static String composeParametersText(final List<UExpression> args) {
return args.stream().map(UExpression::getSourcePsi).filter(Objects::nonNull).map(psi -> psi.getText()).collect(Collectors.joining(","));
}