From 159cf612e9090b95a6a130f4ad9ca4cab73cb7b7 Mon Sep 17 00:00:00 2001 From: Bart van Helvert Date: Wed, 15 Nov 2023 15:46:19 +0100 Subject: [PATCH] [uast] Support try-with-resource expressions in Java #IDEA-337821 Fixed GitOrigin-RevId: c17644363e2d00219f5ab08a547ad5532f24974b --- .../controlStructures/KotlinUTryExpression.kt | 5 ++++- .../uast/controlStructures/UTryExpression.kt | 16 ++++++++++++---- .../uast/java/JavaUastLanguagePlugin.kt | 4 ++++ .../controlStructures/JavaUTryExpression.kt | 18 ++++++++++++------ .../Simple/TryWithResources.identifiers.txt | 6 ++++++ .../java/Simple/TryWithResources.java | 9 +++++++-- .../java/Simple/TryWithResources.log.txt | 11 +++++++++++ .../java/Simple/TryWithResources.refNames.txt | 5 +++++ .../java/Simple/TryWithResources.render.txt | 6 ++++++ .../java/Simple/TryWithResources.resolved.txt | 5 +++++ 10 files changed, 72 insertions(+), 13 deletions(-) diff --git a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/controlStructures/KotlinUTryExpression.kt b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/controlStructures/KotlinUTryExpression.kt index cafd42e05982..654f27433600 100644 --- a/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/controlStructures/KotlinUTryExpression.kt +++ b/plugins/kotlin/uast/uast-kotlin-base/src/org/jetbrains/uast/kotlin/controlStructures/KotlinUTryExpression.kt @@ -32,7 +32,10 @@ class KotlinUTryExpression( } } - override val resourceVariables: List + @Deprecated("This API doesn't support resource expression", replaceWith = ReplaceWith("resources")) + override val resourceVariables: List get() = resources.filterIsInstance() + + override val resources: List get() = emptyList() override val hasResources: Boolean diff --git a/uast/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt b/uast/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt index 2efb15b268e7..7ba1a1005b98 100644 --- a/uast/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt +++ b/uast/uast-common/src/org/jetbrains/uast/controlStructures/UTryExpression.kt @@ -34,8 +34,16 @@ interface UTryExpression : UExpression { val hasResources: Boolean /** - * Returns the list of resource variables declared in this expression, or an empty list if this expression is not a `try-with-resources` expression. + * Returns the list of resource variables or expressions declared in this expression, or an empty list if this expression is not a + * `try-with-resources` expression. */ + val resources: List get() = emptyList() + + /** + * Returns the list of resource variables declared in this expression, or an empty list if this expression is not a `try-with-resources` + * expression. + */ + @Deprecated("This API doesn't support resource expression", ReplaceWith("resources")) val resourceVariables: List /** @@ -66,7 +74,7 @@ interface UTryExpression : UExpression { override fun accept(visitor: UastVisitor) { if (visitor.visitTryExpression(this)) return uAnnotations.acceptList(visitor) - resourceVariables.acceptList(visitor) + resources.acceptList(visitor) tryClause.accept(visitor) catchClauses.acceptList(visitor) finallyClause?.accept(visitor) @@ -78,9 +86,9 @@ interface UTryExpression : UExpression { override fun asRenderString(): String = buildString { append("try ") - if (hasResources) { + if (resources.isNotEmpty()) { append("(") - append(resourceVariables.joinToString("\n") { it.asRenderString() }) + append(resources.joinToString("\n") { it.asRenderString() }) append(")") } appendLine(tryClause.asRenderString().trim('\n', '\r')) diff --git a/uast/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt b/uast/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt index be5e95f814c8..53b8569582f1 100644 --- a/uast/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt +++ b/uast/uast-java/src/org/jetbrains/uast/java/JavaUastLanguagePlugin.kt @@ -315,6 +315,10 @@ internal object JavaConverter { override fun visitReferenceParameterList(list: PsiReferenceParameterList) { result = true } + + override fun visitResourceList(resourceList: PsiResourceList) { + result = true + } } element.accept(visitor) diff --git a/uast/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUTryExpression.kt b/uast/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUTryExpression.kt index 91a7ea3684d7..1d846ac45acb 100644 --- a/uast/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUTryExpression.kt +++ b/uast/uast-java/src/org/jetbrains/uast/java/controlStructures/JavaUTryExpression.kt @@ -15,7 +15,7 @@ class JavaUTryExpression( private val tryClausePart = UastLazyPart() private val catchClausesPart = UastLazyPart>() private val finallyClausePart = UastLazyPart() - private val resourceVariablesPart = UastLazyPart>() + private val resourceVariablesPart = UastLazyPart>() override val tryClause: UExpression get() = tryClausePart.getOrBuild { JavaConverter.convertOrEmpty(sourcePsi.tryBlock, this) } @@ -26,12 +26,18 @@ class JavaUTryExpression( override val finallyClause: UBlockExpression? get() = finallyClausePart.getOrBuild { sourcePsi.finallyBlock?.let { JavaConverter.convertBlock(it, this) } } - override val resourceVariables: List + @Deprecated("This API doesn't support resource expression", replaceWith = ReplaceWith("resources")) + override val resourceVariables: List get() = resources.filterIsInstance() + + override val resources: List get() = resourceVariablesPart.getOrBuild { - sourcePsi.resourceList - ?.filterIsInstance() - ?.map { JavaUVariable.create(it, this) } - ?: emptyList() + sourcePsi.resourceList?.mapNotNull { resourceListElem -> + when (resourceListElem) { + is PsiResourceVariable -> JavaUVariable.create(resourceListElem, this) + is PsiResourceExpression -> JavaConverter.convertOrEmpty(resourceListElem.expression, this) + else -> null + } + } ?: emptyList() } override val hasResources: Boolean diff --git a/uast/uast-tests/java/Simple/TryWithResources.identifiers.txt b/uast/uast-tests/java/Simple/TryWithResources.identifiers.txt index 90690f6eaa2d..b659be1bdb28 100644 --- a/uast/uast-tests/java/Simple/TryWithResources.identifiers.txt +++ b/uast/uast-tests/java/Simple/TryWithResources.identifiers.txt @@ -13,3 +13,9 @@ foo -> UMethod (name = foo) from PsiIdentifier:foo path -> USimpleNameReferenceExpression (identifier = path) from PsiIdentifier:path br -> USimpleNameReferenceExpression (identifier = br) from PsiIdentifier:br readLine -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from PsiIdentifier:readLine +foo -> UMethod (name = foo) from PsiIdentifier:foo +BufferedReader -> USimpleNameReferenceExpression (identifier = BufferedReader) from PsiIdentifier:BufferedReader +br -> UParameter (name = br) from PsiIdentifier:br + br -> USimpleNameReferenceExpression (identifier = br) from PsiIdentifier:br + br -> USimpleNameReferenceExpression (identifier = br) from PsiIdentifier:br + readLine -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from PsiIdentifier:readLine diff --git a/uast/uast-tests/java/Simple/TryWithResources.java b/uast/uast-tests/java/Simple/TryWithResources.java index c46c9ca2231d..b69f704a1642 100644 --- a/uast/uast-tests/java/Simple/TryWithResources.java +++ b/uast/uast-tests/java/Simple/TryWithResources.java @@ -18,9 +18,14 @@ import java.io.FileReader; public class TryWithResources { public void foo() { - try (BufferedReader br = - new BufferedReader(new FileReader(path))) { + try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } } + + public void foo(BufferedReader br) { + try (br) { + return br.readLine(); + } + } } \ No newline at end of file diff --git a/uast/uast-tests/java/Simple/TryWithResources.log.txt b/uast/uast-tests/java/Simple/TryWithResources.log.txt index c7d874efd5bd..75260dea40bf 100644 --- a/uast/uast-tests/java/Simple/TryWithResources.log.txt +++ b/uast/uast-tests/java/Simple/TryWithResources.log.txt @@ -17,3 +17,14 @@ UFile (package = ) USimpleNameReferenceExpression (identifier = br) UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) UIdentifier (Identifier (readLine)) + UMethod (name = foo) + UParameter (name = br) + UBlockExpression + UTryExpression (with resources) + USimpleNameReferenceExpression (identifier = br) + UBlockExpression + UReturnExpression + UQualifiedReferenceExpression + USimpleNameReferenceExpression (identifier = br) + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) + UIdentifier (Identifier (readLine)) diff --git a/uast/uast-tests/java/Simple/TryWithResources.refNames.txt b/uast/uast-tests/java/Simple/TryWithResources.refNames.txt index b62049b4e176..0a9d8774371b 100644 --- a/uast/uast-tests/java/Simple/TryWithResources.refNames.txt +++ b/uast/uast-tests/java/Simple/TryWithResources.refNames.txt @@ -11,3 +11,8 @@ java -> USimpleNameReferenceExpression (identifier = java) from PsiJavaCodeRefer readLine -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from PsiMethodCallExpression:br.readLine() readLine -> UQualifiedReferenceExpression from PsiReferenceExpression:br.readLine br -> USimpleNameReferenceExpression (identifier = br) from PsiReferenceExpression:br +BufferedReader -> USimpleNameReferenceExpression (identifier = BufferedReader) from PsiJavaCodeReferenceElement:BufferedReader + br -> USimpleNameReferenceExpression (identifier = br) from PsiReferenceExpression:br + readLine -> UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) from PsiMethodCallExpression:br.readLine() + readLine -> UQualifiedReferenceExpression from PsiReferenceExpression:br.readLine + br -> USimpleNameReferenceExpression (identifier = br) from PsiReferenceExpression:br diff --git a/uast/uast-tests/java/Simple/TryWithResources.render.txt b/uast/uast-tests/java/Simple/TryWithResources.render.txt index 183498d8b7fa..dbd226c33d0b 100644 --- a/uast/uast-tests/java/Simple/TryWithResources.render.txt +++ b/uast/uast-tests/java/Simple/TryWithResources.render.txt @@ -8,4 +8,10 @@ public class TryWithResources { } } + public fun foo(br: java.io.BufferedReader) : void { + try (br){ + return br.readLine() + } + + } } diff --git a/uast/uast-tests/java/Simple/TryWithResources.resolved.txt b/uast/uast-tests/java/Simple/TryWithResources.resolved.txt index ca435bf2a3f5..2505054d38d0 100644 --- a/uast/uast-tests/java/Simple/TryWithResources.resolved.txt +++ b/uast/uast-tests/java/Simple/TryWithResources.resolved.txt @@ -13,3 +13,8 @@ UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = ja UReturnExpression -> UQualifiedReferenceExpression -> PsiMethod:readLine: readLine UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) -> UQualifiedReferenceExpression -> PsiMethod:readLine: readLine UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = br) -> PsiResourceVariable:br: br + UTypeReferenceExpression (name = java.io.BufferedReader) -> USimpleNameReferenceExpression (identifier = BufferedReader) -> PsiClass:BufferedReader: BufferedReader + UTryExpression (with resources) -> USimpleNameReferenceExpression (identifier = br) -> PsiParameter:br: br + UReturnExpression -> UQualifiedReferenceExpression -> PsiMethod:readLine: readLine + UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) -> UQualifiedReferenceExpression -> PsiMethod:readLine: readLine + UQualifiedReferenceExpression -> USimpleNameReferenceExpression (identifier = br) -> PsiParameter:br: br