diff --git a/.travis.yml b/.travis.yml
index 99a559dad..9c70b38bd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,6 +4,10 @@ jdk:
cache:
directories:
- $HOME/.m2
+branches:
+ only:
+ - master
+ - /^release-.+$/
script: >
mvn test \
-Dteavm.test.skip=false \
diff --git a/core/src/main/java/org/teavm/vm/TeaVM.java b/core/src/main/java/org/teavm/vm/TeaVM.java
index 1892901eb..a4c57f160 100644
--- a/core/src/main/java/org/teavm/vm/TeaVM.java
+++ b/core/src/main/java/org/teavm/vm/TeaVM.java
@@ -766,7 +766,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
* obtains all implementation classes that are enumerated there.
*/
public void installPlugins() {
- for (TeaVMPlugin plugin : ServiceLoader.load(TeaVMPlugin.class, classLoader)) {
+ for (TeaVMPlugin plugin : TeaVMPluginLoader.load(classLoader)) {
plugin.install(this);
}
}
diff --git a/core/src/main/java/org/teavm/vm/TeaVMPluginLoader.java b/core/src/main/java/org/teavm/vm/TeaVMPluginLoader.java
index 1994c26cf..b4db270ed 100644
--- a/core/src/main/java/org/teavm/vm/TeaVMPluginLoader.java
+++ b/core/src/main/java/org/teavm/vm/TeaVMPluginLoader.java
@@ -73,7 +73,7 @@ public final class TeaVMPluginLoader {
.collect(Collectors.toList());
}
- public static List orderPlugins(ClassLoader classLoader, Set classNames) {
+ static List orderPlugins(ClassLoader classLoader, Set classNames) {
Map descriptors = new HashMap<>();
try {
for (String className : classNames) {
@@ -160,11 +160,11 @@ public final class TeaVMPluginLoader {
throw new IllegalStateException("Plugin " + descriptor.name
+ " has both before and after annotations");
}
- descriptor.beforeList.addAll(Arrays.asList(descriptor.before));
- for (String after : descriptor.after) {
- PluginDescriptor afterDescriptor = descriptors.get(after);
- if (afterDescriptor != null && afterDescriptor.reachable) {
- afterDescriptor.beforeList.add(descriptor.name);
+ descriptor.afterList.addAll(Arrays.asList(descriptor.after));
+ for (String before : descriptor.before) {
+ PluginDescriptor beforeDescriptor = descriptors.get(before);
+ if (beforeDescriptor != null && beforeDescriptor.reachable) {
+ beforeDescriptor.afterList.add(descriptor.name);
}
}
}
@@ -180,14 +180,15 @@ public final class TeaVMPluginLoader {
}
path.add(descriptor.name);
- for (String before : descriptor.beforeList) {
- PluginDescriptor beforeDescriptor = descriptors.get(before);
- if (beforeDescriptor != null) {
- if (visited.contains(before) && !emmited.contains(before)) {
+ for (String after : descriptor.afterList) {
+ PluginDescriptor afterDescriptor = descriptors.get(after);
+ if (afterDescriptor != null && afterDescriptor.reachable) {
+ if (visited.contains(after) && !emmited.contains(after)) {
List loop = new ArrayList<>();
+ Collections.reverse(path);
for (String pathElem : path) {
loop.add(pathElem);
- if (pathElem.equals(descriptor.name)) {
+ if (pathElem.equals(afterDescriptor.name)) {
break;
}
}
@@ -195,7 +196,7 @@ public final class TeaVMPluginLoader {
throw new IllegalStateException("Circular dependency found: " + loop.stream()
.collect(Collectors.joining(" -> ")));
}
- orderDescriptors(beforeDescriptor, descriptors, list, visited, emmited, path);
+ orderDescriptors(afterDescriptor, descriptors, list, visited, emmited, path);
}
}
@@ -260,7 +261,7 @@ public final class TeaVMPluginLoader {
String[] requires = new String[0];
String[] before = new String[0];
String[] after = new String[0];
- List beforeList = new ArrayList<>();
+ List afterList = new ArrayList<>();
boolean reachable;
}
}
diff --git a/core/src/test/java/org/teavm/vm/PluginLoaderTest.java b/core/src/test/java/org/teavm/vm/PluginLoaderTest.java
index aea0b4fc6..99301ba02 100644
--- a/core/src/test/java/org/teavm/vm/PluginLoaderTest.java
+++ b/core/src/test/java/org/teavm/vm/PluginLoaderTest.java
@@ -15,12 +15,13 @@
*/
package org.teavm.vm;
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
+import org.teavm.vm.spi.After;
import org.teavm.vm.spi.Before;
import org.teavm.vm.spi.Requires;
import org.teavm.vm.spi.TeaVMHost;
@@ -37,6 +38,25 @@ public class PluginLoaderTest {
assertThat(plugins.size(), is(2));
assertThat(plugins.get(0), is(B.class.getName()));
assertThat(plugins.get(1), is(A.class.getName()));
+
+ plugins = order(C.class, D.class);
+ assertThat(plugins.size(), is(2));
+ assertThat(plugins.get(0), is(C.class.getName()));
+ assertThat(plugins.get(1), is(D.class.getName()));
+ }
+
+ @Test
+ public void respectsPluginDependency() {
+ List plugins = order(B.class);
+ assertThat(plugins.size(), is(0));
+
+ plugins = order(A.class);
+ assertThat(plugins.size(), is(1));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void detectsCircularDependency() {
+ order(Pre.class, Head.class, Tail.class);
}
private List order(Class>... classes) {
@@ -57,4 +77,39 @@ public class PluginLoaderTest {
public void install(TeaVMHost host) {
}
}
+
+ static class C implements TeaVMPlugin {
+ @Override
+ public void install(TeaVMHost host) {
+ }
+ }
+
+ @After(C.class)
+ @Requires(C.class)
+ static class D implements TeaVMPlugin {
+ @Override
+ public void install(TeaVMHost host) {
+ }
+ }
+
+ @Before(Head.class)
+ static class Pre implements TeaVMPlugin {
+ @Override
+ public void install(TeaVMHost host) {
+ }
+ }
+
+ @Before(Tail.class)
+ static class Head implements TeaVMPlugin {
+ @Override
+ public void install(TeaVMHost host) {
+ }
+ }
+
+ @Before(Head.class)
+ static class Tail implements TeaVMPlugin {
+ @Override
+ public void install(TeaVMHost host) {
+ }
+ }
}
diff --git a/pom.xml b/pom.xml
index 21282c232..bf1e6e088 100644
--- a/pom.xml
+++ b/pom.xml
@@ -243,7 +243,7 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 2.15
+ 2.16
validate