lua-profiles
Mike Barry 2023-12-08 07:15:03 -05:00
rodzic aa9d7b7993
commit 66258b8d0b
7 zmienionych plików z 139 dodań i 46 usunięć

Wyświetl plik

@ -1,9 +1,9 @@
package com.onthegomap.planetiler.experimental.lua;
import static com.onthegomap.planetiler.experimental.lua.JavaToLuaCase.transformMemberName;
import static java.util.Map.entry;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeToken;
import com.onthegomap.planetiler.util.Format;
@ -24,9 +24,7 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
@ -81,8 +79,6 @@ public class GenerateLuaTypes {
entry(Void.class, "nil"),
entry(void.class, "nil")
);
private static final Converter<String, String> CAMEL_TO_SNAKE_CASE =
CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.LOWER_UNDERSCORE);
private static final TypeToken<List<?>> LIST_TYPE = new TypeToken<>() {};
private static final TypeToken<Map<?, ?>> MAP_TYPE = new TypeToken<>() {};
private final Deque<String> debugStack = new LinkedList<>();
@ -127,30 +123,6 @@ public class GenerateLuaTypes {
}
}
private static String transformMemberName(String fieldName) {
if (isLowerCamelCase(fieldName)) {
fieldName = CAMEL_TO_SNAKE_CASE.convert(fieldName);
}
if (LuaConversions.LUA_KEYWORDS.contains(fieldName)) {
fieldName = Objects.requireNonNull(fieldName).toUpperCase(Locale.ROOT);
}
return fieldName;
}
private static boolean isLowerCamelCase(String fieldName) {
var chars = fieldName.toCharArray();
if (!Character.isLowerCase(chars[0])) {
return false;
}
boolean upper = false, lower = false, underscore = false;
for (char c : chars) {
upper |= Character.isUpperCase(c);
lower |= Character.isLowerCase(c);
underscore |= c == '_';
}
return upper && lower && !underscore;
}
private void write(String line) {
builder.append(line).append(NEWLINE);
}

Wyświetl plik

@ -0,0 +1,71 @@
package com.onthegomap.planetiler.experimental.lua;
import static java.lang.Character.isDigit;
import static java.lang.Character.isLowerCase;
import static java.lang.Character.isUpperCase;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Converts conventional javaMemberNames to lua_member_names, and lua keywords to uppercase.
*/
public class JavaToLuaCase {
public static final Set<String> LUA_KEYWORDS = Set.of(
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if",
"in", "local", "nil", "not", "or",
"repeat", "return", "then", "true", "until", "while"
);
private static final String LOWER = "[a-z]";
private static final String DIGIT = "\\d";
private static final String UPPER = "[A-Z]";
private static final String UPPER_OR_DIGIT = "[" + UPPER + DIGIT + "]";
private static final List<Boundary> BOUNDARIES = List.of(
// getUTF8string -> get_utf8_string
new Boundary(DIGIT, LOWER),
// fooBar -> foo_bar
new Boundary(LOWER, UPPER),
// ASCIIString -> ascii_string, UTF8String -> utf8_string
new Boundary(UPPER_OR_DIGIT, UPPER + LOWER)
);
private static final List<Pattern> BOUNDARY_PATTERNS = BOUNDARIES.stream()
.map(b -> Pattern.compile("(" + b.prev + ")(" + b.next + ")"))
.toList();
public static boolean isLowerCamelCase(String fieldName) {
var chars = fieldName.toCharArray();
if (!isLowerCase(chars[0])) {
return false;
}
boolean upper = false, lower = false, underscore = false;
for (char c : chars) {
upper |= isUpperCase(c) || isDigit(c);
lower |= isLowerCase(c);
underscore |= c == '_';
}
return upper && lower && !underscore;
}
public static String transformMemberName(String fieldName) {
if (isLowerCamelCase(fieldName)) {
fieldName = camelToSnake(fieldName);
}
if (LUA_KEYWORDS.contains(fieldName)) {
fieldName = Objects.requireNonNull(fieldName).toUpperCase(Locale.ROOT);
}
return fieldName;
}
private static String camelToSnake(String fieldName) {
for (Pattern pattern : BOUNDARY_PATTERNS) {
fieldName = pattern.matcher(fieldName).replaceAll("$1_$2");
}
return fieldName.toLowerCase();
}
private record Boundary(String prev, String next) {}
}

