Converter from Java: better conversion from java-specific to Kotlin classes

#KT-5173 Fixed
This commit is contained in:
Valentin Kipyatkov
2014-06-11 18:42:40 +04:00
parent c36624a58e
commit da5fe7adb0
16 changed files with 238 additions and 94 deletions
+19 -2
View File
@@ -78,8 +78,25 @@ public class Converter private(val project: Project, val settings: ConverterSett
}
public fun convertFile(javaFile: PsiJavaFile): File {
val fileMembers = FileMemberList(javaFile.getChildren().map { convertTopElement(it) }.filterNotNull())
return File(fileMembers, createMainFunction(javaFile))
var convertedChildren = javaFile.getChildren().map {
if (it is PsiImportList) {
val importList = convertImportList(it)
typeConverter.importList = importList
importList
}
else {
convertTopElement(it)
}
}.filterNotNull()
typeConverter.importList = null
if (typeConverter.importsToAdd.isNotEmpty()) {
val importList = convertedChildren.filterIsInstance(javaClass<ImportList>()).first()
val newImportList = ImportList(importList.imports + typeConverter.importsToAdd)
convertedChildren = convertedChildren.map { if (it == importList) newImportList else it }
}
return File(FileMemberList(convertedChildren), createMainFunction(javaFile))
}
public fun convertAnonymousClassBody(anonymousClass: PsiAnonymousClass): AnonymousClassBody {
+17 -1
View File
@@ -21,14 +21,30 @@ import org.jetbrains.jet.j2k.ast.Nullability
import com.intellij.psi.*
import org.jetbrains.jet.j2k.visitors.TypeVisitor
import java.util.HashMap
import java.util.HashSet
import org.jetbrains.jet.j2k.ast.Import
import org.jetbrains.jet.j2k.ast.ImportList
class TypeConverter(val settings: ConverterSettings, val conversionScope: ConversionScope) {
private val nullabilityCache = HashMap<PsiElement, Nullability>()
private val classesToImport = HashSet<String>()
public var importList: ImportList? = null
set(value) {
$importList = value
importNames = importList?.imports?.mapTo(HashSet<String>()) { it.name } ?: setOf()
}
public var importNames: Set<String> = setOf()
private set
public val importsToAdd: Collection<Import>
get() = classesToImport.map { Import(it) }
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
if (`type` == null) return Type.Empty
val result = `type`.accept<Type>(TypeVisitor(this))!!
val result = `type`.accept<Type>(TypeVisitor(this, classesToImport))!!
return when (nullability) {
Nullability.NotNull -> result.toNotNullType()
Nullability.Nullable -> result.toNullableType()
+1 -1
View File
@@ -28,7 +28,7 @@ class Import(val name: String) : Element {
override fun toKotlin() = "import " + name
}
class ImportList(private val imports: List<Import>) : Element {
class ImportList(public val imports: List<Import>) : Element {
override val isEmpty: Boolean
get() = imports.isEmpty()
@@ -27,7 +27,7 @@ import org.jetbrains.jet.j2k.TypeConverter
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor<Type>() {
class TypeVisitor(private val converter: TypeConverter, private val classesToImport: MutableSet<String>) : PsiTypeVisitor<Type>() {
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
val name = primitiveType.getCanonicalText()
return if (name == "void") {
@@ -68,40 +68,74 @@ class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor<Type>()
}
}
private val toKotlinTypesMap = mapOf(
CommonClassNames.JAVA_LANG_OBJECT to "kotlin.Any",
CommonClassNames.JAVA_LANG_BYTE to "kotlin.Byte",
CommonClassNames.JAVA_LANG_CHARACTER to "kotlin.Char",
CommonClassNames.JAVA_LANG_DOUBLE to "kotlin.Double",
CommonClassNames.JAVA_LANG_FLOAT to "kotlin.Float",
CommonClassNames.JAVA_LANG_INTEGER to "kotlin.Int",
CommonClassNames.JAVA_LANG_LONG to "kotlin.Long",
CommonClassNames.JAVA_LANG_SHORT to "kotlin.Short",
CommonClassNames.JAVA_LANG_BOOLEAN to "kotlin.Boolean",
CommonClassNames.JAVA_LANG_ITERABLE to "kotlin.Iterable",
CommonClassNames.JAVA_UTIL_ITERATOR to "kotlin.Iterator",
CommonClassNames.JAVA_UTIL_LIST to "kotlin.List",
CommonClassNames.JAVA_UTIL_COLLECTION to "kotlin.Collection",
CommonClassNames.JAVA_UTIL_SET to "kotlin.Set",
CommonClassNames.JAVA_UTIL_MAP to "kotlin.Map"
)
private fun constructClassTypeIdentifier(classType: PsiClassType): Identifier {
val psiClass = classType.resolve()
if (psiClass != null) {
val qualifiedName = psiClass.getQualifiedName()
when(qualifiedName) {
CommonClassNames.JAVA_LANG_ITERABLE -> return Identifier(CommonClassNames.JAVA_LANG_ITERABLE)
CommonClassNames.JAVA_UTIL_ITERATOR -> return Identifier(CommonClassNames.JAVA_UTIL_ITERATOR)
CommonClassNames.JAVA_UTIL_LIST -> return Identifier("MutableList")
val javaClassName = psiClass.getQualifiedName()
val kotlinClassName = toKotlinTypesMap[javaClassName]
if (kotlinClassName != null) {
val kotlinShortName = getShortName(kotlinClassName)
if (kotlinShortName == getShortName(javaClassName!!) && converter.importNames.contains(getPackageName(javaClassName) + ".*")) {
classesToImport.add(kotlinClassName)
}
return Identifier(kotlinShortName)
}
}
val classTypeName = createQualifiedName(classType)
if (classTypeName.isEmpty()) {
return Identifier(getClassTypeName(classType))
if (classType is PsiClassReferenceType) {
val reference = classType.getReference()
if (reference.isQualified()) {
var result = Identifier(reference.getReferenceName()!!).toKotlin()
var qualifier = reference.getQualifier()
while (qualifier != null) {
val codeRefElement = qualifier as PsiJavaCodeReferenceElement
result = Identifier(codeRefElement.getReferenceName()!!).toKotlin() + "." + result
qualifier = codeRefElement.getQualifier()
}
return Identifier(result)
}
}
return Identifier(classTypeName)
return Identifier(classType.getClassName() ?: "")
}
private fun getPackageName(className: String): String = className.substring(0, className.lastIndexOf('.'))
private fun getShortName(className: String): String = className.substring(className.lastIndexOf('.') + 1)
private fun createRawTypesForResolvedReference(classType: PsiClassType): List<Type> {
val typeParams = LinkedList<Type>()
if (classType is PsiClassReferenceType) {
val reference = classType.getReference()
val resolve = reference.resolve()
val resolve = classType.getReference().resolve()
if (resolve is PsiClass) {
for (typeParam in resolve.getTypeParameters()) {
val superTypes = typeParam.getSuperTypes()
val boundType = if (superTypes.size > 0)
ClassType(Identifier(getClassTypeName(superTypes[0])),
val boundType = if (superTypes.size > 0) {
ClassType(constructClassTypeIdentifier(superTypes[0]),
converter.convertTypes(superTypes[0].getParameters()),
Nullability.Default,
converter.settings)
else
}
else {
StarProjectionType()
}
typeParams.add(boundType)
}
}
@@ -121,39 +155,4 @@ class TypeVisitor(private val converter: TypeConverter) : PsiTypeVisitor<Type>()
override fun visitEllipsisType(ellipsisType: PsiEllipsisType): Type {
return VarArgType(converter.convertType(ellipsisType.getComponentType()))
}
private fun createQualifiedName(classType: PsiClassType): String {
if (classType is PsiClassReferenceType) {
val reference = classType.getReference()
if (reference.isQualified()) {
var result = Identifier(reference.getReferenceName()!!).toKotlin()
var qualifier = reference.getQualifier()
while (qualifier != null) {
val codeRefElement = qualifier as PsiJavaCodeReferenceElement
result = Identifier(codeRefElement.getReferenceName()!!).toKotlin() + "." + result
qualifier = codeRefElement.getQualifier()
}
return result
}
}
return ""
}
private fun getClassTypeName(classType: PsiClassType): String {
var canonicalTypeStr: String? = classType.getCanonicalText()
return when(canonicalTypeStr) {
CommonClassNames.JAVA_LANG_OBJECT -> "Any"
CommonClassNames.JAVA_LANG_BYTE -> "Byte"
CommonClassNames.JAVA_LANG_CHARACTER -> "Char"
CommonClassNames.JAVA_LANG_DOUBLE -> "Double"
CommonClassNames.JAVA_LANG_FLOAT -> "Float"
CommonClassNames.JAVA_LANG_INTEGER -> "Int"
CommonClassNames.JAVA_LANG_LONG -> "Long"
CommonClassNames.JAVA_LANG_SHORT -> "Short"
CommonClassNames.JAVA_LANG_BOOLEAN -> "Boolean"
else -> classType.getClassName() ?: classType.getCanonicalText()
}
}
}
@@ -31,7 +31,7 @@ import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("j2k/tests/testData/ast")
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.KotlinExclusion.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.StaticMembers.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TryWithResource.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.StaticMembers.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.ToKotlinClasses.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TryWithResource.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConverterTest {
public void testAllFilesPresentInAst() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast"), Pattern.compile("^(.+)\\.java$"), true);
@@ -1691,19 +1691,6 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
}
@TestMetadata("j2k/tests/testData/ast/kotlinExclusion")
public static class KotlinExclusion extends AbstractJavaToKotlinConverterTest {
public void testAllFilesPresentInKotlinExclusion() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/kotlinExclusion"), Pattern.compile("^(.+)\\.java$"), true);
}
@TestMetadata("kt-656.java")
public void testKt_656() throws Exception {
doTest("j2k/tests/testData/ast/kotlinExclusion/kt-656.java");
}
}
@TestMetadata("j2k/tests/testData/ast/labelStatement")
public static class LabelStatement extends AbstractJavaToKotlinConverterTest {
public void testAllFilesPresentInLabelStatement() throws Exception {
@@ -2434,6 +2421,34 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
}
@TestMetadata("j2k/tests/testData/ast/toKotlinClasses")
public static class ToKotlinClasses extends AbstractJavaToKotlinConverterTest {
public void testAllFilesPresentInToKotlinClasses() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/toKotlinClasses"), Pattern.compile("^(.+)\\.java$"), true);
}
@TestMetadata("iterableAndIterator.java")
public void testIterableAndIterator() throws Exception {
doTest("j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator.java");
}
@TestMetadata("iterableAndIterator2.java")
public void testIterableAndIterator2() throws Exception {
doTest("j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator2.java");
}
@TestMetadata("iterableAndIterator3.java")
public void testIterableAndIterator3() throws Exception {
doTest("j2k/tests/testData/ast/toKotlinClasses/iterableAndIterator3.java");
}
@TestMetadata("TypeParameterBound.java")
public void testTypeParameterBound() throws Exception {
doTest("j2k/tests/testData/ast/toKotlinClasses/TypeParameterBound.java");
}
}
@TestMetadata("j2k/tests/testData/ast/trait")
public static class Trait extends AbstractJavaToKotlinConverterTest {
@TestMetadata("abstactInterface.java")
@@ -2781,7 +2796,6 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
suite.addTestSuite(IsOperator.class);
suite.addTestSuite(Issues.class);
suite.addTestSuite(KotlinApiAccess.class);
suite.addTestSuite(KotlinExclusion.class);
suite.addTestSuite(LabelStatement.class);
suite.addTestSuite(List.class);
suite.addTestSuite(LiteralExpression.class);
@@ -2807,6 +2821,7 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
suite.addTestSuite(SynchronizedStatement.class);
suite.addTestSuite(ThisExpression.class);
suite.addTestSuite(ThrowStatement.class);
suite.addTestSuite(ToKotlinClasses.class);
suite.addTestSuite(Trait.class);
suite.addTestSuite(TryStatement.class);
suite.addTestSuite(TryWithResource.class);
@@ -1 +1 @@
val a = array<java.lang.Double>(1.0, 2.0, 3.0)
val a = array<Double>(1.0, 2.0, 3.0)
@@ -1 +1 @@
val a = array<java.lang.Float>(1.0, 2.0, 3.0)
val a = array<Float>(1.0, 2.0, 3.0)
@@ -1,23 +0,0 @@
package demo
class Test() : java.lang.Iterable<String> {
override fun iterator(): java.util.Iterator<String>? {
return null
}
public fun push(i: java.util.Iterator<String>): java.util.Iterator<String> {
val j = i
return j
}
}
class FullTest() : java.lang.Iterable<String> {
override fun iterator(): java.util.Iterator<String>? {
return null
}
public fun push(i: java.util.Iterator<String>): java.util.Iterator<String> {
val j = i
return j
}
}
@@ -0,0 +1,8 @@
//file
import java.util.*;
interface I<T extends List<Iterator<String>>> {
}
class C implements I<ArrayList<Iterator<String>>> {
}
@@ -0,0 +1,7 @@
import java.util.*
import kotlin.List
import kotlin.Iterator
trait I<T : List<Iterator<String>>>
class C() : I<ArrayList<Iterator<String>>>
@@ -0,0 +1,23 @@
package demo
class Test() : Iterable<String> {
override fun iterator(): Iterator<String>? {
return null
}
public fun push(i: Iterator<String>): Iterator<String> {
val j = i
return j
}
}
class FullTest() : Iterable<String> {
override fun iterator(): Iterator<String>? {
return null
}
public fun push(i: Iterator<String>): Iterator<String> {
val j = i
return j
}
}
@@ -0,0 +1,28 @@
//file
package demo;
import java.util.*;
class Test implements Iterable<String> {
@Override
public Iterator<String> iterator() {
return null;
}
public Iterator<String> push(Iterator<String> i) {
Iterator<String> j = i;
return j;
}
}
class FullTest implements java.lang.Iterable<String> {
@Override
public java.util.Iterator<String> iterator() {
return null;
}
public java.util.Iterator<String> push(java.util.Iterator<String> i) {
java.util.Iterator<String> j = i;
return j;
}
}
@@ -0,0 +1,26 @@
package demo
import java.util.*
import kotlin.Iterator
class Test() : Iterable<String> {
override fun iterator(): Iterator<String>? {
return null
}
public fun push(i: Iterator<String>): Iterator<String> {
val j = i
return j
}
}
class FullTest() : Iterable<String> {
override fun iterator(): Iterator<String>? {
return null
}
public fun push(i: Iterator<String>): Iterator<String> {
val j = i
return j
}
}
@@ -0,0 +1,16 @@
//file
package demo;
import java.util.Iterator;
class Test implements Iterable<String> {
@Override
public Iterator<String> iterator() {
return null;
}
public Iterator<String> push(Iterator<String> i) {
Iterator<String> j = i;
return j;
}
}
@@ -0,0 +1,12 @@
package demo
class Test() : Iterable<String> {
override fun iterator(): Iterator<String>? {
return null
}
public fun push(i: Iterator<String>): Iterator<String> {
val j = i
return j
}
}