mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
Adds minification
This commit is contained in:
parent
bb7053cfa4
commit
10c1e2f528
|
@ -6,9 +6,7 @@ import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.teavm.codegen.DefaultAliasProvider;
|
import org.teavm.codegen.*;
|
||||||
import org.teavm.codegen.DefaultNamingStrategy;
|
|
||||||
import org.teavm.codegen.SourceWriter;
|
|
||||||
import org.teavm.dependency.DependencyChecker;
|
import org.teavm.dependency.DependencyChecker;
|
||||||
import org.teavm.javascript.Decompiler;
|
import org.teavm.javascript.Decompiler;
|
||||||
import org.teavm.javascript.Renderer;
|
import org.teavm.javascript.Renderer;
|
||||||
|
@ -25,7 +23,7 @@ public class ClasslibTestGenerator {
|
||||||
private static PrintStream out;
|
private static PrintStream out;
|
||||||
private static ClasspathClassHolderSource classSource;
|
private static ClasspathClassHolderSource classSource;
|
||||||
private static Decompiler decompiler;
|
private static Decompiler decompiler;
|
||||||
private static DefaultAliasProvider aliasProvider;
|
private static AliasProvider aliasProvider;
|
||||||
private static DefaultNamingStrategy naming;
|
private static DefaultNamingStrategy naming;
|
||||||
private static SourceWriter writer;
|
private static SourceWriter writer;
|
||||||
private static Renderer renderer;
|
private static Renderer renderer;
|
||||||
|
@ -42,9 +40,12 @@ public class ClasslibTestGenerator {
|
||||||
}
|
}
|
||||||
classSource = new ClasspathClassHolderSource();
|
classSource = new ClasspathClassHolderSource();
|
||||||
decompiler = new Decompiler(classSource);
|
decompiler = new Decompiler(classSource);
|
||||||
aliasProvider = new DefaultAliasProvider();
|
aliasProvider = new MinifyingAliasProvider();
|
||||||
naming = new DefaultNamingStrategy(aliasProvider, classSource);
|
naming = new DefaultNamingStrategy(aliasProvider, classSource);
|
||||||
writer = new SourceWriter(naming);
|
naming.setMinifying(true);
|
||||||
|
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
||||||
|
builder.setMinified(true);
|
||||||
|
writer = builder.build();
|
||||||
renderer = new Renderer(writer, classSource);
|
renderer = new Renderer(writer, classSource);
|
||||||
DependencyChecker dependencyChecker = new DependencyChecker(classSource);
|
DependencyChecker dependencyChecker = new DependencyChecker(classSource);
|
||||||
for (int i = 0; i < testClasses.length; ++i) {
|
for (int i = 0; i < testClasses.length; ++i) {
|
||||||
|
|
|
@ -30,12 +30,21 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
private Map<String, String> privateAliases = new HashMap<>();
|
private Map<String, String> privateAliases = new HashMap<>();
|
||||||
private Map<String, String> classAliases = new HashMap<>();
|
private Map<String, String> classAliases = new HashMap<>();
|
||||||
private Map<String, String> fieldAliases = new HashMap<>();
|
private Map<String, String> fieldAliases = new HashMap<>();
|
||||||
|
private boolean minifying;
|
||||||
|
|
||||||
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassHolderSource classSource) {
|
public DefaultNamingStrategy(AliasProvider aliasProvider, ClassHolderSource classSource) {
|
||||||
this.aliasProvider = aliasProvider;
|
this.aliasProvider = aliasProvider;
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isMinifying() {
|
||||||
|
return minifying;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinifying(boolean minifying) {
|
||||||
|
this.minifying = minifying;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNameFor(String cls) {
|
public String getNameFor(String cls) {
|
||||||
String name = classAliases.get(cls);
|
String name = classAliases.get(cls);
|
||||||
|
@ -78,6 +87,11 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFullNameFor(MethodReference method) throws NamingException {
|
||||||
|
return minifying ? getNameFor(method) : getNameFor(method.getClassName()) + "_" + getNameFor(method);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNameFor(FieldReference field) {
|
public String getNameFor(FieldReference field) {
|
||||||
String realCls = getRealFieldOwner(field.getClassName(), field.getFieldName());
|
String realCls = getRealFieldOwner(field.getClassName(), field.getFieldName());
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.teavm.codegen;
|
||||||
|
|
||||||
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class MinifyingAliasProvider implements AliasProvider {
|
||||||
|
private String startLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
private String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
private int lastSuffix;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlias(FieldReference field) {
|
||||||
|
return getNewAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlias(MethodReference method) {
|
||||||
|
return getNewAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlias(String className) {
|
||||||
|
return getNewAlias();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getNewAlias() {
|
||||||
|
int index = lastSuffix;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(startLetters.charAt(index % startLetters.length()));
|
||||||
|
index /= startLetters.length();
|
||||||
|
while (index > 0) {
|
||||||
|
sb.append(letters.charAt(index % letters.length()));
|
||||||
|
index /= letters.length();
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,5 +27,7 @@ public interface NamingStrategy {
|
||||||
|
|
||||||
String getNameFor(MethodReference method) throws NamingException;
|
String getNameFor(MethodReference method) throws NamingException;
|
||||||
|
|
||||||
|
String getFullNameFor(MethodReference method) throws NamingException;
|
||||||
|
|
||||||
String getNameFor(FieldReference field) throws NamingException;
|
String getNameFor(FieldReference field) throws NamingException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,16 @@ public class SourceWriter {
|
||||||
private int indentSize = 0;
|
private int indentSize = 0;
|
||||||
private NamingStrategy naming;
|
private NamingStrategy naming;
|
||||||
private boolean lineStart;
|
private boolean lineStart;
|
||||||
|
private boolean minified;
|
||||||
|
|
||||||
public SourceWriter(NamingStrategy naming) {
|
SourceWriter(NamingStrategy naming) {
|
||||||
this.naming = naming;
|
this.naming = naming;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setMinified(boolean minified) {
|
||||||
|
this.minified = minified;
|
||||||
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
sb.setLength(0);
|
sb.setLength(0);
|
||||||
}
|
}
|
||||||
|
@ -28,42 +33,37 @@ public class SourceWriter {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(Object value) {
|
public SourceWriter append(Object value) {
|
||||||
appendIndent();
|
return append(String.valueOf(value));
|
||||||
sb.append(value);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(int value) {
|
public SourceWriter append(int value) {
|
||||||
appendIndent();
|
return append(String.valueOf(value));
|
||||||
sb.append(value);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter append(char value) {
|
public SourceWriter append(char value) {
|
||||||
appendIndent();
|
return append(String.valueOf(value));
|
||||||
sb.append(value);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(String cls) throws NamingException {
|
public SourceWriter appendClass(String cls) throws NamingException {
|
||||||
appendIndent();
|
return append(naming.getNameFor(cls));
|
||||||
sb.append(naming.getNameFor(cls));
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendField(FieldReference field) throws NamingException {
|
public SourceWriter appendField(FieldReference field) throws NamingException {
|
||||||
appendIndent();
|
return append(naming.getNameFor(field));
|
||||||
sb.append(naming.getNameFor(field));
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethod(MethodReference method) throws NamingException {
|
public SourceWriter appendMethod(MethodReference method) throws NamingException {
|
||||||
appendIndent();
|
return append(naming.getNameFor(method));
|
||||||
sb.append(naming.getNameFor(method));
|
}
|
||||||
return this;
|
|
||||||
|
public SourceWriter appendMethodBody(MethodReference method) throws NamingException {
|
||||||
|
return append(naming.getFullNameFor(method));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendIndent() {
|
private void appendIndent() {
|
||||||
|
if (minified) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (lineStart) {
|
if (lineStart) {
|
||||||
for (int i = 0; i < indentSize; ++i) {
|
for (int i = 0; i < indentSize; ++i) {
|
||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
|
@ -78,6 +78,21 @@ public class SourceWriter {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SourceWriter ws() {
|
||||||
|
if (!minified) {
|
||||||
|
sb.append(' ');
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceWriter softNewLine() {
|
||||||
|
if (!minified) {
|
||||||
|
sb.append('\n');
|
||||||
|
lineStart = true;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public SourceWriter indent() {
|
public SourceWriter indent() {
|
||||||
++indentSize;
|
++indentSize;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.teavm.codegen;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class SourceWriterBuilder {
|
||||||
|
private NamingStrategy naming;
|
||||||
|
private boolean minified;
|
||||||
|
|
||||||
|
public SourceWriterBuilder(NamingStrategy naming) {
|
||||||
|
this.naming = naming;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMinified() {
|
||||||
|
return minified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMinified(boolean minified) {
|
||||||
|
this.minified = minified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SourceWriter build() {
|
||||||
|
SourceWriter writer = new SourceWriter(naming);
|
||||||
|
writer.setMinified(minified);
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,30 +57,33 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderRuntimeCls() {
|
private void renderRuntimeCls() {
|
||||||
writer.append("$rt_cls = function(clsProto) {").indent().newLine();
|
writer.append("$rt_cls").ws().append("=").ws().append("function(clsProto)").ws().append("{")
|
||||||
|
.indent().softNewLine();
|
||||||
String classClass = "java.lang.Class";
|
String classClass = "java.lang.Class";
|
||||||
writer.append("var cls = clsProto.classObject;").newLine();
|
writer.append("var cls").ws().append("=").ws().append("clsProto.classObject;").softNewLine();
|
||||||
writer.append("if (cls === undefined) {").newLine().indent();
|
writer.append("if").softNewLine().append("(cls").ws().append("===").ws().append("undefined)").ws()
|
||||||
|
.append("{").softNewLine().indent();
|
||||||
MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew",
|
MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew",
|
||||||
ValueType.object(classClass)));
|
ValueType.object(classClass)));
|
||||||
writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef)
|
writer.append("cls").ws().append("=").ws().appendMethodBody(createMethodRef).append("();").softNewLine();
|
||||||
.append("();").newLine();
|
writer.append("cls.$data = clsProto;").softNewLine();
|
||||||
writer.append("cls.$data = clsProto;").newLine();
|
|
||||||
if (classSource.getClassHolder(classClass).getField("name") != null) {
|
if (classSource.getClassHolder(classClass).getField("name") != null) {
|
||||||
writer.append("cls.").appendField(new FieldReference(classClass, "name"))
|
writer.append("cls.").appendField(new FieldReference(classClass, "name")).ws().append("=").ws()
|
||||||
.append(" = clsProto.$meta.name !== undefined ? $rt_str(clsProto.$meta.name) : null;").newLine();
|
.append("clsProto.$meta.name").ws().append("!==").ws().append("undefined").ws().append("?").ws()
|
||||||
|
.append("$rt_str(clsProto.$meta.name)").ws().append(":").ws().append("null;").softNewLine();
|
||||||
}
|
}
|
||||||
if (classSource.getClassHolder(classClass).getField("primitive") != null) {
|
if (classSource.getClassHolder(classClass).getField("primitive") != null) {
|
||||||
writer.append("cls.").appendField(new FieldReference(classClass, "primitive"))
|
writer.append("cls.").appendField(new FieldReference(classClass, "primitive"))
|
||||||
.append(" = clsProto.$meta.primitive ? 1 : 0;").newLine();
|
.append(" = clsProto.$meta.primitive ? 1 : 0;").newLine();
|
||||||
}
|
}
|
||||||
if (classSource.getClassHolder(classClass).getField("array") != null) {
|
if (classSource.getClassHolder(classClass).getField("array") != null) {
|
||||||
writer.append("cls.").appendField(new FieldReference(classClass, "array"))
|
writer.append("cls.").appendField(new FieldReference(classClass, "array")).ws()
|
||||||
.append(" = clsProto.$meta.item ? 1 : 0;").newLine();
|
.append("=").ws().append("clsProto.$meta.item").ws().append("?").ws()
|
||||||
|
.append("1").ws().append(":").ws().append("0;").softNewLine();
|
||||||
}
|
}
|
||||||
writer.append("clsProto.classObject = cls;").newLine();
|
writer.append("clsProto.classObject").ws().append("=").ws().append("cls;").softNewLine();
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
writer.append("return cls;").newLine();
|
writer.append("return cls;").softNewLine();
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,14 +91,14 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
String stringClass = "java.lang.String";
|
String stringClass = "java.lang.String";
|
||||||
MethodReference stringCons = new MethodReference(stringClass, new MethodDescriptor("<init>",
|
MethodReference stringCons = new MethodReference(stringClass, new MethodDescriptor("<init>",
|
||||||
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID));
|
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID));
|
||||||
writer.append("$rt_str = function(str) {").indent().newLine();
|
writer.append("$rt_str = function(str) {").indent().softNewLine();
|
||||||
writer.append("var characters = $rt_createCharArray(str.length);").newLine();
|
writer.append("var characters = $rt_createCharArray(str.length);").softNewLine();
|
||||||
writer.append("var charsBuffer = characters.data;").newLine();
|
writer.append("var charsBuffer = characters.data;").softNewLine();
|
||||||
writer.append("for (var i = 0; i < str.length; i = (i + 1) | 0) {").indent().newLine();
|
writer.append("for (var i = 0; i < str.length; i = (i + 1) | 0) {").indent().softNewLine();
|
||||||
writer.append("charsBuffer[i] = str.charCodeAt(i) & 0xFFFF;").newLine();
|
writer.append("charsBuffer[i] = str.charCodeAt(i) & 0xFFFF;").softNewLine();
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
writer.append("return ").appendClass("java.lang.String").append(".")
|
writer.append("return ").appendClass("java.lang.String").append(".")
|
||||||
.appendMethod(stringCons).append("(characters);").newLine();
|
.appendMethod(stringCons).append("(characters);").softNewLine();
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +108,8 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
public void render(ClassNode cls) throws RenderingException {
|
public void render(ClassNode cls) throws RenderingException {
|
||||||
try {
|
try {
|
||||||
writer.appendClass(cls.getName()).append(" = function() {").indent().newLine();
|
writer.appendClass(cls.getName()).ws().append("=").ws().append("function()").ws().append("{")
|
||||||
|
.indent().softNewLine();
|
||||||
for (FieldNode field : cls.getFields()) {
|
for (FieldNode field : cls.getFields()) {
|
||||||
if (field.getModifiers().contains(NodeModifier.STATIC)) {
|
if (field.getModifiers().contains(NodeModifier.STATIC)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -114,11 +118,11 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
value = getDefaultValue(field.getType());
|
value = getDefaultValue(field.getType());
|
||||||
}
|
}
|
||||||
writer.append("this.").appendField(new FieldReference(cls.getName(), field.getName())).append(" = ")
|
writer.append("this.").appendField(new FieldReference(cls.getName(), field.getName())).ws()
|
||||||
.append(constantToString(value)).append(";").newLine();
|
.append("=").ws().append(constantToString(value)).append(";").softNewLine();
|
||||||
}
|
}
|
||||||
writer.append("this.$class = ").appendClass(cls.getName()).append(";").newLine();
|
writer.append("this.$class").ws().append("=").ws().appendClass(cls.getName()).append(";").softNewLine();
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").softNewLine();
|
||||||
|
|
||||||
for (FieldNode field : cls.getFields()) {
|
for (FieldNode field : cls.getFields()) {
|
||||||
if (!field.getModifiers().contains(NodeModifier.STATIC)) {
|
if (!field.getModifiers().contains(NodeModifier.STATIC)) {
|
||||||
|
@ -129,17 +133,17 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
value = getDefaultValue(field.getType());
|
value = getDefaultValue(field.getType());
|
||||||
}
|
}
|
||||||
writer.appendClass(cls.getName()).append('.')
|
writer.appendClass(cls.getName()).append('.')
|
||||||
.appendField(new FieldReference(cls.getName(), field.getName())).append(" = ")
|
.appendField(new FieldReference(cls.getName(), field.getName())).ws().append("=").ws()
|
||||||
.append(constantToString(value)).append(";").newLine();
|
.append(constantToString(value)).append(";").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.appendClass(cls.getName()).append(".prototype = new ")
|
writer.appendClass(cls.getName()).append(".prototype").ws().append("=").append("new ")
|
||||||
.append(cls.getParentName() != null ? naming.getNameFor(cls.getParentName()) :
|
.append(cls.getParentName() != null ? naming.getNameFor(cls.getParentName()) :
|
||||||
"Object").append("();").newLine();
|
"Object").append("();").softNewLine();
|
||||||
writer.appendClass(cls.getName()).append(".$meta = { ");
|
writer.appendClass(cls.getName()).append(".$meta").ws().append("=").append("{").ws();
|
||||||
writer.append("name : \"").append(cls.getName()).append("\", ");
|
writer.append("name").ws().append(":").ws().append("\"").append(cls.getName()).append("\",").ws();
|
||||||
writer.append("primitive : false, ");
|
writer.append("primitive").ws().append(":").ws().append("false,").ws();
|
||||||
writer.append("supertypes : [");
|
writer.append("supertypes").ws().append(":").ws().append("[");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
if (cls.getParentName() != null) {
|
if (cls.getParentName() != null) {
|
||||||
writer.appendClass(cls.getParentName());
|
writer.appendClass(cls.getParentName());
|
||||||
|
@ -153,7 +157,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.appendClass(iface);
|
writer.appendClass(iface);
|
||||||
}
|
}
|
||||||
writer.append("]");
|
writer.append("]");
|
||||||
writer.append(" };").newLine();
|
writer.ws().append("};").softNewLine();
|
||||||
for (MethodNode method : cls.getMethods()) {
|
for (MethodNode method : cls.getMethods()) {
|
||||||
render(method);
|
render(method);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user