J2K: Fix java 9 try-with-resources

This commit is contained in:
Simon Ogorodnik
2020-07-17 23:06:36 +03:00
parent c5005f8695
commit 8bcf1000f6
10 changed files with 107 additions and 14 deletions
@@ -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(),
@@ -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<JKDeclaration>,
resourceDeclarations: List<JKJavaResourceElement>,
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
)
@@ -90,17 +90,16 @@ fun blockStatement(statements: List<JKStatement>) =
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(
@@ -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)
}
}
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)
}
@@ -125,16 +125,18 @@ class JKJavaThrowStatement(exception: JKExpression) : JKStatement() {
}
class JKJavaTryStatement(
resourceDeclarations: List<JKDeclaration>,
resourceDeclarations: List<JKJavaResourceElement>,
tryBlock: JKBlock,
finallyBlock: JKBlock,
catchSections: List<JKJavaTryCatchSection>
) : JKStatement() {
var resourceDeclarations: List<JKDeclaration> by children(resourceDeclarations)
var resourceDeclarations: List<JKJavaResourceElement> by children(resourceDeclarations)
var tryBlock: JKBlock by child(tryBlock)
var finallyBlock: JKBlock by child(finallyBlock)
var catchSections: List<JKJavaTryCatchSection> by children(catchSections)
override fun accept(visitor: JKVisitor) = visitor.visitJavaTryStatement(this)
val isTryWithResources get() = resourceDeclarations.isNotEmpty()
}
class JKJavaSynchronizedStatement(
+14
View File
@@ -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();
}
}
}
+16
View File
@@ -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()
}
}
}
}
+14
View File
@@ -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();
}
}
}
+17
View File
@@ -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()
}
}
}
}
@@ -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");