mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Introduces concept of an *injector*. Uses injectors to make generated
JavaScript code neat.
This commit is contained in:
parent
ae2e669ec3
commit
c9f78c5cdf
|
@ -20,6 +20,7 @@ import org.teavm.common.*;
|
|||
import org.teavm.javascript.ast.*;
|
||||
import org.teavm.javascript.ni.GeneratedBy;
|
||||
import org.teavm.javascript.ni.Generator;
|
||||
import org.teavm.javascript.ni.InjectedBy;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.util.ProgramUtils;
|
||||
|
||||
|
@ -117,6 +118,9 @@ public class Decompiler {
|
|||
if (method.getModifiers().contains(ElementModifier.ABSTRACT)) {
|
||||
continue;
|
||||
}
|
||||
if (method.getAnnotations().get(InjectedBy.class.getName()) != null) {
|
||||
continue;
|
||||
}
|
||||
clsNode.getMethods().add(decompile(method));
|
||||
}
|
||||
clsNode.getInterfaces().addAll(cls.getInterfaces());
|
||||
|
|
|
@ -96,7 +96,6 @@ public class JavascriptBuilder {
|
|||
SourceWriterBuilder builder = new SourceWriterBuilder(naming);
|
||||
builder.setMinified(minifying);
|
||||
SourceWriter sourceWriter = builder.build(writer);
|
||||
Renderer renderer = new Renderer(sourceWriter, classSource);
|
||||
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.Class", new MethodDescriptor("createNew",
|
||||
ValueType.object("java.lang.Class"))));
|
||||
dependencyChecker.attachMethodGraph(new MethodReference("java.lang.String", new MethodDescriptor("<init>",
|
||||
|
@ -104,6 +103,7 @@ public class JavascriptBuilder {
|
|||
executor.complete();
|
||||
ListableClassHolderSource classSet = dependencyChecker.cutUnachievableClasses();
|
||||
Decompiler decompiler = new Decompiler(classSet, classLoader, executor);
|
||||
Renderer renderer = new Renderer(sourceWriter, classSet, classLoader);
|
||||
ClassSetOptimizer optimizer = new ClassSetOptimizer(executor);
|
||||
optimizer.optimizeAll(classSet);
|
||||
executor.complete();
|
||||
|
|
|
@ -16,13 +16,20 @@
|
|||
package org.teavm.javascript;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.codegen.NamingException;
|
||||
import org.teavm.codegen.NamingStrategy;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.ast.*;
|
||||
import org.teavm.javascript.ni.GeneratorContext;
|
||||
import org.teavm.javascript.ni.InjectedBy;
|
||||
import org.teavm.javascript.ni.Injector;
|
||||
import org.teavm.javascript.ni.InjectorContext;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
|
@ -34,12 +41,23 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
private NamingStrategy naming;
|
||||
private SourceWriter writer;
|
||||
private ClassHolderSource classSource;
|
||||
private ClassLoader classLoader;
|
||||
private boolean minifying;
|
||||
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
||||
|
||||
public Renderer(SourceWriter writer, ClassHolderSource classSource) {
|
||||
private static class InjectorHolder {
|
||||
public final Injector injector;
|
||||
|
||||
public InjectorHolder(Injector injector) {
|
||||
this.injector = injector;
|
||||
}
|
||||
}
|
||||
|
||||
public Renderer(SourceWriter writer, ClassHolderSource classSource, ClassLoader classLoader) {
|
||||
this.naming = writer.getNaming();
|
||||
this.writer = writer;
|
||||
this.classSource = classSource;
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public SourceWriter getWriter() {
|
||||
|
@ -193,6 +211,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
}
|
||||
writer.outdent().append("}").newLine();
|
||||
for (MethodNode method : cls.getMethods()) {
|
||||
cls.getMethods();
|
||||
if (!method.getModifiers().contains(NodeModifier.STATIC)) {
|
||||
renderDeclaration(method);
|
||||
}
|
||||
|
@ -947,6 +966,11 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
@Override
|
||||
public void visit(InvocationExpr expr) {
|
||||
try {
|
||||
Injector injector = getInjector(expr.getMethod());
|
||||
if (injector != null) {
|
||||
injector.generate(new InjectorContextImpl(expr.getArguments()), expr.getMethod());
|
||||
return;
|
||||
}
|
||||
String className = naming.getNameFor(expr.getMethod().getClassName());
|
||||
String name = naming.getNameFor(expr.getMethod());
|
||||
String fullName = naming.getFullNameFor(expr.getMethod());
|
||||
|
@ -1124,4 +1148,77 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
throw new RenderingException("IO error occured", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Injector getInjector(MethodReference ref) {
|
||||
InjectorHolder holder = injectorMap.get(ref);
|
||||
if (holder == null) {
|
||||
MethodHolder method = classSource.getClassHolder(ref.getClassName()).getMethod(ref.getDescriptor());
|
||||
AnnotationHolder injectedByAnnot = method.getAnnotations().get(InjectedBy.class.getName());
|
||||
if (injectedByAnnot != null) {
|
||||
ValueType type = injectedByAnnot.getValues().get("value").getJavaClass();
|
||||
holder = new InjectorHolder(instantiateInjector(((ValueType.Object)type).getClassName()));
|
||||
} else {
|
||||
holder = new InjectorHolder(null);
|
||||
}
|
||||
injectorMap.put(ref, holder);
|
||||
}
|
||||
return holder.injector;
|
||||
}
|
||||
|
||||
private Injector instantiateInjector(String type) {
|
||||
try {
|
||||
Class<? extends Injector> cls = Class.forName(type, true, classLoader).asSubclass(Injector.class);
|
||||
Constructor<? extends Injector> cons = cls.getConstructor();
|
||||
return cons.newInstance();
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Illegal injector: " + type, e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Default constructor was not found in the " + type + " injector", e);
|
||||
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
|
||||
throw new RuntimeException("Error instantiating injector " + type, e);
|
||||
}
|
||||
}
|
||||
|
||||
private class InjectorContextImpl implements InjectorContext {
|
||||
private List<Expr> arguments;
|
||||
|
||||
public InjectorContextImpl(List<Expr> arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expr getArgument(int index) {
|
||||
return arguments.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMinifying() {
|
||||
return minifying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeEscaped(String str) throws IOException {
|
||||
writer.append(escapeString(str));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeType(ValueType type) throws IOException {
|
||||
writer.append(typeToClsString(naming, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExpr(Expr expr) throws IOException {
|
||||
expr.acceptVisitor(Renderer.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argumentCount() {
|
||||
return arguments.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript.ni;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface InjectedBy {
|
||||
Class<? extends Injector> value();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript.ni;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface Injector {
|
||||
void generate(InjectorContext context, MethodReference methodRef) throws IOException;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright 2014 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.javascript.ni;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.ast.Expr;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface InjectorContext {
|
||||
Expr getArgument(int index);
|
||||
|
||||
int argumentCount();
|
||||
|
||||
boolean isMinifying();
|
||||
|
||||
SourceWriter getWriter();
|
||||
|
||||
void writeEscaped(String str) throws IOException;
|
||||
|
||||
void writeType(ValueType type) throws IOException;
|
||||
|
||||
void writeExpr(Expr expr) throws IOException;
|
||||
}
|
|
@ -45,25 +45,25 @@ public final class JS {
|
|||
|
||||
public static native <T extends JSObject> JSArray<T> createArray(int size);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject getTypeName(JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject getGlobal();
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
public static native JSObject wrap(String str);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject wrap(char c);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject wrap(int num);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject wrap(float num);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject wrap(double num);
|
||||
|
||||
public static <T extends JSObject> JSArray<T> wrap(T[] array) {
|
||||
|
@ -90,7 +90,7 @@ public final class JS {
|
|||
return result;
|
||||
}
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native boolean unwrapBoolean(JSObject obj);
|
||||
|
||||
public static byte unwrapByte(JSObject obj) {
|
||||
|
@ -101,53 +101,53 @@ public final class JS {
|
|||
return (short)unwrapInt(obj);
|
||||
}
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native int unwrapInt(JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native float unwrapFloat(JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native double unwrapDouble(JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
public static native String unwrapString(JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native char unwrapCharacter(JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native boolean isUndefined(JSObject obj);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
|
||||
|
||||
|
@ -170,9 +170,9 @@ public final class JS {
|
|||
};
|
||||
}
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject get(JSObject instance, JSObject index);
|
||||
|
||||
@GeneratedBy(JSNativeGenerator.class)
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native void set(JSObject instance, JSObject index, JSObject obj);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ package org.teavm.javascript.ni;
|
|||
|
||||
import java.io.IOException;
|
||||
import org.teavm.codegen.SourceWriter;
|
||||
import org.teavm.javascript.ast.ConstantExpr;
|
||||
import org.teavm.javascript.ast.Expr;
|
||||
import org.teavm.javascript.ast.InvocationExpr;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
|
@ -24,47 +27,62 @@ import org.teavm.model.MethodReference;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class JSNativeGenerator implements Generator {
|
||||
public class JSNativeGenerator implements Generator, Injector {
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||
throws IOException {
|
||||
if (methodRef.getName().equals("wrap")) {
|
||||
generateWrapString(context, writer);
|
||||
} else if (methodRef.getName().equals("unwrapString")) {
|
||||
writer.append("return $rt_str(").append(context.getParameterName(1)).append(");")
|
||||
.softNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
SourceWriter writer = context.getWriter();
|
||||
switch (methodRef.getName()) {
|
||||
case "getTypeName":
|
||||
writer.append("return typeof ").append(context.getParameterName(1)).append(";").softNewLine();
|
||||
break;
|
||||
case "getGlobal":
|
||||
writer.append("return window;").softNewLine();
|
||||
break;
|
||||
case "wrap":
|
||||
if (methodRef.getParameterTypes()[0].isObject("java.lang.String")) {
|
||||
generateWrapString(context, writer);
|
||||
} else {
|
||||
writer.append("return ").append(context.getParameterName(1)).append(";").softNewLine();
|
||||
}
|
||||
break;
|
||||
case "get":
|
||||
writer.append("return ").append(context.getParameterName(1)).append("[")
|
||||
.append(context.getParameterName(2)).append("];").softNewLine();
|
||||
break;
|
||||
case "set":
|
||||
writer.append(context.getParameterName(1)).append("[").append(context.getParameterName(2))
|
||||
.append("] = ").append(context.getParameterName(3)).softNewLine();
|
||||
break;
|
||||
case "invoke":
|
||||
generateInvoke(context, writer, methodRef.parameterCount() - 2);
|
||||
writer.append("window");
|
||||
break;
|
||||
case "isUndefined":
|
||||
writer.append("return ").append(context.getParameterName(1)).append(" === undefined;");
|
||||
writer.append("(");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
writer.ws().append("===").ws().append("undefined)");
|
||||
break;
|
||||
default:
|
||||
if (methodRef.getName().startsWith("unwrap")) {
|
||||
if (methodRef.getDescriptor().getResultType().isObject("java.lang.String")) {
|
||||
writer.append("return $rt_str(").append(context.getParameterName(1)).append(");")
|
||||
.softNewLine();
|
||||
} else {
|
||||
writer.append("return ").append(context.getParameterName(1)).append(";").softNewLine();
|
||||
case "getTypeName":
|
||||
writer.append("(typeof ");
|
||||
context.writeExpr(context.getArgument(0));
|
||||
writer.append(")");
|
||||
break;
|
||||
case "get":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
renderProperty(context.getArgument(1), context);
|
||||
break;
|
||||
case "set":
|
||||
writer.append('(');
|
||||
context.writeExpr(context.getArgument(0));
|
||||
renderProperty(context.getArgument(1), context);
|
||||
writer.ws().append('=').ws();
|
||||
context.writeExpr(context.getArgument(2));
|
||||
writer.append(')');
|
||||
break;
|
||||
case "invoke":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
renderProperty(context.getArgument(1), context);
|
||||
writer.append('(');
|
||||
for (int i = 2; i < context.argumentCount(); ++i) {
|
||||
if (i > 2) {
|
||||
writer.append(',').ws();
|
||||
}
|
||||
context.writeExpr(context.getArgument(i));
|
||||
}
|
||||
writer.append(')');
|
||||
break;
|
||||
case "wrap":
|
||||
case "unwrap":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -80,15 +98,51 @@ public class JSNativeGenerator implements Generator {
|
|||
writer.append("return result;").softNewLine();
|
||||
}
|
||||
|
||||
private void generateInvoke(GeneratorContext context, SourceWriter writer, int argNum) throws IOException {
|
||||
writer.append("return ").append(context.getParameterName(1)).append("[")
|
||||
.append(context.getParameterName(2)).append("](");
|
||||
for (int i = 0; i < argNum; ++i) {
|
||||
if (i > 0) {
|
||||
writer.append(",").ws();
|
||||
}
|
||||
writer.append(context.getParameterName(i + 3));
|
||||
private void renderProperty(Expr property, InjectorContext context) throws IOException {
|
||||
SourceWriter writer = context.getWriter();
|
||||
String name = extractPropertyName(property);
|
||||
if (name == null) {
|
||||
writer.append('[');
|
||||
context.writeExpr(property);
|
||||
writer.append(']');
|
||||
} else if (!isIdentifier(name)) {
|
||||
writer.append("[\"");
|
||||
context.writeEscaped(name);
|
||||
writer.append("\"]");
|
||||
} else {
|
||||
writer.append(".").append(name);
|
||||
}
|
||||
writer.append(");").softNewLine();
|
||||
}
|
||||
|
||||
private String extractPropertyName(Expr propertyName) {
|
||||
if (!(propertyName instanceof InvocationExpr)) {
|
||||
return null;
|
||||
}
|
||||
InvocationExpr invoke = (InvocationExpr)propertyName;
|
||||
if (!invoke.getMethod().getClassName().equals(JS.class.getName())) {
|
||||
return null;
|
||||
}
|
||||
if (!invoke.getMethod().getName().equals("wrap") ||
|
||||
!invoke.getMethod().getDescriptor().parameterType(0).isObject("java.lang.String")) {
|
||||
return null;
|
||||
}
|
||||
Expr arg = invoke.getArguments().get(0);
|
||||
if (!(arg instanceof ConstantExpr)) {
|
||||
return null;
|
||||
}
|
||||
ConstantExpr constant = (ConstantExpr)arg;
|
||||
return constant.getValue() instanceof String ? (String)constant.getValue() : null;
|
||||
}
|
||||
|
||||
private boolean isIdentifier(String name) {
|
||||
if (name.isEmpty() || !Character.isJavaIdentifierStart(name.charAt(0))) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 1; i < name.length(); ++i) {
|
||||
if (!Character.isJavaIdentifierPart(name.charAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user