diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/JavaToJKTreeBuilder.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/JavaToJKTreeBuilder.kt index ed99e0815ce..6d4623787e2 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/JavaToJKTreeBuilder.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/JavaToJKTreeBuilder.kt @@ -990,7 +990,7 @@ class JavaToJKTreeBuilder constructor( JKJavaThrowStatement(with(expressionTreeMapper) { exception.toJK() }) is PsiTryStatement -> JKJavaTryStatement( - resourceList?.toList()?.map { (it as PsiLocalVariable).toJK() }.orEmpty(), + resourceList?.toList()?.map { (it as PsiResourceListElement).toJK() }.orEmpty(), tryBlock?.toJK() ?: JKBodyStub, finallyBlock?.toJK() ?: JKBodyStub, catchSections.map { it.toJK() } @@ -1009,6 +1009,13 @@ class JavaToJKTreeBuilder constructor( } } + fun PsiResourceListElement.toJK(): JKJavaResourceElement = + when (this) { + is PsiResourceVariable -> JKJavaResourceDeclaration((this as PsiLocalVariable).toJK()) + is PsiResourceExpression -> JKJavaResourceExpression(with(expressionTreeMapper) { this@toJK.expression.toJK() }) + else -> throwCanNotConvertError() + } + fun PsiCatchSection.toJK(): JKJavaTryCatchSection = JKJavaTryCatchSection( parameter?.toJK() ?: throwCanNotConvertError(), diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TryStatementConversion.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TryStatementConversion.kt index fa92972f9dd..2dd3bf5b268 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TryStatementConversion.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/conversions/TryStatementConversion.kt @@ -17,9 +17,10 @@ import org.jetbrains.kotlin.nj2k.useExpression class TryStatementConversion(context: NewJ2kConverterContext) : RecursiveApplicableConversionBase(context) { override fun applyToElement(element: JKTreeElement): JKTreeElement { if (element !is JKJavaTryStatement) return recurse(element) - return if (element.resourceDeclarations.isEmpty()) + return if (element.isTryWithResources) + recurse(convertTryStatementWithResources(element)) + else recurse(convertNoResourcesTryStatement(element)) - else recurse(convertTryStatementWithResources(element)) } private fun convertNoResourcesTryStatement(tryStatement: JKJavaTryStatement): JKStatement = @@ -49,16 +50,20 @@ class TryStatementConversion(context: NewJ2kConverterContext) : RecursiveApplica } private fun resourceDeclarationsToUseExpression( - resourceDeclarations: List, + resourceDeclarations: List, innerStatement: JKStatement ): JKStatement = resourceDeclarations .reversed() - .fold(innerStatement) { inner, variable -> + .fold(innerStatement) { inner, element -> + val (receiver, name) = when (element) { + is JKJavaResourceExpression -> element::expression.detached() to null + is JKJavaResourceDeclaration -> element.declaration::initializer.detached() to element.declaration::name.detached() + } JKExpressionStatement( useExpression( - receiver = (variable as JKLocalVariable)::initializer.detached(), - variableIdentifier = variable::name.detached(), + receiver = receiver, + variableIdentifier = name, body = inner, symbolProvider = symbolProvider ) diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt index 677ed4e6204..1ca476eb6cb 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/expressions.kt @@ -90,17 +90,16 @@ fun blockStatement(statements: List) = fun useExpression( receiver: JKExpression, - variableIdentifier: JKNameIdentifier, + variableIdentifier: JKNameIdentifier?, body: JKStatement, symbolProvider: JKSymbolProvider ): JKExpression { val useSymbol = symbolProvider.provideMethodSymbol("kotlin.io.use") - val lambdaParameter = - JKParameter(JKTypeElement(JKNoType), variableIdentifier) + val lambdaParameter = if (variableIdentifier != null) JKParameter(JKTypeElement(JKNoType), variableIdentifier) else null val lambda = JKLambdaExpression( body, - listOf(lambdaParameter) + listOfNotNull(lambdaParameter) ) val methodCall = JKCallExpressionImpl( diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt index 5ec765c0686..758adad33c3 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/elements.kt @@ -251,4 +251,13 @@ class JKKtTryCatchSection( var parameter: JKParameter by child(parameter) var block: JKBlock by child(block) override fun accept(visitor: JKVisitor) = visitor.visitKtTryCatchSection(this) -} \ No newline at end of file +} + +sealed class JKJavaResourceElement : JKTreeElement(), PsiOwner by PsiOwnerImpl() + +class JKJavaResourceExpression(expression: JKExpression) : JKJavaResourceElement() { + var expression by child(expression) +} +class JKJavaResourceDeclaration(declaration: JKLocalVariable) : JKJavaResourceElement() { + var declaration by child(declaration) +} diff --git a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/statements.kt b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/statements.kt index e9ac2caf137..16988ad4296 100644 --- a/nj2k/src/org/jetbrains/kotlin/nj2k/tree/statements.kt +++ b/nj2k/src/org/jetbrains/kotlin/nj2k/tree/statements.kt @@ -125,16 +125,18 @@ class JKJavaThrowStatement(exception: JKExpression) : JKStatement() { } class JKJavaTryStatement( - resourceDeclarations: List, + resourceDeclarations: List, tryBlock: JKBlock, finallyBlock: JKBlock, catchSections: List ) : JKStatement() { - var resourceDeclarations: List by children(resourceDeclarations) + var resourceDeclarations: List by children(resourceDeclarations) var tryBlock: JKBlock by child(tryBlock) var finallyBlock: JKBlock by child(finallyBlock) var catchSections: List by children(catchSections) override fun accept(visitor: JKVisitor) = visitor.visitJavaTryStatement(this) + + val isTryWithResources get() = resourceDeclarations.isNotEmpty() } class JKJavaSynchronizedStatement( diff --git a/nj2k/testData/newJ2k/tryWithResource/Java9.java b/nj2k/testData/newJ2k/tryWithResource/Java9.java new file mode 100644 index 00000000000..5978415891a --- /dev/null +++ b/nj2k/testData/newJ2k/tryWithResource/Java9.java @@ -0,0 +1,14 @@ +import java.io.*; + +public class Java9 { + public void check() throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + + try(br; + BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in)); + ) { + br.readLine(); + br2.readLine(); + } + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/tryWithResource/Java9.kt b/nj2k/testData/newJ2k/tryWithResource/Java9.kt new file mode 100644 index 00000000000..893ad04d787 --- /dev/null +++ b/nj2k/testData/newJ2k/tryWithResource/Java9.kt @@ -0,0 +1,16 @@ +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader + +class Java9 { + @Throws(IOException::class) + fun check() { + val br = BufferedReader(InputStreamReader(System.`in`)) + br.use { + BufferedReader(InputStreamReader(System.`in`)).use { br2 -> + br.readLine() + br2.readLine() + } + } + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/tryWithResource/Java9Multiple.java b/nj2k/testData/newJ2k/tryWithResource/Java9Multiple.java new file mode 100644 index 00000000000..3352e4e184b --- /dev/null +++ b/nj2k/testData/newJ2k/tryWithResource/Java9Multiple.java @@ -0,0 +1,14 @@ +import java.io.*; + +public class Java9 { + public void check() throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); + BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in)); + try(br; + br2 + ) { + br.readLine(); + br2.readLine(); + } + } +} \ No newline at end of file diff --git a/nj2k/testData/newJ2k/tryWithResource/Java9Multiple.kt b/nj2k/testData/newJ2k/tryWithResource/Java9Multiple.kt new file mode 100644 index 00000000000..5e503878c6d --- /dev/null +++ b/nj2k/testData/newJ2k/tryWithResource/Java9Multiple.kt @@ -0,0 +1,17 @@ +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader + +class Java9 { + @Throws(IOException::class) + fun check() { + val br = BufferedReader(InputStreamReader(System.`in`)) + val br2 = BufferedReader(InputStreamReader(System.`in`)) + br.use { + br2.use { + br.readLine() + br2.readLine() + } + } + } +} diff --git a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java index e6f0a87e36e..d2a05450f60 100644 --- a/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java +++ b/nj2k/tests/org/jetbrains/kotlin/nj2k/NewJavaToKotlinConverterSingleFileTestGenerated.java @@ -5066,6 +5066,16 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("nj2k/testData/newJ2k/tryWithResource"), Pattern.compile("^([^\\.]+)\\.java$"), null, true); } + @TestMetadata("Java9.java") + public void testJava9() throws Exception { + runTest("nj2k/testData/newJ2k/tryWithResource/Java9.java"); + } + + @TestMetadata("Java9Multiple.java") + public void testJava9Multiple() throws Exception { + runTest("nj2k/testData/newJ2k/tryWithResource/Java9Multiple.java"); + } + @TestMetadata("Multiline.java") public void testMultiline() throws Exception { runTest("nj2k/testData/newJ2k/tryWithResource/Multiline.java");