mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
Add class handling in dependency checker
This commit is contained in:
parent
8db424809a
commit
1826e04951
@ -20,159 +20,33 @@
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-cli" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-cli" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-tooling" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-tooling" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-platform" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-platform" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-html4j" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-html4j" />
|
||||
</profile>
|
||||
<profile default="false" name="Maven default annotation processors profile" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-maven-webapp" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-jso-impl" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-jso-impl" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-maven-plugin" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-maven-plugin" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-jso-apis" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-jso-apis" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-samples-scala" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-samples-scala" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-jso" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-jso" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-core" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-core" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-samples-kotlin" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-samples-kotlin" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-classlib" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-classlib" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-samples-async" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-samples-async" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-samples-video" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-samples-video" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-samples-storage" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-samples-storage" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-samples-benchmark" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-samples-benchmark" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-samples-hello" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-samples-hello" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-extras-slf4j" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-extras-slf4j" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-chrome-rdp" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-chrome-rdp" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-tests" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-tests" />
|
||||
</profile>
|
||||
<profile default="false" name="Annotation profile for teavm-metaprogramming-api" enabled="true">
|
||||
<sourceOutputDir name="target/generated-sources/annotations" />
|
||||
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
|
||||
<outputRelativeToContentRoot value="true" />
|
||||
<processorPath useClasspath="true" />
|
||||
<module name="teavm-classlib" />
|
||||
<module name="teavm-cli" />
|
||||
<module name="teavm-core" />
|
||||
<module name="teavm-extras-slf4j" />
|
||||
<module name="teavm-html4j" />
|
||||
<module name="teavm-jso" />
|
||||
<module name="teavm-jso-apis" />
|
||||
<module name="teavm-jso-impl" />
|
||||
<module name="teavm-maven-plugin" />
|
||||
<module name="teavm-maven-webapp" />
|
||||
<module name="teavm-metaprogramming-api" />
|
||||
<module name="teavm-platform" />
|
||||
<module name="teavm-samples-async" />
|
||||
<module name="teavm-samples-benchmark" />
|
||||
<module name="teavm-samples-hello" />
|
||||
<module name="teavm-samples-kotlin" />
|
||||
<module name="teavm-samples-scala" />
|
||||
<module name="teavm-samples-storage" />
|
||||
<module name="teavm-samples-video" />
|
||||
<module name="teavm-tests" />
|
||||
<module name="teavm-tooling" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
<bytecodeTargetLevel>
|
||||
|
@ -388,6 +388,19 @@ class DependencyGraphBuilder {
|
||||
DependencyNode node = nodes[receiver.getIndex()];
|
||||
if (node != null) {
|
||||
node.propagate(dependencyChecker.getType("java.lang.Class"));
|
||||
if (!(cst instanceof ValueType.Primitive)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
while (cst instanceof ValueType.Array) {
|
||||
cst = ((ValueType.Array) cst).getItemType();
|
||||
sb.append('[');
|
||||
}
|
||||
if (cst instanceof ValueType.Object) {
|
||||
sb.append(((ValueType.Object) cst).getClassName());
|
||||
} else {
|
||||
sb.append(cst.toString());
|
||||
}
|
||||
node.getClassValueNode().propagate(dependencyChecker.getType(sb.toString()));
|
||||
}
|
||||
}
|
||||
while (cst instanceof ValueType.Array) {
|
||||
cst = ((ValueType.Array) cst).getItemType();
|
||||
@ -656,6 +669,10 @@ class DependencyGraphBuilder {
|
||||
invokeVirtual(receiver, instance, method, arguments);
|
||||
break;
|
||||
}
|
||||
if (method.getName().equals("getClass") && method.parameterCount() == 0
|
||||
&& method.getReturnType().isObject(Class.class) && receiver != null) {
|
||||
nodes[instance.getIndex()].connect(nodes[receiver.getIndex()].getClassValueNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||
private List<DependencyNodeToNodeTransition> transitions;
|
||||
private volatile String tag;
|
||||
private DependencyNode arrayItemNode;
|
||||
private DependencyNode classValueNode;
|
||||
private int degree;
|
||||
int index;
|
||||
boolean locked;
|
||||
@ -201,6 +202,18 @@ public class DependencyNode implements ValueDependencyInfo {
|
||||
return arrayItemNode;
|
||||
}
|
||||
|
||||
public DependencyNode getClassValueNode() {
|
||||
if (classValueNode == null) {
|
||||
classValueNode = new DependencyNode(dependencyChecker, dependencyChecker.nodes.size(), degree);
|
||||
dependencyChecker.nodes.add(classValueNode);
|
||||
if (DependencyChecker.shouldLog) {
|
||||
classValueNode.tag = tag + "@";
|
||||
}
|
||||
classValueNode.addConsumer(this::propagate);
|
||||
}
|
||||
return classValueNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasArrayType() {
|
||||
return arrayItemNode != null && (arrayItemNode.types != null || arrayItemNode.smallTypes != null);
|
||||
|
@ -40,6 +40,9 @@ class DependencyNodeToNodeTransition implements DependencyConsumer {
|
||||
source.getArrayItem().connect(destination.getArrayItem());
|
||||
destination.getArrayItem().connect(source.getArrayItem());
|
||||
}
|
||||
if (type.getName().equals("java.lang.Class")) {
|
||||
source.getClassValueNode().connect(destination.getClassValueNode());
|
||||
}
|
||||
if (!destination.hasType(type)) {
|
||||
destination.propagate(type);
|
||||
}
|
||||
|
@ -30,9 +30,9 @@ public interface MethodDependencyInfo {
|
||||
|
||||
int getParameterCount();
|
||||
|
||||
DependencyNode getResult();
|
||||
ValueDependencyInfo getResult();
|
||||
|
||||
DependencyNode getThrown();
|
||||
ValueDependencyInfo getThrown();
|
||||
|
||||
MethodReference getReference();
|
||||
|
||||
|
@ -26,5 +26,7 @@ public interface ValueDependencyInfo {
|
||||
|
||||
boolean hasArrayType();
|
||||
|
||||
DependencyNode getArrayItem();
|
||||
ValueDependencyInfo getArrayItem();
|
||||
|
||||
ValueDependencyInfo getClassValueNode();
|
||||
}
|
||||
|
@ -60,6 +60,12 @@
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-tooling</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
140
tests/src/test/java/org/teavm/dependency/ClassValueTest.java
Normal file
140
tests/src/test/java/org/teavm/dependency/ClassValueTest.java
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2016 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 static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import org.junit.Test;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.tooling.TeaVMProblemRenderer;
|
||||
import org.teavm.tooling.TeaVMToolLog;
|
||||
import org.teavm.vm.TeaVM;
|
||||
import org.teavm.vm.TeaVMBuilder;
|
||||
|
||||
public class ClassValueTest {
|
||||
@Test
|
||||
public void simple() {
|
||||
ValueDependencyInfo info = runTestWithConsume("simpleSnippet").getClassValueNode();
|
||||
assertTrue("Long must be consumed", info.hasType("java.lang.Long"));
|
||||
assertTrue("String must be consumed", info.hasType("java.lang.String"));
|
||||
assertTrue("Nothing except Long and String expected", info.getTypes().length == 2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static void simpleSnippet() {
|
||||
consume(Long.class);
|
||||
consume(String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromGetClass() {
|
||||
ValueDependencyInfo info = runTestWithConsume("fromGetClassSnippet").getClassValueNode();
|
||||
assertTrue("Long must be consumed", info.hasType("java.lang.Long"));
|
||||
assertTrue("String must be consumed", info.hasType("java.lang.String"));
|
||||
assertTrue("Nothing except Long and String expected", info.getTypes().length == 2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static void fromGetClassSnippet() {
|
||||
consumeClass(23L);
|
||||
consumeClass("foo");
|
||||
}
|
||||
|
||||
private static void consumeClass(Object value) {
|
||||
consume(value.getClass());
|
||||
}
|
||||
|
||||
protected static void consume(@SuppressWarnings("unused") Object value) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
private ValueDependencyInfo runTestWithConsume(String methodName) {
|
||||
DependencyInfo info = runTest(methodName);
|
||||
MethodDependencyInfo methodInfo = info.getMethod(new MethodReference(ClassValueTest.class, "consume",
|
||||
Object.class, void.class));
|
||||
if (methodInfo == null) {
|
||||
fail("consume method never reached");
|
||||
}
|
||||
return methodInfo.getVariable(1);
|
||||
}
|
||||
|
||||
private DependencyInfo runTest(String methodName) {
|
||||
TeaVM vm = new TeaVMBuilder().build();
|
||||
vm.installPlugins();
|
||||
vm.entryPoint(new MethodReference(getClass().getName(), methodName, ValueType.VOID));
|
||||
vm.build(new StringBuilder(), null);
|
||||
if (!vm.getProblemProvider().getSevereProblems().isEmpty()) {
|
||||
fail("Code compiled with errors:\n" + describeProblems(vm));
|
||||
}
|
||||
return vm.getDependencyInfo();
|
||||
}
|
||||
|
||||
private String describeProblems(TeaVM vm) {
|
||||
Log log = new Log();
|
||||
TeaVMProblemRenderer.describeProblems(vm, log);
|
||||
return log.sb.toString();
|
||||
}
|
||||
|
||||
|
||||
static class Log implements TeaVMToolLog {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void info(String text) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String text) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String text) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String text, Throwable e) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String text, Throwable e) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(String text, Throwable e) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String text, Throwable e) {
|
||||
appendLine(text);
|
||||
}
|
||||
|
||||
private void appendLine(String text) {
|
||||
sb.append(text).append('\n');
|
||||
}
|
||||
}
|
||||
}
|
@ -26,5 +26,6 @@
|
||||
<orderEntry type="module" module-name="teavm-jso-apis" production-on-test="" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.11" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
|
||||
<orderEntry type="module" module-name="teavm-tooling" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
Loading…
Reference in New Issue
Block a user