Generate types and functions with their members
This commit is contained in:
parent
e30e005d09
commit
b82639cf0d
|
@ -1,18 +1,19 @@
|
||||||
package io.github.lonamiwebs.overgram.generator;
|
package io.github.lonamiwebs.overgram.generator;
|
||||||
|
|
||||||
|
import io.github.lonamiwebs.overgram.parser.TLArg;
|
||||||
import io.github.lonamiwebs.overgram.parser.TLObject;
|
import io.github.lonamiwebs.overgram.parser.TLObject;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class Generator {
|
public class Generator {
|
||||||
public static void generateJava(
|
public static void generateJava(
|
||||||
final List<TLObject> types, final List<TLObject> functions,
|
final List<TLObject> types, final List<TLObject> functions,
|
||||||
final File abstractsFile, final File typesFile, final File functionsFile) throws IOException {
|
final File abstractsFile, final File typesFile, final File functionsFile) throws IOException {
|
||||||
makeParents(abstractsFile, typesFile, functionsFile);
|
makeParents(abstractsFile, typesFile, functionsFile);
|
||||||
|
try (final Writer writer = new BufferedWriter(new FileWriter(abstractsFile))) {
|
||||||
|
writeAbstract(writer, types);
|
||||||
|
}
|
||||||
try (final Writer writer = new BufferedWriter(new FileWriter(typesFile))) {
|
try (final Writer writer = new BufferedWriter(new FileWriter(typesFile))) {
|
||||||
writeCode(writer, "Types", "TLObject", types);
|
writeCode(writer, "Types", "TLObject", types);
|
||||||
}
|
}
|
||||||
|
@ -21,34 +22,86 @@ public class Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void writeAbstract(final Writer writer, final List<TLObject> objects) throws IOException {
|
||||||
|
writer.write("package io.github.lonamiwebs.overgram.tl;\n");
|
||||||
|
writer.write("@SuppressWarnings(\"unused\")\n");
|
||||||
|
writer.write("public class Abstract {\n");
|
||||||
|
for (final Map.Entry<String, List<String>> nsNames : stringsByNamespace(uniqueTypes(objects)).entrySet()) {
|
||||||
|
if (!nsNames.getKey().isEmpty()) {
|
||||||
|
writer.write("public static class ");
|
||||||
|
writer.write(nsNames.getKey());
|
||||||
|
writer.write(" {\n");
|
||||||
|
}
|
||||||
|
for (final String name : nsNames.getValue()) {
|
||||||
|
writer.write("public static abstract class ");
|
||||||
|
writer.write(TLObject.toCamelCase(name));
|
||||||
|
writer.write(" extends TLObject {}\n");
|
||||||
|
}
|
||||||
|
if (!nsNames.getKey().isEmpty()) {
|
||||||
|
writer.write("}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writer.write("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
private static void writeCode(
|
private static void writeCode(
|
||||||
final Writer writer, final String className, final String extendsName,
|
final Writer writer, final String className, final String extendsName,
|
||||||
final List<TLObject> objects) throws IOException {
|
final List<TLObject> objects) throws IOException {
|
||||||
writer.write("package io.github.lonamiwebs.overgram.tl;\n");
|
writer.write("package io.github.lonamiwebs.overgram.tl;\n");
|
||||||
|
writer.write("import io.github.lonamiwebs.overgram.utils.BinaryReader;\n");
|
||||||
|
writer.write("import io.github.lonamiwebs.overgram.utils.BinaryWriter;\n");
|
||||||
|
writer.write("import java.util.List;\n");
|
||||||
|
writer.write("@SuppressWarnings(\"unused\")\n");
|
||||||
writer.write("public class ");
|
writer.write("public class ");
|
||||||
writer.write(className);
|
writer.write(className);
|
||||||
writer.write(" {\n");
|
writer.write(" {\n");
|
||||||
for (Map.Entry<String, List<TLObject>> nsObjects : byNamespace(objects).entrySet()) {
|
for (final Map.Entry<String, List<TLObject>> nsObjects : byNamespace(objects).entrySet()) {
|
||||||
if (!nsObjects.getKey().isEmpty()) {
|
if (!nsObjects.getKey().isEmpty()) {
|
||||||
writer.write("public static class ");
|
writer.write("public static class ");
|
||||||
writer.write(TLObject.toCamelCase(nsObjects.getKey()));
|
writer.write(nsObjects.getKey());
|
||||||
writer.write(" {\n");
|
writer.write(" {\n");
|
||||||
}
|
}
|
||||||
for (TLObject object : nsObjects.getValue()) {
|
for (final TLObject object : nsObjects.getValue()) {
|
||||||
writer.write("public static class ");
|
writer.write("public static class ");
|
||||||
writer.write(TLObject.toCamelCase(object.name));
|
writer.write(TLObject.toCamelCase(object.name));
|
||||||
writer.write(" extends ");
|
writer.write(" extends ");
|
||||||
writer.write(extendsName);
|
writer.write(extendsName);
|
||||||
writer.write(" {\n");
|
writer.write(" {\n");
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
|
for (TLArg arg : object.args) {
|
||||||
|
if (arg.flags) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write("private ");
|
||||||
|
writer.write(arg.javaType());
|
||||||
|
writer.write(" var" + n);
|
||||||
|
++n;
|
||||||
|
writer.write(";\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.write("public ");
|
||||||
|
writer.write(TLObject.toCamelCase(object.name));
|
||||||
|
writer.write("() {}\n");
|
||||||
|
|
||||||
|
// Use the builder pattern because Java is stupid and has no optional named arguments.
|
||||||
|
// Objects will be created with nothing set and the arguments set with .argument(value).
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
writer.write("public void serialize(final BinaryWriter writer) {}\n");
|
||||||
|
writer.write("public void deserialize(final BinaryReader reader) {}\n");
|
||||||
|
|
||||||
writer.write("}\n");
|
writer.write("}\n");
|
||||||
}
|
}
|
||||||
if (!nsObjects.getKey().isEmpty()) {
|
if (!nsObjects.getKey().isEmpty()) {
|
||||||
writer.write("}\n");
|
writer.write("}\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
writer.write("}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<String, List<TLObject>> byNamespace(final List<TLObject> objects) {
|
private static Map<String, List<TLObject>> byNamespace(final Iterable<TLObject> objects) {
|
||||||
final Map<String, List<TLObject>> result = new HashMap<>();
|
final Map<String, List<TLObject>> result = new HashMap<>();
|
||||||
for (final TLObject object : objects) {
|
for (final TLObject object : objects) {
|
||||||
result.computeIfAbsent(object.namespace, k -> new ArrayList<>()).add(object);
|
result.computeIfAbsent(object.namespace, k -> new ArrayList<>()).add(object);
|
||||||
|
@ -56,6 +109,34 @@ public class Generator {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<String, List<String>> stringsByNamespace(final Iterable<String> strings) {
|
||||||
|
final Map<String, List<String>> result = new HashMap<>();
|
||||||
|
|
||||||
|
String[] tmp;
|
||||||
|
String namespace;
|
||||||
|
String name;
|
||||||
|
for (final String string : strings) {
|
||||||
|
tmp = string.split("\\.");
|
||||||
|
if (tmp.length == 1) {
|
||||||
|
namespace = "";
|
||||||
|
name = tmp[0];
|
||||||
|
} else {
|
||||||
|
namespace = tmp[0];
|
||||||
|
name = tmp[1];
|
||||||
|
}
|
||||||
|
result.computeIfAbsent(namespace, k -> new ArrayList<>()).add(name);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<String> uniqueTypes(final List<TLObject> objects) {
|
||||||
|
final Set<String> result = new HashSet<>();
|
||||||
|
for (final TLObject object : objects) {
|
||||||
|
result.add(object.type);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static void makeParents(final File... files) throws IOException {
|
private static void makeParents(final File... files) throws IOException {
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
file = file.getAbsoluteFile().getParentFile();
|
file = file.getAbsoluteFile().getParentFile();
|
||||||
|
|
|
@ -43,6 +43,73 @@ public class TLArg {
|
||||||
return new TLArg(tmp[0], types, flags, flag);
|
return new TLArg(tmp[0], types, flags, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String javaType() {
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
boolean nested = false;
|
||||||
|
for (final String type : types) {
|
||||||
|
switch (type) {
|
||||||
|
case "vector":
|
||||||
|
case "Vector":
|
||||||
|
builder.append("List");
|
||||||
|
break;
|
||||||
|
case "int":
|
||||||
|
if (flag == null && !nested) {
|
||||||
|
builder.append("int");
|
||||||
|
} else {
|
||||||
|
builder.append("Integer");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "long":
|
||||||
|
// TODO handle int128 and int256 properly
|
||||||
|
case "int128":
|
||||||
|
case "int256":
|
||||||
|
if (flag == null && !nested) {
|
||||||
|
builder.append("long");
|
||||||
|
} else {
|
||||||
|
builder.append("Long");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "double":
|
||||||
|
if (flag == null && !nested) {
|
||||||
|
builder.append("double");
|
||||||
|
} else {
|
||||||
|
builder.append("Double");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Bool":
|
||||||
|
if (flag == null && !nested) {
|
||||||
|
builder.append("boolean");
|
||||||
|
} else {
|
||||||
|
builder.append("Boolean");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "true":
|
||||||
|
builder.append("boolean");
|
||||||
|
break;
|
||||||
|
case "string":
|
||||||
|
builder.append("String");
|
||||||
|
break;
|
||||||
|
case "bytes":
|
||||||
|
builder.append("byte[]");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
builder.append("Abstract.");
|
||||||
|
builder.append(TLObject.toCamelCase(type));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
builder.append('<');
|
||||||
|
nested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.setLength(builder.length() - 1);
|
||||||
|
for (int i = 1; i < types.size(); ++i) {
|
||||||
|
builder.append('>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
|
|
@ -29,7 +29,10 @@ public class TLObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String toCamelCase(final String string) {
|
public static String toCamelCase(final String string) {
|
||||||
return string.substring(0, 1).toUpperCase() + string.substring(1);
|
final int dot = string.lastIndexOf(".");
|
||||||
|
return string.substring(0, dot + 1)
|
||||||
|
+ string.substring(dot + 1, dot + 2).toUpperCase()
|
||||||
|
+ string.substring(dot + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TLObject fromString(String string) {
|
public static TLObject fromString(String string) {
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package io.github.lonamiwebs.overgram.tl;
|
package io.github.lonamiwebs.overgram.tl;
|
||||||
|
|
||||||
public abstract class TLObject {
|
import io.github.lonamiwebs.overgram.utils.BinaryReader;
|
||||||
|
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
|
||||||
|
|
||||||
|
public abstract class TLObject {
|
||||||
|
public abstract void serialize(final BinaryWriter writer);
|
||||||
|
public abstract void deserialize(final BinaryReader reader);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
package io.github.lonamiwebs.overgram.utils;
|
||||||
|
|
||||||
|
public class BinaryReader {
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package io.github.lonamiwebs.overgram.utils;
|
||||||
|
|
||||||
|
|
||||||
|
public class BinaryWriter {
|
||||||
|
}
|
Loading…
Reference in New Issue