diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumTransformer.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumTransformer.java
index ba5d33fb0..1fbbe3a61 100644
--- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumTransformer.java
+++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumTransformer.java
@@ -24,7 +24,7 @@ import org.teavm.model.*;
*/
public class EnumTransformer implements ClassHolderTransformer {
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
if (cls.getParent() != null && !cls.getParent().equals("java.lang.Enum")) {
return;
}
diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/JavacSupport.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/JavacSupport.java
index def1bef59..ba53ffc09 100644
--- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/JavacSupport.java
+++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/JavacSupport.java
@@ -27,7 +27,7 @@ import org.teavm.model.instructions.InvokeInstruction;
*/
public class JavacSupport implements ClassHolderTransformer {
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
if (cls.getName().equals("javax.tools.ToolProvider")) {
MethodHolder method = cls.getMethod(new MethodDescriptor("getSystemJavaCompiler",
ValueType.object("javax.tools.JavaCompiler")));
diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java
index b8442f5dc..07cb02d55 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java
@@ -17,6 +17,7 @@ package org.teavm.dependency;
import org.teavm.common.ServiceRepository;
import org.teavm.model.ClassHolder;
+import org.teavm.model.Diagnostics;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
@@ -38,4 +39,6 @@ public interface DependencyAgent extends DependencyInfo, ServiceRepository {
ClassDependency linkClass(String className, final DependencyStack stack);
FieldDependency linkField(FieldReference fieldRef, DependencyStack stack);
+
+ Diagnostics getDiagnostics();
}
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 955b3e4e6..d2bbfbd50 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java
@@ -50,9 +50,12 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
private DependencyViolations dependencyViolations;
private DependencyCheckerInterruptor interruptor;
private boolean interrupted;
+ private Diagnostics diagnostics;
- public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services) {
- this.classSource = new DependencyClassSource(classSource);
+ public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
+ Diagnostics diagnostics) {
+ this.diagnostics = diagnostics;
+ this.classSource = new DependencyClassSource(classSource, diagnostics);
this.classLoader = classLoader;
this.services = services;
methodReaderCache = new CachedMapper<>(new Mapper() {
@@ -431,23 +434,23 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
return methodCache.getKnown(methodRef);
}
- public DependencyViolations getDependencyViolations() {
+ public DependencyViolations getViolations() {
if (dependencyViolations == null) {
dependencyViolations = new DependencyViolations(missingMethods, missingClasses, missingFields);
}
return dependencyViolations;
}
- public void checkForMissingItems() {
- getDependencyViolations().checkForMissingItems();
+ public void checkForViolations() {
+ getViolations().checkForViolations();
}
- public boolean hasMissingItems() {
- return getDependencyViolations().hasMissingItems();
+ public boolean hasViolations() {
+ return getViolations().hasSevereViolations();
}
- public void showMissingItems(Appendable sb) throws IOException {
- getDependencyViolations().showMissingItems(sb);
+ public void showViolations(Appendable sb) throws IOException {
+ getViolations().showViolations(sb);
}
public void processDependencies() {
@@ -469,4 +472,9 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
public T getService(Class type) {
return services.getService(type);
}
+
+ @Override
+ public Diagnostics getDiagnostics() {
+ return diagnostics;
+ }
}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java
index 0dc82049f..681fb0df8 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java
@@ -22,10 +22,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.teavm.common.CachedMapper;
import org.teavm.common.Mapper;
-import org.teavm.model.ClassHolder;
-import org.teavm.model.ClassHolderTransformer;
-import org.teavm.model.ClassReader;
-import org.teavm.model.ClassReaderSource;
+import org.teavm.model.*;
import org.teavm.model.util.ModelUtils;
/**
@@ -34,6 +31,7 @@ import org.teavm.model.util.ModelUtils;
*/
class DependencyClassSource implements ClassReaderSource {
private ClassReaderSource innerSource;
+ private Diagnostics diagnostics;
private ConcurrentMap generatedClasses = new ConcurrentHashMap<>();
private List transformers = new ArrayList<>();
private CachedMapper cache = new CachedMapper<>(
@@ -43,8 +41,9 @@ class DependencyClassSource implements ClassReaderSource {
}
});
- public DependencyClassSource(ClassReaderSource innerSource) {
+ public DependencyClassSource(ClassReaderSource innerSource, Diagnostics diagnostics) {
this.innerSource = innerSource;
+ this.diagnostics = diagnostics;
}
@Override
@@ -65,7 +64,7 @@ class DependencyClassSource implements ClassReaderSource {
ClassHolder cls = findClass(name);
if (cls != null && !transformers.isEmpty()) {
for (ClassHolderTransformer transformer : transformers) {
- transformer.transformClass(cls, innerSource);
+ transformer.transformClass(cls, innerSource, diagnostics);
}
cls = ModelUtils.copyClass(cls);
}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyDiagnostics.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyDiagnostics.java
new file mode 100644
index 000000000..ac6cb6604
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyDiagnostics.java
@@ -0,0 +1,63 @@
+/*
+ * 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.dependency;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.teavm.model.Diagnostics;
+import org.teavm.model.InstructionLocation;
+import org.teavm.vm.DiagnosticsProblem;
+import org.teavm.vm.DiagnosticsProblemSeverity;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+class DependencyDiagnostics implements Diagnostics {
+ private List problems = new ArrayList<>();
+ private List severeProblems = new ArrayList<>();
+
+ @Override
+ public void error(InstructionLocation location, String error) {
+ DiagnosticsProblem violation = new DiagnosticsProblem(DiagnosticsProblemSeverity.ERROR, location, error);
+ problems.add(violation);
+ severeProblems.add(violation);
+ }
+
+ @Override
+ public void error(String error) {
+ error(null, error);
+ }
+
+ @Override
+ public void warning(InstructionLocation location, String error) {
+ DiagnosticsProblem violation = new DiagnosticsProblem(DiagnosticsProblemSeverity.WARNING, location, error);
+ problems.add(violation);
+ }
+
+ @Override
+ public void warning(String error) {
+ warning(null, error);
+ }
+
+ public List getProblems() {
+ return problems;
+ }
+
+ public List getSevereProblems() {
+ return severeProblems;
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyViolations.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyViolations.java
index e04558d86..1e3d5997e 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyViolations.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyViolations.java
@@ -47,24 +47,24 @@ public class DependencyViolations {
return missingFields;
}
- public boolean hasMissingItems() {
+ public boolean hasSevereViolations() {
return !missingMethods.isEmpty() || !missingClasses.isEmpty() || !missingFields.isEmpty();
}
- public void checkForMissingItems() {
- if (!hasMissingItems()) {
+ public void checkForViolations() {
+ if (!hasSevereViolations()) {
return;
}
StringBuilder sb = new StringBuilder();
try {
- showMissingItems(sb);
+ showViolations(sb);
} catch (IOException e) {
throw new AssertionError("StringBuilder should not throw IOException");
}
throw new IllegalStateException(sb.toString());
}
- public void showMissingItems(Appendable sb) throws IOException {
+ public void showViolations(Appendable sb) throws IOException {
List items = new ArrayList<>();
Map stackMap = new HashMap<>();
for (ClassDependencyInfo cls : missingClasses) {
@@ -80,15 +80,15 @@ public class DependencyViolations {
items.add(field.getReference().toString());
}
Collections.sort(items);
- sb.append("Can't compile due to the following items missing:\n");
+ sb.append("Can't compile due to the following violations:\n");
for (String item : items) {
- sb.append(" ").append(item).append("\n");
+ sb.append("Missing ").append(item).append("\n");
DependencyStack stack = stackMap.get(item);
if (stack == null) {
- sb.append(" at unknown location\n");
+ sb.append(" at unknown location\n");
} else {
while (stack.getMethod() != null) {
- sb.append(" at ").append(stack.getMethod().toString());
+ sb.append(" at ").append(stack.getMethod().toString());
if (stack.getLocation() != null) {
sb.append(":").append(String.valueOf(stack.getLocation().getLine()));
}
diff --git a/teavm-core/src/main/java/org/teavm/javascript/NullPointerExceptionTransformer.java b/teavm-core/src/main/java/org/teavm/javascript/NullPointerExceptionTransformer.java
index f915886d9..3d66705cb 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/NullPointerExceptionTransformer.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/NullPointerExceptionTransformer.java
@@ -26,7 +26,7 @@ import org.teavm.model.instructions.NullCheckInstruction;
*/
public class NullPointerExceptionTransformer implements ClassHolderTransformer {
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
for (MethodHolder method : cls.getMethods()) {
Program program = method.getProgram();
if (program == null) {
diff --git a/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java b/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java
index 593360e11..4ae8cdcb0 100644
--- a/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java
+++ b/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java
@@ -15,10 +15,11 @@
*/
package org.teavm.model;
+
/**
*
* @author Alexey Andreev
*/
public interface ClassHolderTransformer {
- void transformClass(ClassHolder cls, ClassReaderSource innerSource);
+ void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics);
}
diff --git a/teavm-core/src/main/java/org/teavm/model/Diagnostics.java b/teavm-core/src/main/java/org/teavm/model/Diagnostics.java
new file mode 100644
index 000000000..f7b046100
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/model/Diagnostics.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 Alexey Andreev.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.teavm.model;
+
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public interface Diagnostics {
+ void error(InstructionLocation location, String error);
+
+ void error(String error);
+
+ void warning(InstructionLocation location, String error);
+
+ void warning(String error);
+}
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 634e82edc..979346193 100644
--- a/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java
+++ b/teavm-core/src/main/java/org/teavm/tooling/TeaVMTool.java
@@ -345,12 +345,12 @@ public class TeaVMTool {
}
}
- public DependencyViolations getDependencyViolations() {
- return vm.getDependencyViolations();
+ public DependencyViolations getViolations() {
+ return vm.getViolations();
}
public void checkForMissingItems() {
- vm.checkForMissingItems();
+ vm.checkForViolations();
}
private void copySourceFiles() {
diff --git a/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblem.java b/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblem.java
new file mode 100644
index 000000000..233d17ab7
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblem.java
@@ -0,0 +1,46 @@
+/*
+ * 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.vm;
+
+import org.teavm.model.InstructionLocation;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class DiagnosticsProblem {
+ private DiagnosticsProblemSeverity severity;
+ private InstructionLocation location;
+ private String text;
+
+ public DiagnosticsProblem(DiagnosticsProblemSeverity severity, InstructionLocation location, String text) {
+ this.severity = severity;
+ this.location = location;
+ this.text = text;
+ }
+
+ public DiagnosticsProblemSeverity getSeverity() {
+ return severity;
+ }
+
+ public InstructionLocation getLocation() {
+ return location;
+ }
+
+ public String getText() {
+ return text;
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblemSeverity.java b/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblemSeverity.java
new file mode 100644
index 000000000..8fa47a89f
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblemSeverity.java
@@ -0,0 +1,25 @@
+/*
+ * 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.vm;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public enum DiagnosticsProblemSeverity {
+ ERROR,
+ WARNING
+}
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 812a78191..a2479e3a4 100644
--- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java
+++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java
@@ -291,7 +291,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* Java class library methods. The behavior of this method before building is not specified.
*/
public boolean hasMissingItems() {
- return dependencyChecker.hasMissingItems();
+ return dependencyChecker.hasViolations();
}
/**
@@ -302,11 +302,11 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* @param target where to append all dependency diagnostics errors.
*/
public void showMissingItems(Appendable target) throws IOException {
- dependencyChecker.showMissingItems(target);
+ dependencyChecker.showViolations(target);
}
- public DependencyViolations getDependencyViolations() {
- return dependencyChecker.getDependencyViolations();
+ public DependencyViolations getViolations() {
+ return dependencyChecker.getViolations();
}
public Collection getClasses() {
@@ -327,8 +327,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* This can happen when you forgot some items in class path or when your code uses unimplemented
* Java class library methods. The behavior of this method before building is not specified.
*/
- public void checkForMissingItems() {
- dependencyChecker.checkForMissingItems();
+ public void checkForViolations() {
+ dependencyChecker.checkForViolations();
}
public DebugInformationEmitter getDebugEmitter() {
@@ -344,7 +344,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* are specified. This method may fail if there are items (classes, methods and fields)
* that are required by entry points, but weren't found in classpath. In this case no
* actual generation happens and no exceptions thrown, but you can further call
- * {@link #checkForMissingItems()} or {@link #hasMissingItems()} to learn the build state.
+ * {@link #checkForViolations()} or {@link #hasMissingItems()} to learn the build state.
*
* @param writer where to generate JavaScript. Should not be null.
* @param target where to generate additional resources. Can be null, but if there are
diff --git a/teavm-core/src/main/java/org/teavm/vm/Violations.java b/teavm-core/src/main/java/org/teavm/vm/Violations.java
new file mode 100644
index 000000000..20d2f0ca1
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/vm/Violations.java
@@ -0,0 +1,42 @@
+/*
+ * 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.vm;
+
+import java.util.List;
+import java.util.Set;
+import org.teavm.dependency.ClassDependencyInfo;
+import org.teavm.dependency.FieldDependencyInfo;
+import org.teavm.dependency.MethodDependencyInfo;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public interface Violations {
+ Set getMissingMethods();
+
+ Set getMissingClasses();
+
+ Set getMissingFields();
+
+ List getDiagnosticsProblems();
+
+ List getSevereDiagnosticsProblems();
+
+ boolean hasSevereViolations();
+
+ void checkForViolations();
+}
diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JCLHacks.java b/teavm-html4j/src/main/java/org/teavm/html4j/JCLHacks.java
index 7a0cbd850..1e4755d63 100644
--- a/teavm-html4j/src/main/java/org/teavm/html4j/JCLHacks.java
+++ b/teavm-html4j/src/main/java/org/teavm/html4j/JCLHacks.java
@@ -24,7 +24,7 @@ import org.teavm.model.instructions.*;
*/
public class JCLHacks implements ClassHolderTransformer {
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
if (cls.getName().equals("java.lang.Thread")) {
installThreadMethods(cls);
}
diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java
index 4359fcc42..4298c01f2 100644
--- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java
+++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java
@@ -25,7 +25,7 @@ import org.teavm.model.*;
*/
public class JavaScriptBodyTransformer implements ClassHolderTransformer {
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
for (MethodHolder method : cls.getMethods()) {
if (method.getAnnotations().get(JavaScriptBody.class.getName()) != null) {
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
diff --git a/teavm-jso/src/main/java/org/teavm/jso/plugin/JSObjectClassTransformer.java b/teavm-jso/src/main/java/org/teavm/jso/plugin/JSObjectClassTransformer.java
index 6af34c710..cc82e5072 100644
--- a/teavm-jso/src/main/java/org/teavm/jso/plugin/JSObjectClassTransformer.java
+++ b/teavm-jso/src/main/java/org/teavm/jso/plugin/JSObjectClassTransformer.java
@@ -15,10 +15,7 @@
*/
package org.teavm.jso.plugin;
-import org.teavm.model.ClassHolder;
-import org.teavm.model.ClassHolderTransformer;
-import org.teavm.model.ClassReaderSource;
-import org.teavm.model.MethodHolder;
+import org.teavm.model.*;
/**
*
@@ -28,8 +25,9 @@ class JSObjectClassTransformer implements ClassHolderTransformer {
private ThreadLocal processor = new ThreadLocal<>();
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
JavascriptNativeProcessor processor = getProcessor(innerSource);
+ processor.setDiagnostics(diagnostics);
processor.processClass(cls);
for (MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null) {
diff --git a/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java b/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java
index c3af8a24a..456966d75 100644
--- a/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java
+++ b/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java
@@ -30,12 +30,17 @@ class JavascriptNativeProcessor {
private Program program;
private List replacement = new ArrayList<>();
private NativeJavascriptClassRepository nativeRepos;
+ private Diagnostics diagnostics;
public JavascriptNativeProcessor(ClassReaderSource classSource) {
this.classSource = classSource;
nativeRepos = new NativeJavascriptClassRepository(classSource);
}
+ public void setDiagnostics(Diagnostics diagnostics) {
+ this.diagnostics = diagnostics;
+ }
+
public void processClass(ClassHolder cls) {
Set preservedMethods = new HashSet<>();
for (String iface : cls.getInterfaces()) {
@@ -90,7 +95,7 @@ class JavascriptNativeProcessor {
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
addPropertyGet(propertyName, invoke.getInstance(), result);
if (result != null) {
- result = unwrap(result, method.getResultType());
+ result = unwrap(insn.getLocation(), result, method.getResultType());
copyVar(result, invoke.getReceiver());
}
} else if (isProperSetter(method.getDescriptor())) {
@@ -101,11 +106,13 @@ class JavascriptNativeProcessor {
} else {
propertyName = cutPrefix(method.getName(), 3);
}
- Variable wrapped = wrapArgument(invoke.getArguments().get(0), method.parameterType(0));
+ Variable wrapped = wrapArgument(insn.getLocation(), invoke.getArguments().get(0),
+ method.parameterType(0));
addPropertySet(propertyName, invoke.getInstance(), wrapped);
} else {
- throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
+ diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript property declaration");
+ continue;
}
} else if (method.getAnnotations().get(JSIndexer.class.getName()) != null) {
if (isProperGetIndexer(method.getDescriptor())) {
@@ -113,7 +120,7 @@ class JavascriptNativeProcessor {
addIndexerGet(invoke.getInstance(), wrap(invoke.getArguments().get(0),
method.parameterType(0)), result);
if (result != null) {
- result = unwrap(result, method.getResultType());
+ result = unwrap(insn.getLocation(), result, method.getResultType());
copyVar(result, invoke.getReceiver());
}
} else if (isProperSetIndexer(method.getDescriptor())) {
@@ -121,8 +128,9 @@ class JavascriptNativeProcessor {
Variable value = wrap(invoke.getArguments().get(1), method.parameterType(1));
addIndexerSet(invoke.getInstance(), index, value);
} else {
- throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
+ diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript indexer declaration");
+ continue;
}
} else {
String name = method.getName();
@@ -130,16 +138,18 @@ class JavascriptNativeProcessor {
boolean isConstructor = false;
if (constructorAnnot != null) {
if (!isSupportedType(method.getResultType())) {
- throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
+ diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript constructor declaration");
+ 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) {
- throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
+ diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
"declared as a native JavaScript constructor, but its name does " +
"not satisfy conventions");
+ continue;
}
name = method.getName().substring(3);
}
@@ -153,14 +163,16 @@ class JavascriptNativeProcessor {
}
}
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
- throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
+ diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript method declaration");
+ continue;
}
}
for (ValueType arg : method.getParameterTypes()) {
if (!isSupportedType(arg)) {
- throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
+ diagnostics.error(insn.getLocation(), "Method " + invoke.getMethod() + " is not " +
"a proper native JavaScript method or constructor declaration");
+ continue;
}
}
Variable result = invoke.getReceiver() != null ? program.createVariable() : null;
@@ -174,12 +186,13 @@ class JavascriptNativeProcessor {
newInvoke.getArguments().add(invoke.getInstance());
newInvoke.getArguments().add(addStringWrap(addString(name)));
for (int k = 0; k < invoke.getArguments().size(); ++k) {
- Variable arg = wrapArgument(invoke.getArguments().get(k), method.parameterType(k));
+ Variable arg = wrapArgument(insn.getLocation(), invoke.getArguments().get(k),
+ method.parameterType(k));
newInvoke.getArguments().add(arg);
}
replacement.add(newInvoke);
if (result != null) {
- result = unwrap(result, method.getResultType());
+ result = unwrap(insn.getLocation(), result, method.getResultType());
copyVar(result, invoke.getReceiver());
}
}
@@ -254,7 +267,7 @@ class JavascriptNativeProcessor {
return var;
}
- private Variable unwrap(Variable var, ValueType type) {
+ private Variable unwrap(InstructionLocation location, Variable var, ValueType type) {
if (type instanceof ValueType.Primitive) {
switch (((ValueType.Primitive)type).getKind()) {
case BOOLEAN:
@@ -290,7 +303,8 @@ class JavascriptNativeProcessor {
return result;
}
}
- throw new IllegalArgumentException("Unsupported type: " + type);
+ diagnostics.error(location, "Unsupported type: " + type);
+ return var;
}
private Variable unwrap(Variable var, String methodName, ValueType resultType) {
@@ -305,20 +319,21 @@ class JavascriptNativeProcessor {
return result;
}
- private Variable wrapArgument(Variable var, ValueType type) {
+ private Variable wrapArgument(InstructionLocation location, Variable var, ValueType type) {
if (type instanceof ValueType.Object) {
String className = ((ValueType.Object)type).getClassName();
ClassReader cls = classSource.get(className);
if (cls.getAnnotations().get(JSFunctor.class.getName()) != null) {
- return wrapFunctor(var, cls);
+ return wrapFunctor(location, var, cls);
}
}
return wrap(var, type);
}
- private Variable wrapFunctor(Variable var, ClassReader type) {
+ private Variable wrapFunctor(InstructionLocation location, Variable var, ClassReader type) {
if (!type.hasModifier(ElementModifier.INTERFACE) || type.getMethods().size() != 1) {
- throw new RuntimeException("Wrong functor: " + type.getName());
+ diagnostics.error(location, "Wrong functor: " + type.getName());
+ return var;
}
String name = type.getMethods().iterator().next().getName();
Variable functor = program.createVariable();
diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java
index f8d25aadf..bb1a04c61 100644
--- a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java
+++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java
@@ -25,7 +25,7 @@ import org.teavm.platform.metadata.MetadataProvider;
*/
class MetadataProviderTransformer implements ClassHolderTransformer {
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
for (MethodHolder method : cls.getMethods()) {
AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName());
if (providerAnnot == null) {
diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java
index 6a3819013..aed4fc2df 100644
--- a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java
+++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorTransformer.java
@@ -15,10 +15,7 @@
*/
package org.teavm.platform.plugin;
-import org.teavm.model.ClassHolder;
-import org.teavm.model.ClassHolderTransformer;
-import org.teavm.model.ClassReaderSource;
-import org.teavm.model.MethodHolder;
+import org.teavm.model.*;
import org.teavm.vm.spi.TeaVMHost;
/**
@@ -33,7 +30,7 @@ class ResourceAccessorTransformer implements ClassHolderTransformer {
}
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
if (cls.getName().equals(ResourceAccessor.class.getName())) {
ResourceAccessorGenerator generator = new ResourceAccessorGenerator();
for (MethodHolder method : cls.getMethods()) {
diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceTransformer.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceTransformer.java
index f0b8854d2..2b29aae60 100644
--- a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceTransformer.java
+++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceTransformer.java
@@ -23,7 +23,7 @@ import org.teavm.model.*;
*/
class ResourceTransformer implements ClassHolderTransformer {
@Override
- public void transformClass(ClassHolder cls, ClassReaderSource innerSource) {
+ public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
for (MethodHolder method : cls.getMethods()) {
Program program = method.getProgram();
if (program != null) {