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