diff --git a/teavm-core/src/main/java/org/teavm/callgraph/CallGraph.java b/teavm-core/src/main/java/org/teavm/callgraph/CallGraph.java
new file mode 100644
index 000000000..213ce96d7
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/CallGraph.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 Alexey Andreev.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.teavm.callgraph;
+
+import java.util.Collection;
+import org.teavm.model.FieldReference;
+import org.teavm.model.MethodReference;
+
+/**
+ *
Root object for traversing through call graph. Graph does not represent polymorphic calls.
+ * Instead, it generated multiple call sites for one location.
+ *
+ * @author Alexey Andreev
+ */
+public interface CallGraph {
+ /**
+ * Get node corresponding to the specific method.
+ *
+ * @param method a method to lookup node for.
+ * @return the node that corresponds to the specified method or null
, if this method is never
+ * called.
+ */
+ CallGraphNode getNode(MethodReference method);
+
+ Collection extends FieldAccessSite> getFieldAccess(FieldReference reference);
+
+ Collection extends ClassAccessSite> getClassAccess(String className);
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/CallGraphNode.java b/teavm-core/src/main/java/org/teavm/callgraph/CallGraphNode.java
new file mode 100644
index 000000000..b027e3bed
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/CallGraphNode.java
@@ -0,0 +1,49 @@
+/*
+ * 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.callgraph;
+
+import java.util.Collection;
+import org.teavm.model.MethodReference;
+
+/**
+ * Represents a method with information about what methods does it call and what method do call the method.
+ * @author Alexey Andreev
+ */
+public interface CallGraphNode {
+ /*
+ * Returns reference to entire call graph.
+ */
+ CallGraph getGraph();
+
+ /**
+ * Returns the method that this node represents.
+ */
+ MethodReference getMethod();
+
+ /**
+ * Returns immutable collection of all call sites that are in the method.
+ */
+ Collection extends CallSite> getCallSites();
+
+ /**
+ * Returns immutable collection of all call sites that call this method.
+ */
+ Collection extends CallSite> getCallerCallSites();
+
+ Collection extends FieldAccessSite> getFieldAccessSites();
+
+ Collection extends ClassAccessSite> getClassAccessSites();
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/CallSite.java b/teavm-core/src/main/java/org/teavm/callgraph/CallSite.java
new file mode 100644
index 000000000..3aa170b13
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/CallSite.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 Alexey Andreev.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.teavm.callgraph;
+
+import org.teavm.model.InstructionLocation;
+
+/**
+ * Call site that represents exact place in the code that calls a method.
.
+ * @author Alexey Andreev
+ */
+public interface CallSite {
+ /**
+ * Gets location of the call site
.
+ *
+ * @return location of the call site or null
if no debug information found for this call site.
+ */
+ InstructionLocation getLocation();
+
+ /**
+ * Gets a method that this call site invokes.
+ */
+ CallGraphNode getCallee();
+
+ /**
+ * Gets a method that contains this call site.
+ */
+ CallGraphNode getCaller();
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/ClassAccessSite.java b/teavm-core/src/main/java/org/teavm/callgraph/ClassAccessSite.java
new file mode 100644
index 000000000..51bbb2528
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/ClassAccessSite.java
@@ -0,0 +1,30 @@
+/*
+ * 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.callgraph;
+
+import org.teavm.model.InstructionLocation;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public interface ClassAccessSite {
+ InstructionLocation getLocation();
+
+ CallGraphNode getCallee();
+
+ String getClassName();
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraph.java b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraph.java
new file mode 100644
index 000000000..67249c67d
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraph.java
@@ -0,0 +1,72 @@
+/*
+ * 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.callgraph;
+
+import java.util.*;
+import org.teavm.model.FieldReference;
+import org.teavm.model.MethodReference;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class DefaultCallGraph implements CallGraph {
+ private Map nodes = new HashMap<>();
+ private Map> fieldAccessSites = new HashMap<>();
+ private Map> classAccessSites = new HashMap<>();
+
+ @Override
+ public DefaultCallGraphNode getNode(MethodReference method) {
+ DefaultCallGraphNode node = nodes.get(method);
+ if (node == null) {
+ node = new DefaultCallGraphNode(this);
+ nodes.put(method, node);
+ }
+ return nodes.get(method);
+ }
+
+ @Override
+ public Collection getFieldAccess(FieldReference reference) {
+ Set resultSet = fieldAccessSites.get(reference);
+ return resultSet != null ? Collections.unmodifiableSet(resultSet) :
+ Collections.emptySet();
+ }
+
+ void addFieldAccess(DefaultFieldAccessSite accessSite) {
+ Set sites = fieldAccessSites.get(accessSite.getField());
+ if (sites == null) {
+ sites = new HashSet<>();
+ fieldAccessSites.put(accessSite.getField(), sites);
+ }
+ sites.add(accessSite);
+ }
+
+ @Override
+ public Collection getClassAccess(String className) {
+ Set resultSet = classAccessSites.get(className);
+ return resultSet != null ? Collections.unmodifiableSet(resultSet) :
+ Collections.emptySet();
+ }
+
+ void addClassAccess(DefaultClassAccessSite accessSite) {
+ Set sites = classAccessSites.get(accessSite.getClassName());
+ if (sites == null) {
+ sites = new HashSet<>();
+ classAccessSites.put(accessSite.getClassName(), sites);
+ }
+ sites.add(accessSite);
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java
new file mode 100644
index 000000000..2b54ef7ee
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallGraphNode.java
@@ -0,0 +1,113 @@
+/*
+ * 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.callgraph;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.teavm.model.FieldReference;
+import org.teavm.model.InstructionLocation;
+import org.teavm.model.MethodReference;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class DefaultCallGraphNode implements CallGraphNode {
+ private DefaultCallGraph graph;
+ private MethodReference method;
+ private Set callSites;
+ private transient Set safeCallSites;
+ private List callerCallSites;
+ private transient List safeCallersCallSites;
+ private Set fieldAccessSites;
+ private transient Set safeFieldAccessSites;
+ private Set classAccessSites;
+ private transient Set safeClassAccessSites;
+
+ DefaultCallGraphNode(DefaultCallGraph graph) {
+ this.graph = graph;
+ }
+
+ @Override
+ public DefaultCallGraph getGraph() {
+ return graph;
+ }
+
+ @Override
+ public MethodReference getMethod() {
+ return method;
+ }
+
+ @Override
+ public Collection getCallSites() {
+ if (safeCallSites == null) {
+ safeCallSites = Collections.unmodifiableSet(callSites);
+ }
+ return safeCallSites;
+ }
+
+ @Override
+ public Collection getCallerCallSites() {
+ if (safeCallersCallSites == null) {
+ safeCallersCallSites = Collections.unmodifiableList(callerCallSites);
+ }
+ return safeCallersCallSites;
+ }
+
+ public void addCallSite(MethodReference method, InstructionLocation location) {
+ DefaultCallGraphNode callee = graph.getNode(method);
+ DefaultCallSite callSite = new DefaultCallSite(location, callee, this);
+ if (callSites.add(callSite)) {
+ callee.callerCallSites.add(callSite);
+ }
+ }
+
+ public void addCallSite(MethodReference method) {
+ addCallSite(method, null);
+ }
+
+ @Override
+ public Collection getFieldAccessSites() {
+ if (safeFieldAccessSites == null) {
+ safeFieldAccessSites = Collections.unmodifiableSet(fieldAccessSites);
+ }
+ return safeFieldAccessSites;
+ }
+
+ public void addFieldAccess(FieldReference field, InstructionLocation location) {
+ DefaultFieldAccessSite site = new DefaultFieldAccessSite(location, this, field);
+ if (fieldAccessSites.add(site)) {
+ graph.addFieldAccess(site);
+ }
+ }
+
+ @Override
+ public Collection extends ClassAccessSite> getClassAccessSites() {
+ if (safeClassAccessSites == null) {
+ safeClassAccessSites = Collections.unmodifiableSet(classAccessSites);
+ }
+ return safeClassAccessSites;
+ }
+
+ public void addClassAccess(String className, InstructionLocation location) {
+ DefaultClassAccessSite site = new DefaultClassAccessSite(location, this, className);
+ if (classAccessSites.add(site)) {
+ graph.addClassAccess(site);
+ }
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallSite.java b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallSite.java
new file mode 100644
index 000000000..badb1d35f
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/DefaultCallSite.java
@@ -0,0 +1,68 @@
+/*
+ * 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.callgraph;
+
+import java.util.Objects;
+import org.teavm.model.InstructionLocation;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class DefaultCallSite implements CallSite {
+ private InstructionLocation location;
+ private DefaultCallGraphNode callee;
+ private DefaultCallGraphNode caller;
+
+ DefaultCallSite(InstructionLocation location, DefaultCallGraphNode callee, DefaultCallGraphNode caller) {
+ this.location = location;
+ this.callee = callee;
+ this.caller = caller;
+ }
+
+ @Override
+ public InstructionLocation getLocation() {
+ return location;
+ }
+
+ @Override
+ public DefaultCallGraphNode getCallee() {
+ return callee;
+ }
+
+ @Override
+ public DefaultCallGraphNode getCaller() {
+ return caller;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof DefaultCallSite)) {
+ return false;
+ }
+ DefaultCallSite other = (DefaultCallSite)obj;
+ return Objects.equals(callee.getMethod(), other.callee.getMethod()) &&
+ Objects.equals(location, other.location);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(callee.getMethod(), location);
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/DefaultClassAccessSite.java b/teavm-core/src/main/java/org/teavm/callgraph/DefaultClassAccessSite.java
new file mode 100644
index 000000000..66ddc1bb4
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/DefaultClassAccessSite.java
@@ -0,0 +1,49 @@
+/*
+ * 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.callgraph;
+
+import org.teavm.model.InstructionLocation;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class DefaultClassAccessSite implements ClassAccessSite {
+ private InstructionLocation location;
+ private CallGraphNode callee;
+ private String className;
+
+ DefaultClassAccessSite(InstructionLocation location, CallGraphNode callee, String className) {
+ this.location = location;
+ this.callee = callee;
+ this.className = className;
+ }
+
+ @Override
+ public InstructionLocation getLocation() {
+ return location;
+ }
+
+ @Override
+ public CallGraphNode getCallee() {
+ return callee;
+ }
+
+ @Override
+ public String getClassName() {
+ return className;
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/DefaultFieldAccessSite.java b/teavm-core/src/main/java/org/teavm/callgraph/DefaultFieldAccessSite.java
new file mode 100644
index 000000000..52594377d
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/DefaultFieldAccessSite.java
@@ -0,0 +1,69 @@
+/*
+ * 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.callgraph;
+
+import java.util.Objects;
+import org.teavm.model.FieldReference;
+import org.teavm.model.InstructionLocation;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class DefaultFieldAccessSite implements FieldAccessSite {
+ private InstructionLocation location;
+ private CallGraphNode callee;
+ private FieldReference field;
+
+ DefaultFieldAccessSite(InstructionLocation location, CallGraphNode callee, FieldReference field) {
+ this.location = location;
+ this.callee = callee;
+ this.field = field;
+ }
+
+ @Override
+ public InstructionLocation getLocation() {
+ return null;
+ }
+
+ @Override
+ public CallGraphNode getCallee() {
+ return null;
+ }
+
+ @Override
+ public FieldReference getField() {
+ return null;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(location, callee, field);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof DefaultFieldAccessSite)) {
+ return false;
+ }
+ DefaultFieldAccessSite other = (DefaultFieldAccessSite)obj;
+ return Objects.equals(location, other.location) && Objects.equals(callee, other.callee) &&
+ Objects.equals(field, other.field);
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/callgraph/FieldAccessSite.java b/teavm-core/src/main/java/org/teavm/callgraph/FieldAccessSite.java
new file mode 100644
index 000000000..938a8721f
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/callgraph/FieldAccessSite.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.callgraph;
+
+import org.teavm.model.FieldReference;
+import org.teavm.model.InstructionLocation;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public interface FieldAccessSite {
+ InstructionLocation getLocation();
+
+ CallGraphNode getCallee();
+
+ FieldReference getField();
+}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/ClassDependency.java b/teavm-core/src/main/java/org/teavm/dependency/ClassDependency.java
index 17b85d577..c3ff7e859 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/ClassDependency.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/ClassDependency.java
@@ -16,6 +16,8 @@
package org.teavm.dependency;
import org.teavm.model.ClassReader;
+import org.teavm.model.InstructionLocation;
+import org.teavm.model.MethodReference;
/**
*
@@ -24,13 +26,11 @@ import org.teavm.model.ClassReader;
public class ClassDependency implements ClassDependencyInfo {
private DependencyChecker checker;
private String className;
- private DependencyStack stack;
private ClassReader classReader;
- ClassDependency(DependencyChecker checker, String className, DependencyStack stack, ClassReader classReader) {
+ ClassDependency(DependencyChecker checker, String className, ClassReader classReader) {
this.checker = checker;
this.className = className;
- this.stack = stack;
this.classReader = classReader;
}
@@ -48,14 +48,9 @@ public class ClassDependency implements ClassDependencyInfo {
return classReader;
}
- @Override
- public DependencyStack getStack() {
- return stack;
- }
-
- public void initClass(DependencyStack stack) {
+ public void initClass(MethodReference caller, InstructionLocation location) {
if (!isMissing()) {
- checker.initClass(this, stack);
+ checker.initClass(this, caller, location);
}
}
}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/ClassDependencyInfo.java b/teavm-core/src/main/java/org/teavm/dependency/ClassDependencyInfo.java
index 46ecc9c72..84c695720 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/ClassDependencyInfo.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/ClassDependencyInfo.java
@@ -23,6 +23,4 @@ public interface ClassDependencyInfo {
String getClassName();
boolean isMissing();
-
- DependencyStack getStack();
}
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 07cb02d55..4862610b8 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyAgent.java
@@ -16,10 +16,8 @@
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;
+import org.teavm.diagnostics.Diagnostics;
+import org.teavm.model.*;
/**
*
@@ -34,11 +32,11 @@ public interface DependencyAgent extends DependencyInfo, ServiceRepository {
void submitClass(ClassHolder cls);
- MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack);
+ MethodDependency linkMethod(MethodReference methodRef, MethodReference caller, InstructionLocation location);
- ClassDependency linkClass(String className, final DependencyStack stack);
+ ClassDependency linkClass(String className, MethodReference caller, InstructionLocation location);
- FieldDependency linkField(FieldReference fieldRef, DependencyStack stack);
+ FieldDependency linkField(FieldReference fieldRef, MethodReference caller, InstructionLocation location);
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 d2bbfbd50..1e43dad3a 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java
@@ -17,8 +17,11 @@ package org.teavm.dependency;
import java.io.IOException;
import java.util.*;
+import org.teavm.callgraph.CallGraph;
+import org.teavm.callgraph.DefaultCallGraph;
import org.teavm.common.*;
import org.teavm.common.CachedMapper.KeyListener;
+import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
import org.teavm.model.util.ModelUtils;
@@ -33,9 +36,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
private ClassLoader classLoader;
private Mapper methodReaderCache;
private Mapper fieldReaderCache;
- private Map stacks = new HashMap<>();
- private Map fieldStacks = new HashMap<>();
- private Map classStacks = new HashMap<>();
private CachedMapper methodCache;
private CachedMapper fieldCache;
private CachedMapper classCache;
@@ -51,6 +51,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
private DependencyCheckerInterruptor interruptor;
private boolean interrupted;
private Diagnostics diagnostics;
+ private DefaultCallGraph callGraph = new DefaultCallGraph();
public DependencyChecker(ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
Diagnostics diagnostics) {
@@ -72,26 +73,24 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
@Override public MethodDependency map(MethodReference preimage) {
MethodReader method = methodReaderCache.map(preimage);
if (method != null && !method.getReference().equals(preimage)) {
- stacks.put(method.getReference(), stacks.get(preimage));
return methodCache.map(method.getReference());
}
- return createMethodDep(preimage, method, stacks.get(preimage));
+ return createMethodDep(preimage, method);
}
});
fieldCache = new CachedMapper<>(new Mapper() {
@Override public FieldDependency map(FieldReference preimage) {
FieldReader field = fieldReaderCache.map(preimage);
if (field != null && !field.getReference().equals(preimage)) {
- fieldStacks.put(field.getReference(), fieldStacks.get(preimage));
return fieldCache.map(field.getReference());
}
- return createFieldNode(preimage, field, fieldStacks.get(preimage));
+ return createFieldNode(preimage, field);
}
});
classCache = new CachedMapper<>(new Mapper() {
@Override public ClassDependency map(String preimage) {
- return createClassDependency(preimage, classStacks.get(preimage));
+ return createClassDependency(preimage);
}
});
methodCache.addKeyListener(new KeyListener() {
@@ -167,7 +166,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
@Override
public String generateClassName() {
- return "$$tmp$$.TempClass" + classNameSuffix++;
+ return "$$teavm_generated_class$$" + classNameSuffix++;
}
@Override
@@ -189,7 +188,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
if (parameters.length + 1 != argumentTypes.length) {
throw new IllegalArgumentException("argumentTypes length does not match the number of method's arguments");
}
- MethodDependency method = linkMethod(methodRef, DependencyStack.ROOT);
+ MethodDependency method = linkMethod(methodRef, null, null);
method.use();
DependencyNode[] varNodes = method.getVariables();
varNodes[0].propagate(getType(methodRef.getClassName()));
@@ -218,7 +217,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
@Override
public ClassDependency linkClass(String className, DependencyStack stack) {
- classStacks.put(className, stack);
return classCache.map(className);
}
@@ -239,21 +237,26 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
}
@Override
- public MethodDependency linkMethod(MethodReference methodRef, DependencyStack stack) {
+ public MethodDependency linkMethod(MethodReference methodRef, MethodReference caller,
+ InstructionLocation location) {
if (methodRef == null) {
throw new IllegalArgumentException();
}
- stacks.put(methodRef, stack);
+ callGraph.addNode(methodRef);
+ if (caller != null) {
+ callGraph.addNode(caller);
+ callGraph.getNode(caller).addCallSite(methodRef, location);
+ }
return methodCache.map(methodRef);
}
- void initClass(ClassDependency cls, final DependencyStack stack) {
+ void initClass(ClassDependency cls, final MethodReference caller, final InstructionLocation location) {
ClassReader reader = cls.getClassReader();
final MethodReader method = reader.getMethod(new MethodDescriptor("", void.class));
if (method != null) {
tasks.add(new Runnable() {
@Override public void run() {
- linkMethod(method.getReference(), stack).use();
+ linkMethod(method.getReference(), caller, location).use();
}
});
}
@@ -373,7 +376,7 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
}
@Override
- public FieldDependency linkField(FieldReference fieldRef, DependencyStack stack) {
+ public FieldDependency linkField(FieldReference fieldRef, MethodReference caller, InstructionLocation location) {
fieldStacks.put(fieldRef, stack);
return fieldCache.map(fieldRef);
}
@@ -434,25 +437,6 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
return methodCache.getKnown(methodRef);
}
- public DependencyViolations getViolations() {
- if (dependencyViolations == null) {
- dependencyViolations = new DependencyViolations(missingMethods, missingClasses, missingFields);
- }
- return dependencyViolations;
- }
-
- public void checkForViolations() {
- getViolations().checkForViolations();
- }
-
- public boolean hasViolations() {
- return getViolations().hasSevereViolations();
- }
-
- public void showViolations(Appendable sb) throws IOException {
- getViolations().showViolations(sb);
- }
-
public void processDependencies() {
interrupted = false;
int index = 0;
@@ -477,4 +461,8 @@ public class DependencyChecker implements DependencyInfo, DependencyAgent {
public Diagnostics getDiagnostics() {
return diagnostics;
}
+
+ public CallGraph getCallGraph() {
+ return callGraph;
+ }
}
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 681fb0df8..672a7416c 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyClassSource.java
@@ -22,6 +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.diagnostics.Diagnostics;
import org.teavm.model.*;
import org.teavm.model.util.ModelUtils;
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 dfdb9e71b..92cff7e72 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java
@@ -18,6 +18,7 @@ package org.teavm.dependency;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.teavm.callgraph.DefaultCallGraphNode;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
import org.teavm.model.util.ListingBuilder;
@@ -31,7 +32,8 @@ class DependencyGraphBuilder {
private DependencyNode[] nodes;
private DependencyNode resultNode;
private ProgramReader program;
- private DependencyStack callerStack;
+ private DefaultCallGraphNode caller;
+ private InstructionLocation currentLocation;
private ExceptionConsumer currentExceptionConsumer;
public DependencyGraphBuilder(DependencyChecker dependencyChecker) {
@@ -50,7 +52,6 @@ class DependencyGraphBuilder {
}
resultNode = dep.getResult();
nodes = dep.getVariables();
- callerStack = new DependencyStack(method.getReference(), dep.getStack());
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlockReader block = program.basicBlockAt(i);
currentExceptionConsumer = createExceptionConsumer(dep, block);
@@ -62,7 +63,7 @@ class DependencyGraphBuilder {
}
for (TryCatchBlockReader tryCatch : block.readTryCatchBlocks()) {
if (tryCatch.getExceptionType() != null) {
- dependencyChecker.linkClass(tryCatch.getExceptionType(), callerStack);
+ dependencyChecker.linkClass(tryCatch.getExceptionType(), caller.getMethod(), null);
}
}
}
@@ -116,20 +117,23 @@ class DependencyGraphBuilder {
private final DependencyChecker checker;
private final DependencyNode[] parameters;
private final DependencyNode result;
- private final DependencyStack stack;
+ private final DefaultCallGraphNode caller;
+ private final InstructionLocation location;
private final Set knownMethods = new HashSet<>();
private ExceptionConsumer exceptionConsumer;
public VirtualCallConsumer(DependencyNode node, ClassReader filterClass,
MethodDescriptor methodDesc, DependencyChecker checker, DependencyNode[] parameters,
- DependencyNode result, DependencyStack stack, ExceptionConsumer exceptionConsumer) {
+ DependencyNode result, DefaultCallGraphNode caller, InstructionLocation location,
+ ExceptionConsumer exceptionConsumer) {
this.node = node;
this.filterClass = filterClass;
this.methodDesc = methodDesc;
this.checker = checker;
this.parameters = parameters;
this.result = result;
- this.stack = stack;
+ this.caller = caller;
+ this.location = location;
this.exceptionConsumer = exceptionConsumer;
}
@@ -147,7 +151,7 @@ class DependencyGraphBuilder {
return;
}
MethodReference methodRef = new MethodReference(className, methodDesc);
- MethodDependency methodDep = checker.linkMethod(methodRef, stack);
+ MethodDependency methodDep = checker.linkMethod(methodRef, caller.getMethod(), location);
if (!methodDep.isMissing() && knownMethods.add(methodRef)) {
methodDep.use();
DependencyNode[] targetParams = methodDep.getVariables();
@@ -185,7 +189,7 @@ class DependencyGraphBuilder {
private InstructionReader reader = new InstructionReader() {
@Override
public void location(InstructionLocation location) {
- callerStack = new DependencyStack(callerStack.getMethod(), location, callerStack.getCause());
+ currentLocation = location;
}
@Override
@@ -200,7 +204,7 @@ class DependencyGraphBuilder {
}
if (cst instanceof ValueType.Object) {
final String className = ((ValueType.Object)cst).getClassName();
- dependencyChecker.linkClass(className, callerStack);
+ dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
}
}
@@ -228,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), callerStack);
+ "", char[].class, void.class), caller.getMethod(), currentLocation);
method.use();
}
@@ -316,7 +320,7 @@ class DependencyGraphBuilder {
nodes[receiver.getIndex()].propagate(dependencyChecker.getType("[" + itemType));
String className = extractClassName(itemType);
if (className != null) {
- dependencyChecker.linkClass(className, callerStack);
+ dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
}
}
@@ -338,7 +342,7 @@ class DependencyGraphBuilder {
nodes[receiver.getIndex()].propagate(dependencyChecker.getType(sb.toString()));
String className = extractClassName(itemType);
if (className != null) {
- dependencyChecker.linkClass(className, callerStack);
+ dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
}
}
@@ -350,7 +354,7 @@ class DependencyGraphBuilder {
@Override
public void getField(VariableReader receiver, VariableReader instance, FieldReference field,
ValueType fieldType) {
- FieldDependency fieldDep = dependencyChecker.linkField(field, callerStack);
+ FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation);
DependencyNode receiverNode = nodes[receiver.getIndex()];
fieldDep.getValue().connect(receiverNode);
initClass(field.getClassName());
@@ -358,7 +362,7 @@ class DependencyGraphBuilder {
@Override
public void putField(VariableReader instance, FieldReference field, VariableReader value) {
- FieldDependency fieldDep = dependencyChecker.linkField(field, callerStack);
+ FieldDependency fieldDep = dependencyChecker.linkField(field, caller.getMethod(), currentLocation);
DependencyNode valueNode = nodes[value.getIndex()];
valueNode.connect(fieldDep.getValue());
initClass(field.getClassName());
@@ -420,7 +424,7 @@ class DependencyGraphBuilder {
private void invokeSpecial(VariableReader receiver, VariableReader instance, MethodReference method,
List extends VariableReader> arguments) {
- MethodDependency methodDep = dependencyChecker.linkMethod(method, callerStack);
+ MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation);
if (methodDep.isMissing()) {
return;
}
@@ -441,7 +445,7 @@ class DependencyGraphBuilder {
private void invokeVirtual(VariableReader receiver, VariableReader instance, MethodReference method,
List extends VariableReader> arguments) {
- MethodDependency methodDep = dependencyChecker.linkMethod(method, callerStack);
+ MethodDependency methodDep = dependencyChecker.linkMethod(method, caller.getMethod(), currentLocation);
if (methodDep.isMissing()) {
return;
}
@@ -453,7 +457,7 @@ class DependencyGraphBuilder {
DependencyConsumer listener = new VirtualCallConsumer(nodes[instance.getIndex()],
dependencyChecker.getClassSource().get(methodDep.getMethod().getOwnerName()),
method.getDescriptor(), dependencyChecker, actualArgs,
- receiver != null ? nodes[receiver.getIndex()] : null, callerStack,
+ receiver != null ? nodes[receiver.getIndex()] : null, caller, currentLocation,
currentExceptionConsumer);
nodes[instance.getIndex()].addConsumer(listener);
}
@@ -462,13 +466,14 @@ class DependencyGraphBuilder {
public void isInstance(VariableReader receiver, VariableReader value, final ValueType type) {
String className = extractClassName(type);
if (className != null) {
- dependencyChecker.linkClass(className, callerStack);
+ dependencyChecker.linkClass(className, caller.getMethod(), currentLocation);
}
}
@Override
public void initClass(final String className) {
- dependencyChecker.linkClass(className, callerStack).initClass(callerStack);
+ dependencyChecker.linkClass(className, caller.getMethod(), currentLocation)
+ .initClass(caller.getMethod(), currentLocation);
}
@Override
@@ -476,8 +481,8 @@ class DependencyGraphBuilder {
DependencyNode valueNode = nodes[value.getIndex()];
DependencyNode receiverNode = nodes[receiver.getIndex()];
valueNode.connect(receiverNode);
- dependencyChecker.linkMethod(new MethodReference("java.lang.NullPointerException",
- "", ValueType.VOID), callerStack).use();
+ dependencyChecker.linkMethod(new MethodReference(NullPointerException.class, "", void.class),
+ caller.getMethod(), currentLocation).use();
currentExceptionConsumer.consume(dependencyChecker.getType("java.lang.NullPointerException"));
}
};
diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyStack.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyStack.java
deleted file mode 100644
index 7072ddc44..000000000
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyStack.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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 org.teavm.model.InstructionLocation;
-import org.teavm.model.MethodReference;
-
-/**
- *
- * @author Alexey Andreev
- */
-public class DependencyStack {
- public static final DependencyStack ROOT = new DependencyStack();
- private MethodReference method;
- private DependencyStack cause;
- private InstructionLocation location;
-
- private DependencyStack() {
- }
-
- public DependencyStack(MethodReference method) {
- this(method, ROOT);
- }
-
- public DependencyStack(MethodReference method, InstructionLocation location) {
- this(method, location, ROOT);
- }
-
- public DependencyStack(MethodReference method, DependencyStack cause) {
- this(method, null, cause);
- }
-
- public DependencyStack(MethodReference method, InstructionLocation location, DependencyStack cause) {
- if (method == null || cause == null) {
- throw new IllegalArgumentException("Arguments must not be null");
- }
- this.method = method;
- this.location = location;
- this.cause = cause;
- }
-
- public MethodReference getMethod() {
- return method;
- }
-
- public DependencyStack getCause() {
- return cause;
- }
-
- public InstructionLocation getLocation() {
- return location;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- DependencyStack stack = this;
- while (true) {
- if (stack.method == null) {
- sb.append(" used by ROOT\n");
- break;
- } else {
- sb.append(" used by " + stack.method);
- if (stack.location != null) {
- sb.append(" : ").append(stack.location.getLine());
- }
- stack = stack.cause;
- }
- }
- return sb.toString();
- }
-}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyViolations.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyViolations.java
deleted file mode 100644
index 1e3d5997e..000000000
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyViolations.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.io.IOException;
-import java.util.*;
-
-/**
- *
- * @author Alexey Andreev
- */
-public class DependencyViolations {
- private final Set missingMethods;
- private final Set missingClasses;
- private final Set missingFields;
-
- DependencyViolations(Collection extends MethodDependencyInfo> missingMethods,
- Collection extends ClassDependencyInfo> missingClasses,
- Collection extends FieldDependencyInfo> missingFields) {
- this.missingMethods = Collections.unmodifiableSet(new HashSet<>(missingMethods));
- this.missingClasses = Collections.unmodifiableSet(new HashSet<>(missingClasses));
- this.missingFields = Collections.unmodifiableSet(new HashSet<>(missingFields));
- }
-
- public Set getMissingMethods() {
- return missingMethods;
- }
-
- public Set getMissingClasses() {
- return missingClasses;
- }
-
- public Set getMissingFields() {
- return missingFields;
- }
-
- public boolean hasSevereViolations() {
- return !missingMethods.isEmpty() || !missingClasses.isEmpty() || !missingFields.isEmpty();
- }
-
- public void checkForViolations() {
- if (!hasSevereViolations()) {
- return;
- }
- StringBuilder sb = new StringBuilder();
- try {
- showViolations(sb);
- } catch (IOException e) {
- throw new AssertionError("StringBuilder should not throw IOException");
- }
- throw new IllegalStateException(sb.toString());
- }
-
- public void showViolations(Appendable sb) throws IOException {
- List items = new ArrayList<>();
- Map stackMap = new HashMap<>();
- for (ClassDependencyInfo cls : missingClasses) {
- stackMap.put(cls.getClassName(), cls.getStack());
- items.add(cls.getClassName());
- }
- for (MethodDependencyInfo method : missingMethods) {
- stackMap.put(method.getReference().toString(), method.getStack());
- items.add(method.getReference().toString());
- }
- for (FieldDependencyInfo field : missingFields) {
- stackMap.put(field.getReference().toString(), field.getStack());
- items.add(field.getReference().toString());
- }
- Collections.sort(items);
- sb.append("Can't compile due to the following violations:\n");
- for (String item : items) {
- sb.append("Missing ").append(item).append("\n");
- DependencyStack stack = stackMap.get(item);
- if (stack == null) {
- sb.append(" at unknown location\n");
- } else {
- while (stack.getMethod() != null) {
- sb.append(" at ").append(stack.getMethod().toString());
- if (stack.getLocation() != null) {
- sb.append(":").append(String.valueOf(stack.getLocation().getLine()));
- }
- sb.append("\n");
- stack = stack.getCause();
- }
- }
- sb.append('\n');
- }
- }
-}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/FieldDependencyInfo.java b/teavm-core/src/main/java/org/teavm/dependency/FieldDependencyInfo.java
index 80f1ce936..6e7e1156f 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/FieldDependencyInfo.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/FieldDependencyInfo.java
@@ -27,6 +27,4 @@ public interface FieldDependencyInfo {
FieldReference getReference();
boolean isMissing();
-
- DependencyStack getStack();
}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/MethodDependencyInfo.java b/teavm-core/src/main/java/org/teavm/dependency/MethodDependencyInfo.java
index 4f06ebfec..cc3359a3a 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/MethodDependencyInfo.java
+++ b/teavm-core/src/main/java/org/teavm/dependency/MethodDependencyInfo.java
@@ -39,6 +39,4 @@ public interface MethodDependencyInfo {
boolean isUsed();
boolean isMissing();
-
- DependencyStack getStack();
}
diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyDiagnostics.java b/teavm-core/src/main/java/org/teavm/diagnostics/DependencyDiagnostics.java
similarity index 64%
rename from teavm-core/src/main/java/org/teavm/dependency/DependencyDiagnostics.java
rename to teavm-core/src/main/java/org/teavm/diagnostics/DependencyDiagnostics.java
index ac6cb6604..08d666ddc 100644
--- a/teavm-core/src/main/java/org/teavm/dependency/DependencyDiagnostics.java
+++ b/teavm-core/src/main/java/org/teavm/diagnostics/DependencyDiagnostics.java
@@ -13,26 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.dependency;
+package org.teavm.diagnostics;
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;
+import org.teavm.model.MethodReference;
/**
*
* @author Alexey Andreev
*/
class DependencyDiagnostics implements Diagnostics {
- private List problems = new ArrayList<>();
- private List severeProblems = new ArrayList<>();
+ 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);
+ public void error(MethodReference method, InstructionLocation location, String error, Object[] params) {
+ Problem violation = new Problem(ProblemSeverity.ERROR, location, error);
problems.add(violation);
severeProblems.add(violation);
}
@@ -44,7 +42,7 @@ class DependencyDiagnostics implements Diagnostics {
@Override
public void warning(InstructionLocation location, String error) {
- DiagnosticsProblem violation = new DiagnosticsProblem(DiagnosticsProblemSeverity.WARNING, location, error);
+ Problem violation = new Problem(ProblemSeverity.WARNING, location, error);
problems.add(violation);
}
@@ -53,11 +51,11 @@ class DependencyDiagnostics implements Diagnostics {
warning(null, error);
}
- public List getProblems() {
+ public List getProblems() {
return problems;
}
- public List getSevereProblems() {
+ public List getSevereProblems() {
return severeProblems;
}
}
diff --git a/teavm-core/src/main/java/org/teavm/model/Diagnostics.java b/teavm-core/src/main/java/org/teavm/diagnostics/Diagnostics.java
similarity index 76%
rename from teavm-core/src/main/java/org/teavm/model/Diagnostics.java
rename to teavm-core/src/main/java/org/teavm/diagnostics/Diagnostics.java
index f7b046100..a061bbac9 100644
--- a/teavm-core/src/main/java/org/teavm/model/Diagnostics.java
+++ b/teavm-core/src/main/java/org/teavm/diagnostics/Diagnostics.java
@@ -13,19 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.model;
+package org.teavm.diagnostics;
+import org.teavm.model.CallLocation;
/**
*
* @author Alexey Andreev
*/
public interface Diagnostics {
- void error(InstructionLocation location, String error);
+ void error(CallLocation location, String error, Object... params);
- void error(String error);
-
- void warning(InstructionLocation location, String error);
-
- void warning(String error);
+ void warning(CallLocation location, String error, Object... params);
}
diff --git a/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblem.java b/teavm-core/src/main/java/org/teavm/diagnostics/Problem.java
similarity index 66%
rename from teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblem.java
rename to teavm-core/src/main/java/org/teavm/diagnostics/Problem.java
index 233d17ab7..b7d0eeec4 100644
--- a/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblem.java
+++ b/teavm-core/src/main/java/org/teavm/diagnostics/Problem.java
@@ -13,30 +13,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.vm;
+package org.teavm.diagnostics;
-import org.teavm.model.InstructionLocation;
+import java.util.Arrays;
+import org.teavm.model.CallLocation;
/**
*
* @author Alexey Andreev
*/
-public class DiagnosticsProblem {
- private DiagnosticsProblemSeverity severity;
- private InstructionLocation location;
+public class Problem {
+ private ProblemSeverity severity;
+ private CallLocation location;
private String text;
+ private Object[] params;
- public DiagnosticsProblem(DiagnosticsProblemSeverity severity, InstructionLocation location, String text) {
+ public Problem(ProblemSeverity severity, CallLocation location, String text, Object[] params) {
this.severity = severity;
this.location = location;
this.text = text;
+ this.params = Arrays.copyOf(params, params.length);
}
- public DiagnosticsProblemSeverity getSeverity() {
+ public ProblemSeverity getSeverity() {
return severity;
}
- public InstructionLocation getLocation() {
+ public CallLocation getLocation() {
return location;
}
diff --git a/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblemSeverity.java b/teavm-core/src/main/java/org/teavm/diagnostics/ProblemSeverity.java
similarity index 91%
rename from teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblemSeverity.java
rename to teavm-core/src/main/java/org/teavm/diagnostics/ProblemSeverity.java
index 8fa47a89f..1a09fca6e 100644
--- a/teavm-core/src/main/java/org/teavm/vm/DiagnosticsProblemSeverity.java
+++ b/teavm-core/src/main/java/org/teavm/diagnostics/ProblemSeverity.java
@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.teavm.vm;
+package org.teavm.diagnostics;
/**
*
* @author Alexey Andreev
*/
-public enum DiagnosticsProblemSeverity {
+public enum ProblemSeverity {
ERROR,
WARNING
}
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 3d66705cb..3d9f3126e 100644
--- a/teavm-core/src/main/java/org/teavm/javascript/NullPointerExceptionTransformer.java
+++ b/teavm-core/src/main/java/org/teavm/javascript/NullPointerExceptionTransformer.java
@@ -15,6 +15,7 @@
*/
package org.teavm.javascript;
+import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction;
diff --git a/teavm-core/src/main/java/org/teavm/model/CallLocation.java b/teavm-core/src/main/java/org/teavm/model/CallLocation.java
new file mode 100644
index 000000000..11017cb3d
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/model/CallLocation.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+import java.util.Objects;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class CallLocation {
+ private MethodReference method;
+ private InstructionLocation sourceLocation;
+
+ public CallLocation(MethodReference method, InstructionLocation sourceLocation) {
+ this.method = method;
+ this.sourceLocation = sourceLocation;
+ }
+
+ public MethodReference getMethod() {
+ return method;
+ }
+
+ public InstructionLocation getSourceLocation() {
+ return sourceLocation;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(method, sourceLocation);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof CallLocation)) {
+ return false;
+ }
+ CallLocation other = (CallLocation)obj;
+ return Objects.equals(method, other.method) && Objects.equals(sourceLocation, other.sourceLocation);
+ }
+}
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 4ae8cdcb0..c7eeebc92 100644
--- a/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java
+++ b/teavm-core/src/main/java/org/teavm/model/ClassHolderTransformer.java
@@ -15,6 +15,8 @@
*/
package org.teavm.model;
+import org.teavm.diagnostics.Diagnostics;
+
/**
*
diff --git a/teavm-core/src/main/java/org/teavm/vm/Violations.java b/teavm-core/src/main/java/org/teavm/vm/Violations.java
index 20d2f0ca1..fe1cbe11e 100644
--- a/teavm-core/src/main/java/org/teavm/vm/Violations.java
+++ b/teavm-core/src/main/java/org/teavm/vm/Violations.java
@@ -20,6 +20,7 @@ import java.util.Set;
import org.teavm.dependency.ClassDependencyInfo;
import org.teavm.dependency.FieldDependencyInfo;
import org.teavm.dependency.MethodDependencyInfo;
+import org.teavm.diagnostics.Problem;
/**
*
@@ -32,9 +33,9 @@ public interface Violations {
Set getMissingFields();
- List getDiagnosticsProblems();
+ List getDiagnosticsProblems();
- List getSevereDiagnosticsProblems();
+ List getSevereDiagnosticsProblems();
boolean hasSevereViolations();
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 cc82e5072..2033ca5df 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,6 +15,7 @@
*/
package org.teavm.jso.plugin;
+import org.teavm.diagnostics.Diagnostics;
import org.teavm.model.*;
/**
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 456966d75..1dcf7a086 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
@@ -16,6 +16,7 @@
package org.teavm.jso.plugin;
import java.util.*;
+import org.teavm.diagnostics.Diagnostics;
import org.teavm.javascript.ni.PreserveOriginalName;
import org.teavm.jso.*;
import org.teavm.model.*;