mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Minor improvements and bugfixes
This commit is contained in:
parent
3935d27f5b
commit
525fd89374
|
@ -16,7 +16,6 @@
|
|||
package org.teavm.callgraph;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
|
||||
/**
|
||||
|
@ -27,15 +26,11 @@ public class DefaultCallSite implements CallSite {
|
|||
private InstructionLocation location;
|
||||
private DefaultCallGraphNode callee;
|
||||
private DefaultCallGraphNode caller;
|
||||
private CallLocation exactLocation;
|
||||
|
||||
DefaultCallSite(InstructionLocation location, DefaultCallGraphNode callee, DefaultCallGraphNode caller) {
|
||||
this.location = location;
|
||||
this.callee = callee;
|
||||
this.caller = caller;
|
||||
if (caller != null) {
|
||||
exactLocation = new CallLocation(caller.getMethod(), location);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,10 +38,6 @@ public class DefaultCallSite implements CallSite {
|
|||
return location;
|
||||
}
|
||||
|
||||
public CallLocation getExactLocation() {
|
||||
return exactLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultCallGraphNode getCallee() {
|
||||
return callee;
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.diagnostics;
|
|||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -58,4 +59,9 @@ public class DefaultProblemTextConsumer implements ProblemTextConsumer {
|
|||
public void appendLocation(InstructionLocation location) {
|
||||
sb.append(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendType(ValueType type) {
|
||||
sb.append(type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,10 +16,7 @@
|
|||
package org.teavm.diagnostics;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -81,6 +78,9 @@ public class Problem {
|
|||
case 'c':
|
||||
type = ParamType.CLASS;
|
||||
break;
|
||||
case 't':
|
||||
type = ParamType.TYPE;
|
||||
break;
|
||||
case 'm':
|
||||
type = ParamType.METHOD;
|
||||
break;
|
||||
|
@ -113,6 +113,12 @@ public class Problem {
|
|||
}
|
||||
consumer.appendClass((String)param);
|
||||
break;
|
||||
case TYPE:
|
||||
if (!(param instanceof ValueType)) {
|
||||
return index;
|
||||
}
|
||||
consumer.appendType((ValueType)param);
|
||||
break;
|
||||
case METHOD:
|
||||
if (!(param instanceof MethodReference)) {
|
||||
return index;
|
||||
|
@ -145,6 +151,7 @@ public class Problem {
|
|||
|
||||
enum ParamType {
|
||||
CLASS,
|
||||
TYPE,
|
||||
METHOD,
|
||||
FIELD,
|
||||
LOCATION
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.diagnostics;
|
|||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -28,6 +29,8 @@ public interface ProblemTextConsumer {
|
|||
|
||||
void appendClass(String className);
|
||||
|
||||
void appendType(ValueType type);
|
||||
|
||||
void appendMethod(MethodReference method);
|
||||
|
||||
void appendField(FieldReference field);
|
||||
|
|
|
@ -65,10 +65,6 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, TICKS_PER_PROFILE);
|
||||
buildProfile(kind, subMonitor, profile, classLoader);
|
||||
}
|
||||
IMarker[] markers = getProject().findMarkers(TeaVMEclipsePlugin.PROBLEM_MARKER_ID, true, IResource.DEPTH_INFINITE);
|
||||
for (IMarker marker : markers) {
|
||||
System.out.println("MARKER INSTALLED: " + marker.getId());
|
||||
}
|
||||
} finally {
|
||||
monitor.done();
|
||||
sourceContainers = null;
|
||||
|
@ -131,7 +127,8 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
monitor.beginTask("Running TeaVM", 10000);
|
||||
tool.generate();
|
||||
if (!tool.wasCancelled()) {
|
||||
putMarkers(tool.getDependencyInfo().getCallGraph(), tool.getProblemProvider().getProblems());
|
||||
putMarkers(tool.getDependencyInfo().getCallGraph(), tool.getProblemProvider().getProblems(),
|
||||
profile);
|
||||
setClasses(profile, classesToResources(tool.getClasses()));
|
||||
refreshTarget(tool.getTargetDirectory());
|
||||
}
|
||||
|
@ -235,80 +232,88 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
for (IMarker marker : markers) {
|
||||
String projectName = (String)marker.getAttribute(TeaVMEclipsePlugin.PROBLEM_MARKER_PROJECT_ATTRIBUTE);
|
||||
String profileName = (String)marker.getAttribute(TeaVMEclipsePlugin.PROBLEM_MARKER_PROFILE_ATTRIBUTE);
|
||||
if (projectName.equals(getProject().getName()) && profileName.equals(profile.getName())) {
|
||||
if (projectName.equals(getProject().getName()) && (profileName == null ||
|
||||
profileName.equals(profile.getName()))) {
|
||||
marker.delete();
|
||||
System.out.println("MARKER REMOVED: " + marker.getId() + " while building project " +
|
||||
getProject().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
getProject().deleteMarkers(TeaVMEclipsePlugin.CONFIG_MARKER_ID, true, IResource.DEPTH_INFINITE);
|
||||
}
|
||||
|
||||
private void putMarkers(CallGraph cg, List<Problem> problems) throws CoreException {
|
||||
private void putMarkers(CallGraph cg, List<Problem> problems, TeaVMProfile profile) throws CoreException {
|
||||
for (Problem problem : problems) {
|
||||
putMarker(cg, problem);
|
||||
putMarker(cg, problem, profile);
|
||||
}
|
||||
}
|
||||
|
||||
private void putMarker(CallGraph cg, Problem problem) throws CoreException {
|
||||
private void putMarker(CallGraph cg, Problem problem, TeaVMProfile profile) throws CoreException {
|
||||
if (problem.getLocation() == null || problem.getLocation().getMethod() == null) {
|
||||
putMarkerAtDefaultLocation(problem);
|
||||
putMarkerAtDefaultLocation(problem, profile);
|
||||
return;
|
||||
}
|
||||
CallGraphNode problemNode = cg.getNode(problem.getLocation().getMethod());
|
||||
if (problemNode == null) {
|
||||
putMarkerAtDefaultLocation(problem);
|
||||
putMarkerAtDefaultLocation(problem, profile);
|
||||
return;
|
||||
}
|
||||
Set<CallSite> callSites = new HashSet<>();
|
||||
collectCallSites(callSites, problemNode);
|
||||
String messagePrefix = problemAsString(problem);
|
||||
boolean wasPut = false;
|
||||
for (CallSite callSite : callSites) {
|
||||
IResource resource = findResource(new CallLocation(callSite.getCaller().getMethod(),
|
||||
callSite.getLocation()));
|
||||
if (resource == null) {
|
||||
continue;
|
||||
}
|
||||
wasPut = true;
|
||||
CallGraphNode node = problemNode;
|
||||
StringBuilder sb = new StringBuilder(messagePrefix);
|
||||
while (node != callSite.getCaller()) {
|
||||
sb.append(", used by ").append(getFullMethodName(node.getMethod()));
|
||||
Iterator<? extends CallSite> callerCallSites = node.getCallerCallSites().iterator();
|
||||
if (!callerCallSites.hasNext()) {
|
||||
break;
|
||||
}
|
||||
node = callerCallSites.next().getCaller();
|
||||
}
|
||||
putMarker(resource, callSite.getLocation(), callSite.getCaller().getMethod(), sb.toString());
|
||||
}
|
||||
IResource resource = findResource(problem.getLocation());
|
||||
boolean wasPut = false;
|
||||
if (resource != null) {
|
||||
putMarker(resource, problem.getLocation().getSourceLocation(), problem.getLocation().getMethod(),
|
||||
messagePrefix);
|
||||
wasPut = true;
|
||||
wasPut |= putMarker(resource, problem.getLocation().getSourceLocation(), problem.getLocation().getMethod(),
|
||||
messagePrefix, profile, false);
|
||||
}
|
||||
if (!wasPut) {
|
||||
putMarkerAtDefaultLocation(problem);
|
||||
wasPut |= putMarkersAtCallSites(problemNode, new HashSet<CallGraphNode>(), messagePrefix, profile,
|
||||
false);
|
||||
}
|
||||
if (!wasPut) {
|
||||
wasPut |= putMarkersAtCallSites(problemNode, new HashSet<CallGraphNode>(), messagePrefix, profile, true);
|
||||
}
|
||||
if (!wasPut) {
|
||||
putMarkerAtDefaultLocation(problem, profile);
|
||||
}
|
||||
}
|
||||
|
||||
private void putMarker(IResource resource, InstructionLocation location, MethodReference method,
|
||||
String text) throws CoreException {
|
||||
IMarker marker = resource.createMarker(TeaVMEclipsePlugin.PROBLEM_MARKER_ID);
|
||||
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
|
||||
marker.setAttribute(IMarker.MESSAGE, text);
|
||||
marker.setAttribute(TeaVMEclipsePlugin.PROBLEM_MARKER_PROJECT_ATTRIBUTE, getProject().getName());
|
||||
private boolean putMarkersAtCallSites(CallGraphNode node, Set<CallGraphNode> visited, String problem,
|
||||
TeaVMProfile profile, boolean force) throws CoreException {
|
||||
if (!visited.add(node)) {
|
||||
return false;
|
||||
}
|
||||
boolean wasPut = true;
|
||||
for (CallSite callSite : node.getCallerCallSites()) {
|
||||
IResource resource = findResource(new CallLocation(callSite.getCaller().getMethod(),
|
||||
callSite.getLocation()));
|
||||
if (resource != null) {
|
||||
wasPut = putMarker(resource, callSite.getLocation(), callSite.getCaller().getMethod(), problem,
|
||||
profile, force);
|
||||
}
|
||||
wasPut |= putMarkersAtCallSites(callSite.getCaller(), visited, problem + ", used by " +
|
||||
getFullMethodName(callSite.getCaller().getMethod()), profile, force);
|
||||
}
|
||||
return wasPut;
|
||||
}
|
||||
|
||||
private boolean putMarker(IResource resource, InstructionLocation location, MethodReference method,
|
||||
String text, TeaVMProfile profile, boolean force) throws CoreException {
|
||||
Integer lineNumber = location != null ? location.getLine() : null;
|
||||
if (lineNumber == null) {
|
||||
lineNumber = findMethodLocation(method, resource);
|
||||
}
|
||||
if (lineNumber == null) {
|
||||
if (!force) {
|
||||
return false;
|
||||
}
|
||||
lineNumber = 1;
|
||||
}
|
||||
IMarker marker = resource.createMarker(TeaVMEclipsePlugin.PROBLEM_MARKER_ID);
|
||||
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
|
||||
marker.setAttribute(IMarker.MESSAGE, text);
|
||||
marker.setAttribute(TeaVMEclipsePlugin.PROBLEM_MARKER_PROJECT_ATTRIBUTE, getProject().getName());
|
||||
marker.setAttribute(TeaVMEclipsePlugin.PROBLEM_MARKER_PROFILE_ATTRIBUTE, profile.getName());
|
||||
marker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
|
||||
return true;
|
||||
}
|
||||
|
||||
private IResource findResource(CallLocation location) {
|
||||
|
@ -334,19 +339,12 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
return resource;
|
||||
}
|
||||
|
||||
private void collectCallSites(Set<CallSite> callSites, CallGraphNode node) {
|
||||
for (CallSite callSite : node.getCallerCallSites()) {
|
||||
if (callSites.add(callSite)) {
|
||||
collectCallSites(callSites, callSite.getCaller());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void putMarkerAtDefaultLocation(Problem problem) throws CoreException {
|
||||
private void putMarkerAtDefaultLocation(Problem problem, TeaVMProfile profile) throws CoreException {
|
||||
IMarker marker = getProject().createMarker(TeaVMEclipsePlugin.PROBLEM_MARKER_ID);
|
||||
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
|
||||
marker.setAttribute(IMarker.MESSAGE, problemAsString(problem));
|
||||
marker.setAttribute(TeaVMEclipsePlugin.PROBLEM_MARKER_PROJECT_ATTRIBUTE, getProject().getName());
|
||||
marker.setAttribute(TeaVMEclipsePlugin.PROBLEM_MARKER_PROFILE_ATTRIBUTE, profile.getName());
|
||||
}
|
||||
|
||||
private Integer findMethodLocation(MethodReference methodRef, IResource resource) throws CoreException {
|
||||
|
@ -364,12 +362,12 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
}
|
||||
for (IMethod method : type.getMethods()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
sb.append(method.getElementName()).append('(');
|
||||
for (String paramType : method.getParameterTypes()) {
|
||||
sb.append(Signature.getTypeErasure(paramType));
|
||||
}
|
||||
sb.append(')').append(Signature.getTypeErasure(method.getReturnType()));
|
||||
if (sb.toString().equals(methodRef.toString())) {
|
||||
if (sb.toString().equals(methodRef.getDescriptor().toString())) {
|
||||
return getLineNumber(method);
|
||||
}
|
||||
}
|
||||
|
@ -401,6 +399,9 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
@Override public void appendClass(String cls) {
|
||||
sb.append(getSimpleClassName(cls));
|
||||
}
|
||||
@Override public void appendType(ValueType type) {
|
||||
sb.append(getTypeName(type));
|
||||
}
|
||||
@Override public void append(String text) {
|
||||
sb.append(text);
|
||||
}
|
||||
|
@ -472,7 +473,7 @@ public class TeaVMProjectBuilder extends IncrementalProjectBuilder {
|
|||
|
||||
private String getSimpleClassName(String className) {
|
||||
int index = className.lastIndexOf('.');
|
||||
return className.substring(index + 1);
|
||||
return className.substring(index + 1).replace('$', '.');
|
||||
}
|
||||
|
||||
private TeaVMProjectSettings getProjectSettings() {
|
||||
|
|
|
@ -95,10 +95,10 @@ class JavascriptNativeProcessor {
|
|||
cutPrefix(method.getName(), 3);
|
||||
}
|
||||
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
|
||||
addPropertyGet(propertyName, invoke.getInstance(), result);
|
||||
addPropertyGet(propertyName, invoke.getInstance(), result, invoke.getLocation());
|
||||
if (result != null) {
|
||||
result = unwrap(callLocation, result, method.getResultType());
|
||||
copyVar(result, invoke.getReceiver());
|
||||
copyVar(result, invoke.getReceiver(), invoke.getLocation());
|
||||
}
|
||||
} else if (isProperSetter(method.getDescriptor())) {
|
||||
String propertyName;
|
||||
|
@ -110,28 +110,30 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
Variable wrapped = wrapArgument(callLocation, invoke.getArguments().get(0),
|
||||
method.parameterType(0));
|
||||
addPropertySet(propertyName, invoke.getInstance(), wrapped);
|
||||
addPropertySet(propertyName, invoke.getInstance(), wrapped, invoke.getLocation());
|
||||
} else {
|
||||
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
|
||||
"a proper native JavaScript property declaration");
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript property " +
|
||||
"declaration", invoke.getMethod());
|
||||
continue;
|
||||
}
|
||||
} else if (method.getAnnotations().get(JSIndexer.class.getName()) != null) {
|
||||
if (isProperGetIndexer(method.getDescriptor())) {
|
||||
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
|
||||
addIndexerGet(invoke.getInstance(), wrap(invoke.getArguments().get(0),
|
||||
method.parameterType(0)), result);
|
||||
method.parameterType(0), invoke.getLocation()), result, invoke.getLocation());
|
||||
if (result != null) {
|
||||
result = unwrap(callLocation, result, method.getResultType());
|
||||
copyVar(result, invoke.getReceiver());
|
||||
copyVar(result, invoke.getReceiver(), invoke.getLocation());
|
||||
}
|
||||
} else if (isProperSetIndexer(method.getDescriptor())) {
|
||||
Variable index = wrap(invoke.getArguments().get(0), method.parameterType(0));
|
||||
Variable value = wrap(invoke.getArguments().get(1), method.parameterType(1));
|
||||
addIndexerSet(invoke.getInstance(), index, value);
|
||||
Variable index = wrap(invoke.getArguments().get(0), method.parameterType(0),
|
||||
invoke.getLocation());
|
||||
Variable value = wrap(invoke.getArguments().get(1), method.parameterType(1),
|
||||
invoke.getLocation());
|
||||
addIndexerSet(invoke.getInstance(), index, value, invoke.getLocation());
|
||||
} else {
|
||||
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
|
||||
"a proper native JavaScript indexer declaration");
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript indexer " +
|
||||
"declaration", invoke.getMethod());
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
@ -140,17 +142,17 @@ class JavascriptNativeProcessor {
|
|||
boolean isConstructor = false;
|
||||
if (constructorAnnot != null) {
|
||||
if (!isSupportedType(method.getResultType())) {
|
||||
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
|
||||
"a proper native JavaScript constructor declaration");
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript " +
|
||||
"constructor declaration", invoke.getMethod());
|
||||
continue;
|
||||
}
|
||||
AnnotationValue nameVal = constructorAnnot.getValue("value");
|
||||
name = nameVal != null ? constructorAnnot.getValue("value").getString() : "";
|
||||
if (name.isEmpty()) {
|
||||
if (!method.getName().startsWith("new") || method.getName().length() == 3) {
|
||||
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
|
||||
"declared as a native JavaScript constructor, but its name does " +
|
||||
"not satisfy conventions");
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not declared as a native " +
|
||||
"JavaScript constructor, but its name does not satisfy conventions",
|
||||
invoke.getMethod());
|
||||
continue;
|
||||
}
|
||||
name = method.getName().substring(3);
|
||||
|
@ -165,15 +167,15 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
}
|
||||
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
|
||||
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
|
||||
"a proper native JavaScript method declaration");
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method " +
|
||||
"declaration", invoke.getMethod());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (ValueType arg : method.getParameterTypes()) {
|
||||
if (!isSupportedType(arg)) {
|
||||
diagnostics.error(callLocation, "Method " + invoke.getMethod() + " is not " +
|
||||
"a proper native JavaScript method or constructor declaration");
|
||||
diagnostics.error(callLocation, "Method {{m0}} is not a proper native JavaScript method " +
|
||||
"or constructor declaration", invoke.getMethod());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +188,9 @@ class JavascriptNativeProcessor {
|
|||
newInvoke.setType(InvocationType.SPECIAL);
|
||||
newInvoke.setReceiver(result);
|
||||
newInvoke.getArguments().add(invoke.getInstance());
|
||||
newInvoke.getArguments().add(addStringWrap(addString(name)));
|
||||
newInvoke.getArguments().add(addStringWrap(addString(name, invoke.getLocation()),
|
||||
invoke.getLocation()));
|
||||
newInvoke.setLocation(invoke.getLocation());
|
||||
for (int k = 0; k < invoke.getArguments().size(); ++k) {
|
||||
Variable arg = wrapArgument(callLocation, invoke.getArguments().get(k),
|
||||
method.parameterType(k));
|
||||
|
@ -195,7 +199,7 @@ class JavascriptNativeProcessor {
|
|||
replacement.add(newInvoke);
|
||||
if (result != null) {
|
||||
result = unwrap(callLocation, result, method.getResultType());
|
||||
copyVar(result, invoke.getReceiver());
|
||||
copyVar(result, invoke.getReceiver(), invoke.getLocation());
|
||||
}
|
||||
}
|
||||
block.getInstructions().set(j, replacement.get(0));
|
||||
|
@ -205,19 +209,21 @@ class JavascriptNativeProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
private void addPropertyGet(String propertyName, Variable instance, Variable receiver) {
|
||||
Variable nameVar = addStringWrap(addString(propertyName));
|
||||
private void addPropertyGet(String propertyName, Variable instance, Variable receiver,
|
||||
InstructionLocation location) {
|
||||
Variable nameVar = addStringWrap(addString(propertyName, location), location);
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
insn.setMethod(new MethodReference(JS.class, "get", JSObject.class, JSObject.class, JSObject.class));
|
||||
insn.setReceiver(receiver);
|
||||
insn.getArguments().add(instance);
|
||||
insn.getArguments().add(nameVar);
|
||||
insn.setLocation(location);
|
||||
replacement.add(insn);
|
||||
}
|
||||
|
||||
private void addPropertySet(String propertyName, Variable instance, Variable value) {
|
||||
Variable nameVar = addStringWrap(addString(propertyName));
|
||||
private void addPropertySet(String propertyName, Variable instance, Variable value, InstructionLocation location) {
|
||||
Variable nameVar = addStringWrap(addString(propertyName, location), location);
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
insn.setMethod(new MethodReference(JS.class, "set", JSObject.class, JSObject.class,
|
||||
|
@ -225,20 +231,22 @@ class JavascriptNativeProcessor {
|
|||
insn.getArguments().add(instance);
|
||||
insn.getArguments().add(nameVar);
|
||||
insn.getArguments().add(value);
|
||||
insn.setLocation(location);
|
||||
replacement.add(insn);
|
||||
}
|
||||
|
||||
private void addIndexerGet(Variable array, Variable index, Variable receiver) {
|
||||
private void addIndexerGet(Variable array, Variable index, Variable receiver, InstructionLocation location) {
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
insn.setMethod(new MethodReference(JS.class, "get", JSObject.class, JSObject.class, JSObject.class));
|
||||
insn.setReceiver(receiver);
|
||||
insn.getArguments().add(array);
|
||||
insn.getArguments().add(index);
|
||||
insn.setLocation(location);
|
||||
replacement.add(insn);
|
||||
}
|
||||
|
||||
private void addIndexerSet(Variable array, Variable index, Variable value) {
|
||||
private void addIndexerSet(Variable array, Variable index, Variable value, InstructionLocation location) {
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
insn.setMethod(new MethodReference(JS.class, "set", JSObject.class, JSObject.class,
|
||||
|
@ -246,25 +254,28 @@ class JavascriptNativeProcessor {
|
|||
insn.getArguments().add(array);
|
||||
insn.getArguments().add(index);
|
||||
insn.getArguments().add(value);
|
||||
insn.setLocation(location);
|
||||
replacement.add(insn);
|
||||
}
|
||||
|
||||
private void copyVar(Variable a, Variable b) {
|
||||
private void copyVar(Variable a, Variable b, InstructionLocation location) {
|
||||
AssignInstruction insn = new AssignInstruction();
|
||||
insn.setAssignee(a);
|
||||
insn.setReceiver(b);
|
||||
insn.setLocation(location);
|
||||
replacement.add(insn);
|
||||
}
|
||||
|
||||
private Variable addStringWrap(Variable var) {
|
||||
return wrap(var, ValueType.object("java.lang.String"));
|
||||
private Variable addStringWrap(Variable var, InstructionLocation location) {
|
||||
return wrap(var, ValueType.object("java.lang.String"), location);
|
||||
}
|
||||
|
||||
private Variable addString(String str) {
|
||||
private Variable addString(String str, InstructionLocation location) {
|
||||
Variable var = program.createVariable();
|
||||
StringConstantInstruction nameInsn = new StringConstantInstruction();
|
||||
nameInsn.setReceiver(var);
|
||||
nameInsn.setConstant(str);
|
||||
nameInsn.setLocation(location);
|
||||
replacement.add(nameInsn);
|
||||
return var;
|
||||
}
|
||||
|
@ -273,19 +284,19 @@ class JavascriptNativeProcessor {
|
|||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive)type).getKind()) {
|
||||
case BOOLEAN:
|
||||
return unwrap(var, "unwrapBoolean", ValueType.BOOLEAN);
|
||||
return unwrap(var, "unwrapBoolean", ValueType.BOOLEAN, location.getSourceLocation());
|
||||
case BYTE:
|
||||
return unwrap(var, "unwrapByte", ValueType.BYTE);
|
||||
return unwrap(var, "unwrapByte", ValueType.BYTE, location.getSourceLocation());
|
||||
case SHORT:
|
||||
return unwrap(var, "unwrapShort", ValueType.SHORT);
|
||||
return unwrap(var, "unwrapShort", ValueType.SHORT, location.getSourceLocation());
|
||||
case INTEGER:
|
||||
return unwrap(var, "unwrapInt", ValueType.INTEGER);
|
||||
return unwrap(var, "unwrapInt", ValueType.INTEGER, location.getSourceLocation());
|
||||
case CHARACTER:
|
||||
return unwrap(var, "unwrapCharacter", ValueType.CHARACTER);
|
||||
return unwrap(var, "unwrapCharacter", ValueType.CHARACTER, location.getSourceLocation());
|
||||
case DOUBLE:
|
||||
return unwrap(var, "unwrapDouble", ValueType.DOUBLE);
|
||||
return unwrap(var, "unwrapDouble", ValueType.DOUBLE, location.getSourceLocation());
|
||||
case FLOAT:
|
||||
return unwrap(var, "unwrapFloat", ValueType.FLOAT);
|
||||
return unwrap(var, "unwrapFloat", ValueType.FLOAT, location.getSourceLocation());
|
||||
case LONG:
|
||||
break;
|
||||
}
|
||||
|
@ -294,22 +305,23 @@ class JavascriptNativeProcessor {
|
|||
if (className.equals(JSObject.class.getName())) {
|
||||
return var;
|
||||
} else if (className.equals("java.lang.String")) {
|
||||
return unwrap(var, "unwrapString", ValueType.object("java.lang.String"));
|
||||
return unwrap(var, "unwrapString", ValueType.object("java.lang.String"), location.getSourceLocation());
|
||||
} else {
|
||||
Variable result = program.createVariable();
|
||||
CastInstruction castInsn = new CastInstruction();
|
||||
castInsn.setReceiver(result);
|
||||
castInsn.setValue(var);
|
||||
castInsn.setTargetType(type);
|
||||
castInsn.setLocation(location.getSourceLocation());
|
||||
replacement.add(castInsn);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
diagnostics.error(location, "Unsupported type: " + type);
|
||||
diagnostics.error(location, "Unsupported type: {{t0}}", type);
|
||||
return var;
|
||||
}
|
||||
|
||||
private Variable unwrap(Variable var, String methodName, ValueType resultType) {
|
||||
private Variable unwrap(Variable var, String methodName, ValueType resultType, InstructionLocation location) {
|
||||
Variable result = program.createVariable();
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setMethod(new MethodReference(JS.class.getName(), methodName, ValueType.object(JSObject.class.getName()),
|
||||
|
@ -317,6 +329,7 @@ class JavascriptNativeProcessor {
|
|||
insn.getArguments().add(var);
|
||||
insn.setReceiver(result);
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
insn.setLocation(location);
|
||||
replacement.add(insn);
|
||||
return result;
|
||||
}
|
||||
|
@ -329,28 +342,29 @@ class JavascriptNativeProcessor {
|
|||
return wrapFunctor(location, var, cls);
|
||||
}
|
||||
}
|
||||
return wrap(var, type);
|
||||
return wrap(var, type, location.getSourceLocation());
|
||||
}
|
||||
|
||||
private Variable wrapFunctor(CallLocation location, Variable var, ClassReader type) {
|
||||
if (!type.hasModifier(ElementModifier.INTERFACE) || type.getMethods().size() != 1) {
|
||||
diagnostics.error(location, "Wrong functor: " + type.getName());
|
||||
diagnostics.error(location, "Wrong functor: {{c0}}", type.getName());
|
||||
return var;
|
||||
}
|
||||
String name = type.getMethods().iterator().next().getName();
|
||||
Variable functor = program.createVariable();
|
||||
Variable nameVar = addStringWrap(addString(name));
|
||||
Variable nameVar = addStringWrap(addString(name, location.getSourceLocation()), location.getSourceLocation());
|
||||
InvokeInstruction insn = new InvokeInstruction();
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
insn.setMethod(new MethodReference(JS.class, "function", JSObject.class, JSObject.class, JSObject.class));
|
||||
insn.setReceiver(functor);
|
||||
insn.getArguments().add(var);
|
||||
insn.getArguments().add(nameVar);
|
||||
insn.setLocation(location.getSourceLocation());
|
||||
replacement.add(insn);
|
||||
return functor;
|
||||
}
|
||||
|
||||
private Variable wrap(Variable var, ValueType type) {
|
||||
private Variable wrap(Variable var, ValueType type, InstructionLocation location) {
|
||||
if (type instanceof ValueType.Object) {
|
||||
String className = ((ValueType.Object)type).getClassName();
|
||||
if (!className.equals("java.lang.String")) {
|
||||
|
@ -364,6 +378,7 @@ class JavascriptNativeProcessor {
|
|||
insn.getArguments().add(var);
|
||||
insn.setReceiver(result);
|
||||
insn.setType(InvocationType.SPECIAL);
|
||||
insn.setLocation(location);
|
||||
replacement.add(insn);
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user