From 9cdc099b1a5822d989b47bf6d702d7bb306a3d10 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Sun, 23 Feb 2014 21:14:10 +0400 Subject: [PATCH] Adds simple support of Class.forName and class.newInstance --- .../org/teavm/classlib/impl/JCLPlugin.java | 1 + .../impl/NewInstanceDependencySupport.java | 55 +++++++++++++++++++ .../java/lang/ClassNativeGenerator.java | 46 +++++++++++++++- .../org/teavm/classlib/java/lang/TClass.java | 25 +++++++++ .../classlib/java/lang/TClassLoader.java | 41 ++++++++++++++ .../java/lang/TClassNotFoundException.java | 36 ++++++++++++ .../java/lang/TIllegalAccessException.java | 32 +++++++++++ .../java/lang/TInstantiationException.java | 32 +++++++++++ .../lang/TReflectiveOperationException.java | 40 ++++++++++++++ .../java/lang/TSystemClassLoader.java | 25 +++++++++ .../util/logging/LoggerNativeGenerator.java | 4 +- .../teavm/classlib/java/lang/ClassTest.java | 8 +++ .../teavm/classlib/java/lang/TestObject.java | 36 ++++++++++++ .../java/org/teavm/javascript/Renderer.java | 6 +- .../teavm/javascript/ni/GeneratorContext.java | 4 +- .../model/ListableClassHolderSource.java | 5 +- .../model/ListableClassReaderSource.java | 26 +++++++++ 17 files changed, 410 insertions(+), 12 deletions(-) create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassNotFoundException.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TIllegalAccessException.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TInstantiationException.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TReflectiveOperationException.java create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystemClassLoader.java create mode 100644 teavm-classlib/src/test/java/org/teavm/classlib/java/lang/TestObject.java create mode 100644 teavm-core/src/main/java/org/teavm/model/ListableClassReaderSource.java diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java index abe39dc91..12ef7fd3d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java @@ -27,5 +27,6 @@ public class JCLPlugin implements JavascriptBuilderPlugin { public void install(JavascriptBuilderHost host) { host.add(new EnumDependencySupport()); host.add(new EnumTransformer()); + host.add(new NewInstanceDependencySupport()); } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java new file mode 100644 index 000000000..da4b47e2f --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java @@ -0,0 +1,55 @@ +/* + * 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.classlib.impl; + +import org.teavm.dependency.*; +import org.teavm.model.*; + +/** + * + * @author Alexey Andreev + */ +public class NewInstanceDependencySupport implements DependencyListener { + private DependencyNode allClassesNode; + + @Override + public void started(DependencyChecker dependencyChecker) { + allClassesNode = dependencyChecker.createNode(); + } + + @Override + public void classAchieved(DependencyChecker dependencyChecker, String className) { + ClassReader cls = dependencyChecker.getClassSource().get(className); + if (cls.hasModifier(ElementModifier.ABSTRACT) || cls.hasModifier(ElementModifier.INTERFACE)) { + return; + } + if (cls.getMethod(new MethodDescriptor("", ValueType.VOID)) != null) { + allClassesNode.propagate(className); + } + } + + @Override + public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) { + MethodReader reader = method.getMethod(); + if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) { + allClassesNode.connect(method.getResult()); + } + } + + @Override + public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) { + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java index 7d1effdcf..ea2ab1e5d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java @@ -24,7 +24,7 @@ import org.teavm.javascript.ni.Generator; import org.teavm.javascript.ni.GeneratorContext; import org.teavm.javascript.ni.Injector; import org.teavm.javascript.ni.InjectorContext; -import org.teavm.model.MethodReference; +import org.teavm.model.*; /** * @@ -41,6 +41,12 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug case "getSuperclass": generateGetSuperclass(context, writer); break; + case "forNameImpl": + generateForName(context, writer); + break; + case "newInstance": + generateNewInstance(context, writer); + break; } } @@ -102,6 +108,43 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug writer.append(".$data)"); } + private void generateForName(GeneratorContext context, SourceWriter writer) throws IOException { + String param = context.getParameterName(1); + writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent(); + for (String name : context.getClassSource().getClassNames()) { + writer.append("case \"" + name + "\": ").appendClass(name).append(".$clinit(); ") + .append("return $rt_cls(").appendClass(name).append(");").softNewLine(); + } + writer.append("default: return null;").softNewLine(); + writer.outdent().append("}").softNewLine(); + } + + private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException { + String self = context.getParameterName(0); + writer.append("if (!").appendClass("java.lang.Class").append(".$$constructors$$) {").indent().softNewLine(); + writer.appendClass("java.lang.Class").append(".$$constructors$$ = true;").softNewLine(); + for (String clsName : context.getClassSource().getClassNames()) { + ClassReader cls = context.getClassSource().get(clsName); + MethodReader method = cls.getMethod(new MethodDescriptor("", ValueType.VOID)); + if (method != null) { + writer.appendClass(clsName).append(".$$constructor$$ = ").appendMethodBody(method.getReference()) + .append(";").softNewLine(); + } + } + writer.outdent().append("}").softNewLine(); + writer.append("var cls = " + self + ".$data;").softNewLine(); + writer.append("var ctor = cls.$$constructor$$;").softNewLine(); + writer.append("if (ctor === null) {").indent().softNewLine(); + writer.append("var ex = new ").appendClass(InstantiationException.class.getName()).append("();"); + writer.appendMethodBody(new MethodReference(InstantiationException.class.getName(), new MethodDescriptor( + "", ValueType.VOID))).append("(ex);").softNewLine(); + writer.append("$rt_throw(ex);").softNewLine(); + writer.outdent().append("}").softNewLine(); + writer.append("var instance = new cls();").softNewLine(); + writer.append("ctor(instance)"); + writer.append("return instance"); + } + @Override public void methodAchieved(DependencyChecker checker, MethodDependency graph) { switch (graph.getReference().getName()) { @@ -110,6 +153,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug case "wrap": case "getSuperclass": case "getComponentType0": + case "forNameImpl": graph.getResult().propagate("java.lang.Class"); break; } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java index 99d786fb0..2bc393085 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java @@ -109,4 +109,29 @@ public class TClass extends TObject { } return (T)obj; } + + public TClassLoader getClassLoader() { + return TClassLoader.getSystemClassLoader(); + } + + @GeneratedBy(ClassNativeGenerator.class) + @PluggableDependency(ClassNativeGenerator.class) + private static native TClass forNameImpl(TString name); + + public static TClass forName(TString name) throws TClassNotFoundException { + TClass result = forNameImpl(name); + if (result == null) { + throw new TClassNotFoundException(); + } + return result; + } + + @SuppressWarnings("unused") + public static TClass forName(TString name, boolean initialize, TClassLoader loader) + throws TClassNotFoundException { + return forName(name); + } + + @GeneratedBy(ClassNativeGenerator.class) + public native T newInstance() throws TInstantiationException, TIllegalAccessException; } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.java new file mode 100644 index 000000000..47e0ed4a8 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassLoader.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.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +public abstract class TClassLoader extends TObject { + private TClassLoader parent; + private static TSystemClassLoader systemClassLoader = new TSystemClassLoader(); + + protected TClassLoader() { + this(null); + } + + protected TClassLoader(TClassLoader parent) { + this.parent = parent; + } + + public TClassLoader getParent() { + return parent; + } + + public static TClassLoader getSystemClassLoader() { + return systemClassLoader; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassNotFoundException.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassNotFoundException.java new file mode 100644 index 000000000..9fc95b1d2 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassNotFoundException.java @@ -0,0 +1,36 @@ +/* + * 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.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +public class TClassNotFoundException extends TReflectiveOperationException { + private static final long serialVersionUID = -1162632869775788325L; + + public TClassNotFoundException() { + super(); + } + + public TClassNotFoundException(TString message, TThrowable cause) { + super(message, cause); + } + + public TClassNotFoundException(TString message) { + super(message); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TIllegalAccessException.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TIllegalAccessException.java new file mode 100644 index 000000000..b8d614d3a --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TIllegalAccessException.java @@ -0,0 +1,32 @@ +/* + * 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.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +public class TIllegalAccessException extends ReflectiveOperationException { + private static final long serialVersionUID = 8240407889170934565L; + + public TIllegalAccessException() { + super(); + } + + public TIllegalAccessException(String message) { + super(message); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TInstantiationException.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TInstantiationException.java new file mode 100644 index 000000000..3c2568808 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TInstantiationException.java @@ -0,0 +1,32 @@ +/* + * 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.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +public class TInstantiationException extends ReflectiveOperationException { + private static final long serialVersionUID = 8771605296206833516L; + + public TInstantiationException() { + super(); + } + + public TInstantiationException(String message) { + super(message); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TReflectiveOperationException.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TReflectiveOperationException.java new file mode 100644 index 000000000..25bff344e --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TReflectiveOperationException.java @@ -0,0 +1,40 @@ +/* + * 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.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +public class TReflectiveOperationException extends TException { + private static final long serialVersionUID = -455785869284249992L; + + public TReflectiveOperationException() { + super(); + } + + public TReflectiveOperationException(TString message, TThrowable cause) { + super(message, cause); + } + + public TReflectiveOperationException(TString message) { + super(message); + } + + public TReflectiveOperationException(TThrowable cause) { + super(cause); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystemClassLoader.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystemClassLoader.java new file mode 100644 index 000000000..da6e8ffea --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystemClassLoader.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.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +class TSystemClassLoader extends TClassLoader { + TSystemClassLoader() { + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java index 177cc9b24..0259c4893 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java @@ -29,8 +29,8 @@ public class LoggerNativeGenerator implements Generator { @Override public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { writer.append("if (console) {").indent().softNewLine(); - writer.append("console.").append(methodRef.getName()).append("(").append(context.getParameterName(1)) - .append(");").softNewLine(); + writer.append("console.").append(methodRef.getName()).append("($rt_ustr(").append(context.getParameterName(1)) + .append("));").softNewLine(); writer.outdent().append("}").softNewLine(); } } diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ClassTest.java b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ClassTest.java index 74572342c..f92a53aa7 100644 --- a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ClassTest.java +++ b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ClassTest.java @@ -89,4 +89,12 @@ public class ClassTest { Object obj = 23; Float.class.cast(obj); } + + @Test + public void instanceCreatedThroughReflection() throws Exception { + Runnable instance = (Runnable)Class.forName(TestObject.class.getName()).newInstance(); + instance.run(); + assertEquals(TestObject.class, instance.getClass()); + assertEquals(1, ((TestObject)instance).getCounter()); + } } diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/TestObject.java b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/TestObject.java new file mode 100644 index 000000000..b36842db1 --- /dev/null +++ b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/TestObject.java @@ -0,0 +1,36 @@ +/* + * 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.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +public class TestObject extends Object implements Runnable { + private int counter; + + public TestObject() { + } + + @Override + public void run() { + ++counter; + } + + public int getCounter() { + return counter; + } +} diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index 552b7f7e6..176309e86 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -37,7 +37,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { private static final String variableNames = "abcdefghijkmnopqrstuvwxyz"; private NamingStrategy naming; private SourceWriter writer; - private ClassHolderSource classSource; + private ListableClassHolderSource classSource; private ClassLoader classLoader; private boolean minifying; private Map injectorMap = new HashMap<>(); @@ -50,7 +50,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { } } - public Renderer(SourceWriter writer, ClassHolderSource classSource, ClassLoader classLoader) { + public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader) { this.naming = writer.getNaming(); this.writer = writer; this.classSource = classSource; @@ -442,7 +442,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { } @Override - public ClassReaderSource getClassSource() { + public ListableClassReaderSource getClassSource() { return classSource; } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratorContext.java b/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratorContext.java index fd856f0b5..9082b8819 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratorContext.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratorContext.java @@ -15,7 +15,7 @@ */ package org.teavm.javascript.ni; -import org.teavm.model.ClassReaderSource; +import org.teavm.model.ListableClassReaderSource; /** * @@ -24,5 +24,5 @@ import org.teavm.model.ClassReaderSource; public interface GeneratorContext { String getParameterName(int index); - ClassReaderSource getClassSource(); + ListableClassReaderSource getClassSource(); } diff --git a/teavm-core/src/main/java/org/teavm/model/ListableClassHolderSource.java b/teavm-core/src/main/java/org/teavm/model/ListableClassHolderSource.java index 5212d5018..173795616 100644 --- a/teavm-core/src/main/java/org/teavm/model/ListableClassHolderSource.java +++ b/teavm-core/src/main/java/org/teavm/model/ListableClassHolderSource.java @@ -15,12 +15,9 @@ */ package org.teavm.model; -import java.util.Set; - /** * * @author Alexey Andreev */ -public interface ListableClassHolderSource extends ClassHolderSource { - Set getClassNames(); +public interface ListableClassHolderSource extends ClassHolderSource, ListableClassReaderSource { } diff --git a/teavm-core/src/main/java/org/teavm/model/ListableClassReaderSource.java b/teavm-core/src/main/java/org/teavm/model/ListableClassReaderSource.java new file mode 100644 index 000000000..980f67b4e --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/ListableClassReaderSource.java @@ -0,0 +1,26 @@ +/* + * 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.Set; + +/** + * + * @author Alexey Andreev + */ +public interface ListableClassReaderSource extends ClassReaderSource { + Set getClassNames(); +}