classlib: implement String.to__Case with locale parameter in JS BE (#766)

This commit is contained in:
Ivan Hetman 2023-11-14 17:57:09 +02:00 committed by GitHub
parent e877cc86e4
commit 5336fc9b3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 14 deletions

View File

@ -195,15 +195,39 @@ public class JSStringInjector implements Injector, Function<ProviderContext, Inj
}
private void toLowerCaseJS(InjectorContext context) {
var writer = context.getWriter();
context.writeExpr(context.getArgument(0));
writer.append(".toLowerCase()");
if (context.argumentCount() == 1) {
var writer = context.getWriter();
context.writeExpr(context.getArgument(0));
writer.append(".toLowerCase()");
return;
}
if (context.argumentCount() == 2) {
var writer = context.getWriter();
context.writeExpr(context.getArgument(0));
writer.append(".toLocaleLowerCase(");
context.writeExpr(context.getArgument(1));
writer.append(")");
return;
}
throw new IllegalArgumentException();
}
private void toUpperCaseJS(InjectorContext context) {
var writer = context.getWriter();
context.writeExpr(context.getArgument(0));
writer.append(".toUpperCase()");
if (context.argumentCount() == 1) {
var writer = context.getWriter();
context.writeExpr(context.getArgument(0));
writer.append(".toUpperCase()");
return;
}
if (context.argumentCount() == 2) {
var writer = context.getWriter();
context.writeExpr(context.getArgument(0));
writer.append(".toLocaleUpperCase(");
context.writeExpr(context.getArgument(1));
writer.append(")");
return;
}
throw new IllegalArgumentException();
}
private void intern(InjectorContext context) {

View File

@ -740,6 +740,9 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
@NoSideEffects
private static native Object toLowerCaseJS(Object nativeString);
@NoSideEffects
private static native Object toLowerCaseJS(Object nativeString, Object languageTag);
private TString toLowerCaseChars() {
var chars = new char[charactersLength()];
for (int i = 0; i < charactersLength(); ++i) {
@ -766,6 +769,10 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
}
public TString toLowerCase(TLocale locale) {
if (PlatformDetector.isJavaScript()) {
var upperCase = toLowerCaseJS(nativeString(), locale.toLanguageTag().nativeString());
return upperCase != nativeString() ? new TString(upperCase) : this;
}
return toLowerCase();
}
@ -800,6 +807,9 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
@NoSideEffects
private static native Object toUpperCaseJS(Object nativeString);
@NoSideEffects
private static native Object toUpperCaseJS(Object nativeString, Object languageTag);
private TString toUpperCaseChars() {
var chars = new char[charactersLength()];
for (int i = 0; i < charactersLength(); ++i) {
@ -825,6 +835,10 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
}
public TString toUpperCase(TLocale locale) {
if (PlatformDetector.isJavaScript()) {
var upperCase = toUpperCaseJS(nativeString(), locale.toLanguageTag().nativeString());
return upperCase != nativeString() ? new TString(upperCase) : this;
}
return toUpperCase();
}

View File

@ -36,6 +36,7 @@ import java.util.Arrays;
import org.teavm.classlib.impl.unicode.CLDRHelper;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.TCloneable;
import org.teavm.classlib.java.lang.TString;
import org.teavm.platform.metadata.ResourceArray;
import org.teavm.platform.metadata.ResourceMap;
import org.teavm.platform.metadata.StringResource;
@ -88,7 +89,7 @@ public final class TLocale implements TCloneable, TSerializable {
if (language == null || country == null || variant == null) {
throw new NullPointerException();
}
if (language.length() == 0 && country.length() == 0) {
if (language.isEmpty() && country.isEmpty()) {
languageCode = "";
countryCode = "";
variantCode = variant;
@ -200,18 +201,18 @@ public final class TLocale implements TCloneable, TSerializable {
public String getDisplayName(TLocale locale) {
int count = 0;
StringBuilder buffer = new StringBuilder();
if (languageCode.length() > 0) {
if (!languageCode.isEmpty()) {
buffer.append(getDisplayLanguage(locale));
count++;
}
if (countryCode.length() > 0) {
if (!countryCode.isEmpty()) {
if (count == 1) {
buffer.append(" (");
}
buffer.append(getDisplayCountry(locale));
count++;
}
if (variantCode.length() > 0) {
if (!variantCode.isEmpty()) {
if (count == 1) {
buffer.append(" (");
} else if (count == 2) {
@ -260,12 +261,12 @@ public final class TLocale implements TCloneable, TSerializable {
public String toString() {
StringBuilder result = new StringBuilder();
result.append(languageCode);
if (countryCode.length() > 0) {
if (!countryCode.isEmpty()) {
result.append('_');
result.append(countryCode);
}
if (variantCode.length() > 0 && result.length() > 0) {
if (0 == countryCode.length()) {
if (!variantCode.isEmpty() && result.length() > 0) {
if (countryCode.isEmpty()) {
result.append("__");
} else {
result.append('_');
@ -274,4 +275,18 @@ public final class TLocale implements TCloneable, TSerializable {
}
return result.toString();
}
public TString toLanguageTag() {
StringBuilder result = new StringBuilder();
result.append(languageCode);
if (!countryCode.isEmpty()) {
result.append('-');
result.append(countryCode);
}
if (!variantCode.isEmpty() && result.length() > 0) {
result.append('-');
result.append(variantCode);
}
return new TString(result.toString().toCharArray());
}
}

View File

@ -22,6 +22,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import java.util.Locale;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.teavm.junit.EachTestCompiledSeparately;
@ -309,8 +310,24 @@ public class StringTest {
}
@Test
public void makesLowerCase() {
public void convertsCase() {
assertEquals("foo bar", "FoO bAr".toLowerCase());
assertEquals("FOO BAR", "FoO bAr".toUpperCase());
}
private String common = "i̇stanbul";
private String turkish = "istanbul";
@Test
@SkipPlatform({ TestPlatform.C, TestPlatform.WEBASSEMBLY, TestPlatform.WASI })
public void convertsCaseLocaled() {
assertEquals(turkish, "İstanbul".toLowerCase(new Locale("tr", "TR")));
assertEquals(common, "İstanbul".toLowerCase(Locale.US));
assertNotEquals(turkish, common);
assertEquals("İSTANBUL", common.toUpperCase(Locale.US));
assertEquals("İSTANBUL", turkish.toUpperCase(new Locale("tr", "TR")));
assertNotEquals(common.toUpperCase(Locale.US), turkish.toUpperCase(new Locale("tr", "TR")));
assertEquals(common.toUpperCase(Locale.US), common.toUpperCase(Locale.CANADA));
}
@Test

View File

@ -61,4 +61,14 @@ public class LocaleTest {
assertEquals("Соединенные Штаты", usEnglish.getDisplayCountry(russian));
assertEquals("Россия", russian.getDisplayCountry(russian));
}
@Test
public void testLanguageTag() {
assertEquals("fr-CA", Locale.CANADA_FRENCH.toLanguageTag());
assertEquals("zh", Locale.CHINESE.toLanguageTag());
assertEquals("zh-TW", Locale.TRADITIONAL_CHINESE.toLanguageTag());
assertEquals("zh-CN", Locale.SIMPLIFIED_CHINESE.toLanguageTag());
assertEquals("en-GB", Locale.UK.toLanguageTag());
assertEquals("en-US", Locale.US.toLanguageTag());
}
}