Wyświetl plik

@ -22,12 +22,6 @@ import org.luaj.vm2.lib.jse.CoerceLuaToJava;
* Helper methods to convert between lua and java types.
*/
public interface LuaConversions {
Set<String> LUA_KEYWORDS = Set.of(
"and", "break", "do", "else", "elseif",
"end", "false", "for", "function", "if",
"in", "local", "nil", "not", "or",
"repeat", "return", "then", "true", "until", "while"
);
static LuaValue toLua(Object sourceFeature) {
return CoerceJavaToLua.coerce(sourceFeature);

Wyświetl plik

@ -21,9 +21,7 @@
******************************************************************************/
package org.luaj.vm2.lib.jse;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
import com.onthegomap.planetiler.experimental.lua.LuaConversions;
import com.onthegomap.planetiler.experimental.lua.JavaToLuaCase;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InaccessibleObjectException;
@ -57,8 +55,6 @@ import org.luaj.vm2.LuaValue;
* @see CoerceLuaToJava
*/
public class JavaClass extends JavaInstance {
private static final Converter<String, String> CAMEL_TO_SNAKE_CASE =
CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.LOWER_UNDERSCORE);
static final Map<Class<?>, JavaClass> classes = new ConcurrentHashMap<>();
@ -174,12 +170,7 @@ public class JavaClass extends JavaInstance {
private <T> void putAliases(Map<LuaValue, T> map) {
for (var entry : List.copyOf(map.entrySet())) {
String key = entry.getKey().tojstring();
String key2;
if (LuaConversions.LUA_KEYWORDS.contains(key)) {
key2 = key.toUpperCase();
} else {
key2 = CAMEL_TO_SNAKE_CASE.convert(key);
}
String key2 = JavaToLuaCase.transformMemberName(key);
map.putIfAbsent(LuaValue.valueOf(key2), entry.getValue());
}
}

Wyświetl plik

@ -487,6 +487,21 @@ class GenerateLuaTypesTest {
UsesPath.class);
}
@Test
void testAbbreviationInName() {
interface Test {
int setSRID(Integer n);
}
assertGenerated("""
---@class (exact) com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2Test
types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2Test = {}
---@param n integer
---@return integer
function types.com_onthegomap_planetiler_experimental_lua_GenerateLuaTypesTest_2Test:set_srid(n) end
""", Test.class);
}
@Test
void testGeneratedMetaFileCompiles() {
String types = new GenerateLuaTypes().generatePlanetiler().toString();

Wyświetl plik

@ -0,0 +1,36 @@
package com.onthegomap.planetiler.experimental.lua;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class JavaToLuaCaseTest {
@ParameterizedTest
@CsvSource({
"foo, foo",
"Foo, Foo",
"fooBar, foo_bar",
"FooBar, FooBar",
"foo_bar, foo_bar",
"foo_BAR, foo_BAR",
"FOO_BAR, FOO_BAR",
"fooBAR, foo_bar",
"getISO3Code, get_iso3_code",
"utf8string, utf8_string",
"arg0, arg0",
"arg10, arg10",
"utf8String, utf8_string",
"getUTF8String, get_utf8_string",
"getUTF8string, get_utf8_string",
"getUTF8ASCIIString, get_utf8ascii_string",
"iso31661Alpha2, iso31661_alpha2",
"getUTF8At0, get_utf8_at0",
"distance3D, distance3d",
"toASCIIString, to_ascii_string",
"and, AND",
})
void testConversions(String input, String expectedOutput) {
assertEquals(expectedOutput, JavaToLuaCase.transformMemberName(input));
}
}

Wyświetl plik

@ -780,6 +780,20 @@ class LuaEnvironmentTests {
assertConvertsTo(1, env.main.call());
}
@Test
void testAbbreviation() {
var env = load("""
function main()
return obj:set_srid(1)
end
""", Map.of("obj", new Object() {
public int setSRID(int a) {
return a + 1;
}
}));
assertConvertsTo(2, env.main.call());
}
@Test
void testEnum() {
enum MyEnum {