diff --git a/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java index 2b54ef7ee..951fc8dec 100644 --- a/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java +++ b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java @@ -89,10 +89,13 @@ public class DefaultCallGraphNode implements CallGraphNode { return safeFieldAccessSites; } - public void addFieldAccess(FieldReference field, InstructionLocation location) { + public boolean addFieldAccess(FieldReference field, InstructionLocation location) { DefaultFieldAccessSite site = new DefaultFieldAccessSite(location, this, field); if (fieldAccessSites.add(site)) { graph.addFieldAccess(site); + return true; + } else { + return false; } } @@ -104,10 +107,13 @@ public class DefaultCallGraphNode implements CallGraphNode { return safeClassAccessSites; } - public void addClassAccess(String className, InstructionLocation location) { + public boolean addClassAccess(String className, InstructionLocation location) { DefaultClassAccessSite site = new DefaultClassAccessSite(location, this, className); if (classAccessSites.add(site)) { graph.addClassAccess(site); + return true; + } else { + return false; } } } diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java index 2eec87d73..3e17cff61 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java @@ -15,14 +15,34 @@ */ package org.teavm.dependency; -import java.io.IOException; -import java.util.*; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Queue; import org.teavm.callgraph.CallGraph; import org.teavm.callgraph.DefaultCallGraph; -import org.teavm.common.*; +import org.teavm.callgraph.DefaultCallGraphNode; +import org.teavm.common.CachedMapper; import org.teavm.common.CachedMapper.KeyListener; +import org.teavm.common.Mapper; +import org.teavm.common.ServiceRepository; import org.teavm.diagnostics.Diagnostics; -import org.teavm.model.*; +import org.teavm.model.AnnotationReader; +import org.teavm.model.CallLocation; +import org.teavm.model.ClassHolder; +import org.teavm.model.ClassHolderTransformer; +import org.teavm.model.ClassReader; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.FieldReader; +import org.teavm.model.FieldReference; +import org.teavm.model.InstructionLocation; +import org.teavm.model.MethodDescriptor; +import org.teavm.model.MethodReader; +import org.teavm.model.MethodReference; +import org.teavm.model.ValueType; import org.teavm.model.util.ModelUtils; /** @@ -42,9 +62,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent { private List listeners = new ArrayList<>(); private ServiceRepository services; private Queue tasks = new ArrayDeque<>(); - Set missingMethods = new HashSet<>(); - Set missingClasses = new HashSet<>(); - Set missingFields = new HashSet<>(); List types = new ArrayList<>(); Map typeMap = new HashMap<>(); private DependencyCheckerInterruptor interruptor; @@ -216,20 +233,38 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent { @Override public ClassDependency linkClass(String className, CallLocation callLocation) { - return classCache.map(className); + ClassDependency dep = classCache.map(className); + if (callLocation != null && callLocation.getMethod() != null) { + DefaultCallGraphNode callGraphNode = callGraph.getNode(callLocation.getMethod()); + addClassAccess(callGraphNode, className, callLocation.getSourceLocation()); + } + return dep; } - private ClassDependency createClassDependency(String className, CallLocation callLocation) { + private void addClassAccess(DefaultCallGraphNode node, String className, InstructionLocation loc) { + if (!node.addClassAccess(className, loc)) { + return; + } ClassReader cls = classSource.get(className); - ClassDependency dependency = new ClassDependency(this, className, stack, cls); - if (dependency.isMissing()) { - missingClasses.add(dependency); - } else { + if (cls != null) { + if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) { + addClassAccess(node, cls.getParent(), loc); + } + for (String iface : cls.getInterfaces()) { + addClassAccess(node, iface, loc); + } + } + } + + private ClassDependency createClassDependency(String className) { + ClassReader cls = classSource.get(className); + ClassDependency dependency = new ClassDependency(this, className, cls); + if (!dependency.isMissing()) { if (cls.getParent() != null && !cls.getParent().equals(className)) { - linkClass(cls.getParent(), stack); + linkClass(cls.getParent(), null); } for (String ifaceName : cls.getInterfaces()) { - linkClass(ifaceName, stack); + linkClass(ifaceName, null); } } return dependency; @@ -241,9 +276,8 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent { throw new IllegalArgumentException(); } callGraph.getNode(methodRef); - if (callLocation != null) { - callGraph.addNode(caller); - callGraph.getNode(caller).addCallSite(methodRef, location); + if (callLocation != null && callLocation.getMethod() != null) { + callGraph.getNode(callLocation.getMethod()).addCallSite(methodRef, callLocation.getSourceLocation()); } return methodCache.map(methodRef); } @@ -306,10 +340,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent { return null; } - private MethodDependency createMethodDep(MethodReference methodRef, MethodReader method, DependencyStack stack) { - if (stack == null) { - stack = DependencyStack.ROOT; - } + private MethodDependency createMethodDep(MethodReference methodRef, MethodReader method) { ValueType[] arguments = methodRef.getParameterTypes(); int paramCount = arguments.length + 1; int varCount = Math.max(paramCount, method != null && method.getProgram() != null ? @@ -335,16 +366,14 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent { thrown.setTag(methodRef + ":THROWN"); } final MethodDependency dep = new MethodDependency(this, parameterNodes, paramCount, resultNode, thrown, - stack, method, methodRef); + method, methodRef); if (method != null) { - final DependencyStack initClassStack = stack; tasks.add(new Runnable() { @Override public void run() { - linkClass(dep.getMethod().getOwnerName(), dep.getStack()).initClass(initClassStack); + CallLocation caller = new CallLocation(dep.getMethod().getReference()); + linkClass(dep.getMethod().getOwnerName(), caller).initClass(caller); } }); - } else { - missingMethods.add(dep); } return dep; } @@ -374,9 +403,19 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent { } @Override - public FieldDependency linkField(FieldReference fieldRef, MethodReference caller, InstructionLocation location) { - fieldStacks.put(fieldRef, stack); - return fieldCache.map(fieldRef); + public FieldDependency linkField(final FieldReference fieldRef, final CallLocation location) { + if (location != null) { + callGraph.getNode(location.getMethod()).addFieldAccess(fieldRef, location.getSourceLocation()); + } + FieldDependency dep = fieldCache.map(fieldRef); + if (!dep.isMissing()) { + tasks.add(new Runnable() { + @Override public void run() { + linkClass(fieldRef.getClassName(), location).initClass(location); + } + }); + } + return dep; } @Override @@ -389,19 +428,16 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent { return classCache.getKnown(className); } - private FieldDependency createFieldNode(final FieldReference fieldRef, FieldReader field, - final DependencyStack stack) { + private FieldDependency createFieldNode(final FieldReference fieldRef, FieldReader field) { DependencyNode node = new DependencyNode(this); if (shouldLog) { node.setTag(fieldRef.getClassName() + "#" + fieldRef.getFieldName()); } - FieldDependency dep = new FieldDependency(node, stack, field, fieldRef); - if (dep.isMissing()) { - missingFields.add(dep); - } else { + FieldDependency dep = new FieldDependency(node, field, fieldRef); + if (!dep.isMissing()) { tasks.add(new Runnable() { @Override public void run() { - linkClass(fieldRef.getClassName(), stack).initClass(stack); + linkClass(fieldRef.getClassName(), null).initClass(null); } }); } diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index 92cff7e72..1080c23e2 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -63,7 +63,7 @@ class DependencyGraphBuilder { } for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) { if (tryCatch.getExceptionType() != null) { - dependencyChecker.linkClass(tryCatch.getExceptionType(), caller.getMethod(), null); + dependencyChecker.linkClass(tryCatch.getExceptionType(), new CallLocation(caller.getMethod())); } } } @@ -151,7 +151,7 @@ class DependencyGraphBuilder { return; } MethodReference methodRef = new MethodReference(className, methodDesc); - MethodDependency methodDep = checker.linkMethod(methodRef, caller.getMethod(), location); + MethodDependency methodDep = checker.linkMethod(methodRef, new CallLocation(caller.getMethod(), location)); if (!methodDep.isMissing() && knownMethods.add(methodRef)) { methodDep.use(); DependencyNode[] targetParams = methodDep.getVariables(); @@ -204,7 +204,7 @@ class DependencyGraphBuilder { } if (cst instanceof ValueType.Object) { final String className = ((ValueType.Object)cst).getClassName(); - dependencyChecker.linkClass(className, caller.getMethod(), currentLocation); + dependencyChecker.linkClass(className, new CallLocation(caller.getMethod(), currentLocation)); } } @@ -232,7 +232,7 @@ class DependencyGraphBuilder { public void stringConstant(VariableReader receiver, String cst) { nodes[receiver.getIndex()].propagate(dependencyChecker.getType("java.lang.String")); MethodDependency method = dependencyChecker.linkMethod(new MethodReference(String.class, - "", char[].class, void.class), caller.getMethod(), currentLocation); + "", char[].class, void.class), new CallLocation(caller.getMethod(), currentLocation)); method.use(); } @@ -320,7 +320,7 @@ class DependencyGraphBuilder { nodes[receiver.getIndex()].propagate(dependencyChecker.getType("[" + itemType)); String className = extractClassName(itemType); if (className != null) { - dependencyChecker.linkClass(className, caller.getMethod(), currentLocation); + dependencyChecker.linkClass(className, new CallLocation(caller.getMethod(), currentLocation)); } } @@ -342,7 +342,7 @@ class DependencyGraphBuilder { nodes[receiver.getIndex()].propagate(dependencyChecker.getType(sb.toString())); String className = extractClassName(itemType); if (className != null) { - dependencyChecker.linkClass(className, caller.getMethod(), currentLocation); + dependencyChecker.linkClass(className, new CallLocation(caller.getMethod(), currentLocation)); } } @@ -354,7 +354,8 @@ class DependencyGraphBuilder { @Override public void getField(VariableReader receiver, VariableReader instance, FieldReference field, ValueType fieldType) { - FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation); + FieldDependency fieldDep = dependencyChecker.linkField(field, + new CallLocation(caller.getMethod(), currentLocation)); DependencyNode receiverNode = nodes[receiver.getIndex()]; fieldDep.getValue().connect(receiverNode); initClass(field.getClassName()); @@ -362,7 +363,8 @@ class DependencyGraphBuilder { @Override public void putField(VariableReader instance, FieldReference field, VariableReader value) { - FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation); + FieldDependency fieldDep = dependencyChecker.linkField(field, + new CallLocation(caller.getMethod(), currentLocation)); DependencyNode valueNode = nodes[value.getIndex()]; valueNode.connect(fieldDep.getValue()); initClass(field.getClassName()); @@ -424,7 +426,8 @@ class DependencyGraphBuilder { private void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method, List arguments) { - MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation); + MethodDependency methodDep = dependencyChecker.linkMethod(method, + new CallLocation(caller.getMethod(), currentLocation)); if (methodDep.isMissing()) { return; } @@ -445,7 +448,8 @@ class DependencyGraphBuilder { private void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method, List arguments) { - MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation); + MethodDependency methodDep = dependencyChecker.linkMethod(method, + new CallLocation(caller.getMethod(), currentLocation)); if (methodDep.isMissing()) { return; } @@ -466,14 +470,14 @@ class DependencyGraphBuilder { public void isInstance(VariableReader receiver, VariableReader value, final ValueType type) { String className = extractClassName(type); if (className != null) { - dependencyChecker.linkClass(className, caller.getMethod(), currentLocation); + dependencyChecker.linkClass(className, new CallLocation(caller.getMethod(), currentLocation)); } } @Override public void initClass(final String className) { - dependencyChecker.linkClass(className, caller.getMethod(), currentLocation) - .initClass(caller.getMethod(), currentLocation); + CallLocation callLocation = new CallLocation(caller.getMethod(), currentLocation); + dependencyChecker.linkClass(className, callLocation).initClass(callLocation); } @Override @@ -482,7 +486,7 @@ class DependencyGraphBuilder { DependencyNode receiverNode = nodes[receiver.getIndex()]; valueNode.connect(receiverNode); dependencyChecker.linkMethod(new MethodReference(NullPointerException.class, "", void.class), - caller.getMethod(), currentLocation).use(); + new CallLocation(caller.getMethod(), currentLocation)).use(); currentExceptionConsumer.consume(dependencyChecker.getType("java.lang.NullPointerException")); } }; diff --git a/teavm-core/src/main/java/org/teavm/dependency/FieldDependency.java b/teavm-core/src/main/java/org/teavm/dependency/FieldDependency.java index af5fd8270..6535bbc06 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/FieldDependency.java +++ b/teavm-core/src/main/java/org/teavm/dependency/FieldDependency.java @@ -24,13 +24,11 @@ import org.teavm.model.FieldReference; */ public class FieldDependency implements FieldDependencyInfo { private DependencyNode value; - private DependencyStack stack; private FieldReader field; private FieldReference reference; - FieldDependency(DependencyNode value, DependencyStack stack, FieldReader field, FieldReference reference) { + FieldDependency(DependencyNode value, FieldReader field, FieldReference reference) { this.value = value; - this.stack = stack; this.field = field; this.reference = reference; } @@ -40,11 +38,6 @@ public class FieldDependency implements FieldDependencyInfo { return value; } - @Override - public DependencyStack getStack() { - return stack; - } - public FieldReader getField() { return field; } diff --git a/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java b/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java index 0a5779a3f..29b215206 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java +++ b/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java @@ -29,20 +29,17 @@ public class MethodDependency implements MethodDependencyInfo { private int parameterCount; private DependencyNode resultNode; private DependencyNode thrown; - private DependencyStack stack; private MethodReader method; private MethodReference reference; private boolean used; MethodDependency(DependencyChecker dependencyChecker, DependencyNode[] variableNodes, int parameterCount, - DependencyNode resultNode, DependencyNode thrown, DependencyStack stack, MethodReader method, - MethodReference reference) { + DependencyNode resultNode, DependencyNode thrown, MethodReader method, MethodReference reference) { this.dependencyChecker = dependencyChecker; this.variableNodes = Arrays.copyOf(variableNodes, variableNodes.length); this.parameterCount = parameterCount; this.thrown = thrown; this.resultNode = resultNode; - this.stack = stack; this.method = method; this.reference = reference; } @@ -81,11 +78,6 @@ public class MethodDependency implements MethodDependencyInfo { return thrown; } - @Override - public DependencyStack getStack() { - return stack; - } - @Override public MethodReference getReference() { return reference; diff --git a/teavm-core/src/main/java/org/teavm/diagnostics/AccumulationDiagnostics.java b/teavm-core/src/main/java/org/teavm/diagnostics/AccumulationDiagnostics.java index 414bdf326..7581ec258 100644 --- a/teavm-core/src/main/java/org/teavm/diagnostics/AccumulationDiagnostics.java +++ b/teavm-core/src/main/java/org/teavm/diagnostics/AccumulationDiagnostics.java @@ -16,6 +16,7 @@ package org.teavm.diagnostics; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.teavm.model.CallLocation; @@ -23,9 +24,11 @@ import org.teavm.model.CallLocation; * * @author Alexey Andreev */ -public class AccumulationDiagnostics implements Diagnostics { +public class AccumulationDiagnostics implements Diagnostics, ProblemProvider { private List problems = new ArrayList<>(); + private List readonlyProblems = Collections.unmodifiableList(problems); private List severeProblems = new ArrayList<>(); + private List readonlySevereProblems = Collections.unmodifiableList(severeProblems); @Override public void error(CallLocation location, String error, Object... params) { @@ -40,11 +43,13 @@ public class AccumulationDiagnostics implements Diagnostics { problems.add(problem); } + @Override public List getProblems() { - return problems; + return readonlyProblems; } + @Override public List getSevereProblems() { - return severeProblems; + return readonlySevereProblems; } } diff --git a/teavm-core/src/main/java/org/teavm/diagnostics/ProblemProvider.java b/teavm-core/src/main/java/org/teavm/diagnostics/ProblemProvider.java new file mode 100644 index 000000000..8faa4e069 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/diagnostics/ProblemProvider.java @@ -0,0 +1,28 @@ +/* + * 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.diagnostics; + +import java.util.List; + +/** + * + * @author Alexey Andreev + */ +public interface ProblemProvider { + List getProblems(); + + List getSevereProblems(); +} diff --git a/teavm-core/src/main/java/org/teavm/model/CallLocation.java b/teavm-core/src/main/java/org/teavm/model/CallLocation.java index 11017cb3d..8f9a93ee8 100644 --- a/teavm-core/src/main/java/org/teavm/model/CallLocation.java +++ b/teavm-core/src/main/java/org/teavm/model/CallLocation.java @@ -25,7 +25,14 @@ public class CallLocation { private MethodReference method; private InstructionLocation sourceLocation; + public CallLocation(MethodReference method) { + this(method, null); + } + public CallLocation(MethodReference method, InstructionLocation sourceLocation) { + if (method == null) { + throw new IllegalArgumentException("Method must not be null"); + } this.method = method; this.sourceLocation = sourceLocation; } diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java index dbeb1fae7..47545e2a5 100644 --- a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java +++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTestTool.java @@ -366,21 +366,11 @@ public class TeaVMTestTool { vm.exportType("TestClass", cons.getClassName()); vm.setDebugEmitter(debugInfoBuilder); vm.build(innerWriter, new DirectoryBuildTarget(outputDir)); - if (!vm.hasMissingItems()) { - innerWriter.append("\n"); - innerWriter.append("\nJUnitClient.run();"); - if (sourceMapsGenerated) { - String sourceMapsFileName = targetName.substring(targetName.lastIndexOf('/') + 1) + ".map"; - innerWriter.append("\n//# sourceMappingURL=").append(sourceMapsFileName); - } - } else { - innerWriter.append("JUnitClient.reportError(\n"); - StringBuilder sb = new StringBuilder(); - vm.showMissingItems(sb); - escapeStringLiteral(sb.toString(), innerWriter); - innerWriter.append(");"); - log.warning("Error building test " + methodRef); - log.warning(sb.toString()); + innerWriter.append("\n"); + innerWriter.append("\nJUnitClient.run();"); + if (sourceMapsGenerated) { + String sourceMapsFileName = targetName.substring(targetName.lastIndexOf('/') + 1) + ".map"; + innerWriter.append("\n//# sourceMappingURL=").append(sourceMapsFileName); } } if (sourceMapsGenerated) { @@ -402,20 +392,6 @@ public class TeaVMTestTool { } } - private void escapeStringLiteral(String text, Writer writer) throws IOException { - int index = 0; - while (true) { - int next = text.indexOf('\n', index); - if (next < 0) { - break; - } - escapeString(text.substring(index, next + 1), writer); - writer.append(" +\n"); - index = next + 1; - } - escapeString(text.substring(index), writer); - } - private void escapeString(String string, Writer writer) throws IOException { writer.append('\"'); for (int i = 0; i < string.length(); ++i) { diff --git a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java index 8f60bcde2..ec82e43d0 100644 --- a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java +++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java @@ -24,6 +24,7 @@ import org.teavm.cache.DiskRegularMethodNodeCache; import org.teavm.cache.FileSymbolTable; import org.teavm.debugging.information.DebugInformation; import org.teavm.debugging.information.DebugInformationBuilder; +import org.teavm.diagnostics.ProblemProvider; import org.teavm.javascript.RenderingContext; import org.teavm.model.*; import org.teavm.parsing.ClasspathClassHolderSource; @@ -199,6 +200,10 @@ public class TeaVMTool { return cancelled; } + public ProblemProvider getProblemProvider() { + return vm != null ? vm.getProblemProvider() : null; + } + public Collection getClasses() { return vm != null ? vm.getClasses() : Collections.emptyList(); } @@ -289,10 +294,6 @@ public class TeaVMTool { cancelled = true; return; } - if (vm.hasMissingItems()) { - log.info("Missing items found"); - return; - } log.info("JavaScript file successfully built"); if (debugInformationGenerated) { DebugInformation debugInfo = debugEmitter.getDebugInformation(); @@ -344,10 +345,6 @@ public class TeaVMTool { } } - public void checkForMissingItems() { - vm.checkForViolations(); - } - private void copySourceFiles() { if (vm.getWrittenClasses() == null) { return; diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index e065820ca..d110ee2fc 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -23,6 +23,7 @@ import org.teavm.debugging.information.DebugInformationEmitter; import org.teavm.debugging.information.SourceLocation; import org.teavm.dependency.*; import org.teavm.diagnostics.AccumulationDiagnostics; +import org.teavm.diagnostics.ProblemProvider; import org.teavm.javascript.*; import org.teavm.javascript.ast.ClassNode; import org.teavm.javascript.ni.Generator; @@ -214,6 +215,10 @@ public class TeaVM implements TeaVMHost, ServiceRepository { return cancelled; } + public ProblemProvider getProblemProvider() { + return diagnostics; + } + /** *

Adds an entry point. TeaVM guarantees, that all methods that are required by the entry point * will be available at run-time in browser. Also you need to specify for each parameter of entry point