mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[uast] UBreakWithValueExpression for evaluating Java 12 "enhanced" switch (IDEA-202555)
This commit is contained in:
@@ -113,7 +113,12 @@ class TreeBasedEvaluator(
|
||||
|
||||
override fun visitBreakExpression(node: UBreakExpression, data: UEvaluationState): UEvaluationInfo {
|
||||
storeState(node, data)
|
||||
return UNothingValue(node) to data storeResultFor node
|
||||
return when (node) {
|
||||
is UBreakWithValueExpression ->
|
||||
node.valueExpression?.accept(chain, data)?.let { UBreakResult(it.value, node) } ?: UUndeterminedValue
|
||||
else ->
|
||||
UNothingValue(node)
|
||||
} to data storeResultFor node
|
||||
}
|
||||
|
||||
override fun visitContinueExpression(node: UContinueExpression, data: UEvaluationState): UEvaluationInfo {
|
||||
@@ -523,9 +528,9 @@ class TreeBasedEvaluator(
|
||||
if (!clauseInfo.reachable) break
|
||||
}
|
||||
val clauseValue = clauseInfo.value
|
||||
if (clauseValue is UNothingValue && clauseValue.containingLoopOrSwitch == node) {
|
||||
if (exitingNode(clauseValue) == node) {
|
||||
// break from switch
|
||||
resultInfo = resultInfo?.merge(clauseInfo) ?: clauseInfo
|
||||
resultInfo = resultInfo merge getBreakResult(clauseInfo)
|
||||
if (caseCondition == UBooleanConstant.True) break@clausesLoop
|
||||
clauseInfo = subjectInfo
|
||||
fallThroughCondition = UBooleanConstant.False
|
||||
@@ -546,6 +551,32 @@ class TreeBasedEvaluator(
|
||||
return resultInfo storeResultFor node
|
||||
}
|
||||
|
||||
private fun exitingNode(uValue: UValue): UExpression? {
|
||||
when (uValue) {
|
||||
is UNothingValue -> return uValue.containingLoopOrSwitch
|
||||
is UPhiValue -> {
|
||||
for (value in uValue.values) if (value is UBreakResult) return value.containingLoopOrSwitch
|
||||
for (value in uValue.values) if (value is UNothingValue) value.containingLoopOrSwitch?.let { return it }
|
||||
return null
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBreakResult(clauseInfo: UEvaluationInfo): UEvaluationInfo {
|
||||
val clauseValue = clauseInfo.value
|
||||
return when (clauseValue) {
|
||||
is UBreakResult -> clauseValue.value to clauseInfo.state
|
||||
is UPhiValue -> UPhiValue.create(clauseValue.values.map {
|
||||
when (it) {
|
||||
is UBreakResult -> it.value
|
||||
else -> it
|
||||
}
|
||||
}) to clauseInfo.state
|
||||
else -> clauseInfo
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateLoop(
|
||||
loop: ULoopExpression,
|
||||
inputState: UEvaluationState,
|
||||
|
||||
@@ -34,4 +34,9 @@ data class UEvaluationInfo(val value: UValue, val state: UEvaluationState) {
|
||||
get() = value.reachable
|
||||
}
|
||||
|
||||
infix fun UEvaluationInfo?.merge(otherInfo: UEvaluationInfo?): UEvaluationInfo? =
|
||||
if (this != null)
|
||||
if (otherInfo != null) this.merge(otherInfo) else this
|
||||
else otherInfo
|
||||
|
||||
infix fun UValue.to(state: UEvaluationState): UEvaluationInfo = UEvaluationInfo(this, state)
|
||||
@@ -38,4 +38,25 @@ interface UBreakExpression : UJumpExpression {
|
||||
override fun asLogString(): String = log("label = $label")
|
||||
|
||||
override fun asRenderString(): String = label?.let { "break@$it" } ?: "break"
|
||||
}
|
||||
|
||||
interface UBreakWithValueExpression : UBreakExpression {
|
||||
|
||||
val valueExpression: UExpression?
|
||||
|
||||
override fun accept(visitor: UastVisitor) {
|
||||
if (visitor.visitBreakExpression(this)) return
|
||||
annotations.acceptList(visitor)
|
||||
valueExpression?.accept(visitor)
|
||||
visitor.afterVisitBreakExpression(this)
|
||||
}
|
||||
|
||||
override fun asLogString(): String = log("label = $label, hasValue = ${valueExpression != null}")
|
||||
|
||||
override fun asRenderString(): String = buildString {
|
||||
append("break")
|
||||
label?.let { append("@$it") }
|
||||
valueExpression?.let { append(" ${it.asRenderString()}") }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@ package org.jetbrains.uast.values
|
||||
import org.jetbrains.uast.*
|
||||
|
||||
// Something that never can be reached / created
|
||||
internal class UNothingValue private constructor(
|
||||
internal open class UNothingValue private constructor(
|
||||
val containingLoopOrSwitch: UExpression?,
|
||||
val kind: JumpKind
|
||||
) : UValueBase() {
|
||||
@@ -36,6 +36,7 @@ internal class UNothingValue private constructor(
|
||||
override val reachable = false
|
||||
|
||||
override fun merge(other: UValue) = when (other) {
|
||||
is UBreakResult -> other
|
||||
is UNothingValue -> {
|
||||
val mergedLoopOrSwitch =
|
||||
if (containingLoopOrSwitch == other.containingLoopOrSwitch) containingLoopOrSwitch
|
||||
@@ -43,7 +44,7 @@ internal class UNothingValue private constructor(
|
||||
val mergedKind = if (mergedLoopOrSwitch == null || kind != other.kind) JumpKind.OTHER else kind
|
||||
UNothingValue(mergedLoopOrSwitch, mergedKind)
|
||||
}
|
||||
else -> super.merge(other)
|
||||
else -> other
|
||||
}
|
||||
|
||||
override fun toString() = "Nothing" + when (kind) {
|
||||
@@ -77,3 +78,13 @@ internal class UNothingValue private constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class UBreakResult(val value: UValue, jump: UBreakWithValueExpression) : UNothingValue(jump) {
|
||||
override fun toString(): String = "UBreakResult($value)"
|
||||
|
||||
override fun merge(other: UValue): UValue = when (other) {
|
||||
is UBreakResult -> UPhiValue.create(this, other)
|
||||
is UNothingValue -> this
|
||||
else -> other.merge(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ class UPhiValue private constructor(val values: Set<UValue>) : UValueBase() {
|
||||
|
||||
override fun toString(): String = values.joinToString(prefix = "Phi(", postfix = ")", separator = ", ")
|
||||
|
||||
override val reachable: Boolean
|
||||
get() = values.any { it.reachable }
|
||||
|
||||
companion object {
|
||||
private const val PHI_LIMIT = 4
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ abstract class JavaAbstractUElement(givenParent: UElement?) : JavaUElementWithCo
|
||||
|
||||
private fun JavaAbstractUElement.unwrapSwitch(uParent: UElement): UElement {
|
||||
when (uParent) {
|
||||
is UBreakExpression -> return uParent.uastParent ?: uParent
|
||||
is UBlockExpression -> {
|
||||
val codeBlockParent = uParent.uastParent
|
||||
when (codeBlockParent) {
|
||||
@@ -92,8 +91,12 @@ private fun JavaAbstractUElement.unwrapSwitch(uParent: UElement): UElement {
|
||||
|
||||
is JavaUSwitchEntry -> {
|
||||
val parentSourcePsi = uParent.sourcePsi
|
||||
if (parentSourcePsi is PsiSwitchLabeledRuleStatement && parentSourcePsi.body?.children?.contains(psi) == true)
|
||||
return uParent.body
|
||||
if (parentSourcePsi is PsiSwitchLabeledRuleStatement && parentSourcePsi.body?.children?.contains(psi) == true) {
|
||||
val psi = psi
|
||||
return if (psi is PsiExpression && uParent.body.expressions.size == 1)
|
||||
DummyUBreakExpression(psi, uParent.body)
|
||||
else uParent.body
|
||||
}
|
||||
else
|
||||
return uParent
|
||||
}
|
||||
|
||||
@@ -288,7 +288,9 @@ internal object JavaConverter {
|
||||
is PsiDoWhileStatement -> expr<UDoWhileExpression>(build(::JavaUDoWhileExpression))
|
||||
is PsiForStatement -> expr<UForExpression>(build(::JavaUForExpression))
|
||||
is PsiForeachStatement -> expr<UForEachExpression>(build(::JavaUForEachExpression))
|
||||
is PsiBreakStatement -> expr<UBreakExpression>(build(::JavaUBreakExpression))
|
||||
is PsiBreakStatement -> expr<UBreakExpression> {
|
||||
el.valueExpression?.let { JavaUBreakWithValueExpression(el, it, givenParent) } ?: JavaUBreakExpression(el, givenParent)
|
||||
}
|
||||
is PsiContinueStatement -> expr<UContinueExpression>(build(::JavaUContinueExpression))
|
||||
is PsiReturnStatement -> expr<UReturnExpression>(build(::JavaUReturnExpression))
|
||||
is PsiAssertStatement -> expr<UCallExpression>(build(::JavaUAssertExpression))
|
||||
|
||||
+47
-6
@@ -54,9 +54,9 @@ class JavaUSwitchEntryList(override val psi: PsiSwitchBlock, override val uastPa
|
||||
val body = statement.body
|
||||
result += when (body) {
|
||||
is PsiBlockStatement ->
|
||||
JavaUSwitchEntry(listOf(statement), body.codeBlock.statements.toList(), this)
|
||||
JavaUSwitchEntry(listOf(statement), body.codeBlock.statements.toList(), this, false)
|
||||
else ->
|
||||
JavaUSwitchEntry(listOf(statement), listOfNotNull(body), this)
|
||||
JavaUSwitchEntry(listOf(statement), listOfNotNull(body), this, true)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -87,7 +87,7 @@ class JavaUSwitchEntryList(override val psi: PsiSwitchBlock, override val uastPa
|
||||
if (switchEntries.isInitialized()) return switchEntries.value.find { it.labels.contains(switchLabelStatement) }
|
||||
|
||||
if (switchLabelStatement is PsiSwitchLabeledRuleStatement) {
|
||||
return JavaUSwitchEntry(listOf(switchLabelStatement), listOfNotNull(switchLabelStatement.body), this)
|
||||
return JavaUSwitchEntry(listOf(switchLabelStatement), listOfNotNull(switchLabelStatement.body), this, true)
|
||||
}
|
||||
|
||||
val bodyStart = switchLabelStatement.nextSiblings.find { it !is PsiSwitchLabelStatement } ?: return null
|
||||
@@ -116,7 +116,8 @@ private val PsiElement.prevSiblings: Sequence<PsiElement> get() = generateSequen
|
||||
class JavaUSwitchEntry(
|
||||
val labels: List<PsiSwitchLabelStatementBase>,
|
||||
val statements: List<PsiStatement>,
|
||||
givenParent: UElement?
|
||||
givenParent: UElement?,
|
||||
private val addDummyBreak: Boolean = false
|
||||
) : JavaAbstractUExpression(givenParent), USwitchClauseExpressionWithBody {
|
||||
override val psi: PsiSwitchLabelStatementBase = labels.first()
|
||||
|
||||
@@ -134,8 +135,21 @@ class JavaUSwitchEntry(
|
||||
override val body: UExpressionList by lz {
|
||||
object : JavaUExpressionList(psi, JavaSpecialExpressionKinds.SWITCH_ENTRY, this) {
|
||||
|
||||
override val expressions: List<UExpression> =
|
||||
this@JavaUSwitchEntry.statements.map { JavaConverter.convertOrEmpty(it, this) }
|
||||
override val expressions: List<UExpression>
|
||||
|
||||
init {
|
||||
val expressions = ArrayList<UExpression>(this@JavaUSwitchEntry.statements.size)
|
||||
for (statement in this@JavaUSwitchEntry.statements) {
|
||||
expressions.add(JavaConverter.convertOrEmpty(statement, this))
|
||||
}
|
||||
if (addDummyBreak) {
|
||||
val lastValueExpressionPsi = expressions.lastOrNull()?.sourcePsi as? PsiExpression
|
||||
if (lastValueExpressionPsi != null)
|
||||
expressions[expressions.size - 1] = DummyUBreakExpression(lastValueExpressionPsi, this)
|
||||
}
|
||||
|
||||
this.expressions = expressions
|
||||
}
|
||||
|
||||
override fun asRenderString() = buildString {
|
||||
appendln("{")
|
||||
@@ -144,6 +158,33 @@ class JavaUSwitchEntry(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal class DummyUBreakExpression(val valueExpressionPsi: PsiExpression,
|
||||
override val uastParent: UElement?) : UBreakWithValueExpression {
|
||||
override val javaPsi: PsiElement? = null
|
||||
override val sourcePsi: PsiElement? = null
|
||||
override val psi: PsiElement?
|
||||
get() = null
|
||||
override val label: String?
|
||||
get() = null
|
||||
override val annotations: List<UAnnotation>
|
||||
get() = emptyList()
|
||||
|
||||
override val valueExpression: UExpression? by lazy { JavaConverter.convertExpression(valueExpressionPsi, this) }
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as DummyUBreakExpression
|
||||
return valueExpressionPsi == other.valueExpressionPsi
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = valueExpressionPsi.hashCode()
|
||||
|
||||
}
|
||||
|
||||
class JavaUDefaultCaseExpression(override val psi: PsiElement?, givenParent: UElement?)
|
||||
|
||||
@@ -17,8 +17,11 @@
|
||||
package org.jetbrains.uast.java
|
||||
|
||||
import com.intellij.psi.PsiBreakStatement
|
||||
import com.intellij.psi.PsiExpression
|
||||
import org.jetbrains.uast.UBreakExpression
|
||||
import org.jetbrains.uast.UBreakWithValueExpression
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UExpression
|
||||
|
||||
class JavaUBreakExpression(
|
||||
override val psi: PsiBreakStatement,
|
||||
@@ -26,4 +29,16 @@ class JavaUBreakExpression(
|
||||
) : JavaAbstractUExpression(givenParent), UBreakExpression {
|
||||
override val label: String?
|
||||
get() = psi.labelIdentifier?.text
|
||||
}
|
||||
|
||||
class JavaUBreakWithValueExpression(
|
||||
override val psi: PsiBreakStatement,
|
||||
val psiExpression: PsiExpression,
|
||||
givenParent: UElement?
|
||||
) : JavaAbstractUExpression(givenParent), UBreakWithValueExpression {
|
||||
override val valueExpression: UExpression? by lazy {
|
||||
JavaConverter.convertExpression(psiExpression, this)
|
||||
}
|
||||
override val label: String?
|
||||
get() = psi.labelIdentifier?.text
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
public class Main {
|
||||
|
||||
private static String getString() {
|
||||
var str = "abc";
|
||||
var str = "baz";
|
||||
|
||||
final String numericString =
|
||||
switch (str) {
|
||||
|
||||
@@ -4,7 +4,7 @@ UFile (package = )
|
||||
UBlockExpression
|
||||
UDeclarationsExpression
|
||||
ULocalVariable (name = str)
|
||||
ULiteralExpression (value = "abc")
|
||||
ULiteralExpression (value = "baz")
|
||||
UDeclarationsExpression
|
||||
ULocalVariable (name = numericString)
|
||||
USwitchExpression
|
||||
@@ -20,20 +20,24 @@ UFile (package = )
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||
UIdentifier (Identifier (println))
|
||||
ULiteralExpression (value = "here")
|
||||
UBreakExpression (label = null)
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "FOO")
|
||||
USwitchClauseExpressionWithBody
|
||||
ULiteralExpression (value = "bar")
|
||||
ULiteralExpression (value = "beer")
|
||||
UExpressionList (switch_entry)
|
||||
ULiteralExpression (value = "BAR")
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "BAR")
|
||||
USwitchClauseExpressionWithBody
|
||||
ULiteralExpression (value = "baz")
|
||||
UExpressionList (switch_entry)
|
||||
ULiteralExpression (value = "bAz")
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "bAz")
|
||||
USwitchClauseExpressionWithBody
|
||||
UDefaultCaseExpression
|
||||
UExpressionList (switch_entry)
|
||||
ULiteralExpression (value = "default")
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "default")
|
||||
UDeclarationsExpression
|
||||
ULocalVariable (name = numericString2)
|
||||
USwitchExpression
|
||||
@@ -42,11 +46,13 @@ UFile (package = )
|
||||
USwitchClauseExpressionWithBody
|
||||
ULiteralExpression (value = "foo")
|
||||
UExpressionList (switch_entry)
|
||||
UBreakExpression (label = null)
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "FOO")
|
||||
USwitchClauseExpressionWithBody
|
||||
ULiteralExpression (value = "bar")
|
||||
UExpressionList (switch_entry)
|
||||
UBreakExpression (label = null)
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "BAR")
|
||||
USwitchClauseExpressionWithBody
|
||||
ULiteralExpression (value = "baz")
|
||||
ULiteralExpression (value = "zub")
|
||||
@@ -58,11 +64,13 @@ UFile (package = )
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1))
|
||||
UIdentifier (Identifier (println))
|
||||
ULiteralExpression (value = "here")
|
||||
UBreakExpression (label = null)
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "bAz")
|
||||
USwitchClauseExpressionWithBody
|
||||
UDefaultCaseExpression
|
||||
UExpressionList (switch_entry)
|
||||
UBreakExpression (label = null)
|
||||
UBreakWithValueExpression (label = null, hasValue = true)
|
||||
ULiteralExpression (value = "default")
|
||||
UReturnExpression
|
||||
UBinaryExpression (operator = +)
|
||||
USimpleNameReferenceExpression (identifier = numericString)
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
public class Main {
|
||||
private static fun getString() : java.lang.String {
|
||||
var str: var = "abc"
|
||||
var str: var = "baz"
|
||||
final var numericString: java.lang.String = switch (str)
|
||||
"foo" -> {
|
||||
System.out.println("here")
|
||||
break
|
||||
break "FOO"
|
||||
}
|
||||
|
||||
"bar", "beer" -> {
|
||||
"BAR"
|
||||
break "BAR"
|
||||
}
|
||||
|
||||
"baz" -> {
|
||||
"bAz"
|
||||
break "bAz"
|
||||
}
|
||||
|
||||
else -> {
|
||||
"default"
|
||||
break "default"
|
||||
}
|
||||
|
||||
|
||||
final var numericString2: java.lang.String = switch (str)
|
||||
"foo" -> {
|
||||
break
|
||||
break "FOO"
|
||||
}
|
||||
|
||||
"bar" -> {
|
||||
break
|
||||
break "BAR"
|
||||
}
|
||||
|
||||
"baz", "zub" -> {
|
||||
System.out.println("here")
|
||||
break
|
||||
break "bAz"
|
||||
}
|
||||
|
||||
else -> {
|
||||
break
|
||||
break "default"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
UFile (package = ) [public class Main {...]
|
||||
UClass (name = Main) [public class Main {...}]
|
||||
UMethod (name = getString) [private static fun getString() : java.lang.String {...}]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [var str: var = "baz"] = Undetermined
|
||||
ULocalVariable (name = str) [var str: var = "baz"]
|
||||
ULiteralExpression (value = "baz") ["baz"] = "baz"
|
||||
UDeclarationsExpression [final var numericString: java.lang.String = switch (str) ...] = Undetermined
|
||||
ULocalVariable (name = numericString) [final var numericString: java.lang.String = switch (str) ...]
|
||||
USwitchExpression [switch (str) ...] = "bAz"
|
||||
USimpleNameReferenceExpression (identifier = str) [str] = (var str = "baz")
|
||||
UExpressionList (switch) [ "foo" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UQualifiedReferenceExpression [System.out.println("here")] = external println("here")("here")
|
||||
UQualifiedReferenceExpression [System.out] = Undetermined
|
||||
USimpleNameReferenceExpression (identifier = System) [System] = external System()
|
||||
USimpleNameReferenceExpression (identifier = out) [out] = Undetermined
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [println("here")] = external println("here")("here")
|
||||
UIdentifier (Identifier (println)) [UIdentifier (Identifier (println))]
|
||||
ULiteralExpression (value = "here") ["here"] = "here"
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "FOO"] = UBreakResult("FOO")
|
||||
ULiteralExpression (value = "FOO") ["FOO"] = "FOO"
|
||||
USwitchClauseExpressionWithBody ["bar", "beer" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
ULiteralExpression (value = "beer") ["beer"] = "beer"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "BAR"] = UBreakResult("BAR")
|
||||
ULiteralExpression (value = "BAR") ["BAR"] = "BAR"
|
||||
USwitchClauseExpressionWithBody ["baz" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "baz") ["baz"] = "baz"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "bAz"] = UBreakResult("bAz")
|
||||
ULiteralExpression (value = "bAz") ["bAz"] = "bAz"
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "default"] = UBreakResult("default")
|
||||
ULiteralExpression (value = "default") ["default"] = "default"
|
||||
UDeclarationsExpression [final var numericString2: java.lang.String = switch (str) ...] = Undetermined
|
||||
ULocalVariable (name = numericString2) [final var numericString2: java.lang.String = switch (str) ...]
|
||||
USwitchExpression [switch (str) ...] = "bAz"
|
||||
USimpleNameReferenceExpression (identifier = str) [str] = (var str = "baz")
|
||||
UExpressionList (switch) [ "foo" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "FOO"] = UBreakResult("FOO")
|
||||
ULiteralExpression (value = "FOO") ["FOO"] = "FOO"
|
||||
USwitchClauseExpressionWithBody ["bar" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "BAR"] = UBreakResult("BAR")
|
||||
ULiteralExpression (value = "BAR") ["BAR"] = "BAR"
|
||||
USwitchClauseExpressionWithBody ["baz", "zub" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "baz") ["baz"] = "baz"
|
||||
ULiteralExpression (value = "zub") ["zub"] = "zub"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UQualifiedReferenceExpression [System.out.println("here")] = external println("here")("here")
|
||||
UQualifiedReferenceExpression [System.out] = Undetermined
|
||||
USimpleNameReferenceExpression (identifier = System) [System] = external System()
|
||||
USimpleNameReferenceExpression (identifier = out) [out] = Undetermined
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [println("here")] = external println("here")("here")
|
||||
UIdentifier (Identifier (println)) [UIdentifier (Identifier (println))]
|
||||
ULiteralExpression (value = "here") ["here"] = "here"
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "bAz"] = UBreakResult("bAz")
|
||||
ULiteralExpression (value = "bAz") ["bAz"] = "bAz"
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "default"] = UBreakResult("default")
|
||||
ULiteralExpression (value = "default") ["default"] = "default"
|
||||
UReturnExpression [return numericString + numericString2] = Nothing
|
||||
UBinaryExpression (operator = +) [numericString + numericString2] = "bAzbAz" (depending on: (var numericString = "bAz"), (var numericString2 = "bAz"))
|
||||
USimpleNameReferenceExpression (identifier = numericString) [numericString] = (var numericString = "bAz")
|
||||
USimpleNameReferenceExpression (identifier = numericString2) [numericString2] = (var numericString2 = "bAz")
|
||||
@@ -0,0 +1,85 @@
|
||||
public class Main {
|
||||
|
||||
private static String getOneOrTwoString(String unknown) {
|
||||
final String switchResult =
|
||||
switch (unknown) {
|
||||
case "foo", "bar" -> "foobar";
|
||||
default -> "default";
|
||||
};
|
||||
|
||||
return switchResult;
|
||||
}
|
||||
|
||||
private static String getOneOrThrow(String unknown) {
|
||||
final String switchResult =
|
||||
switch (unknown) {
|
||||
case "foo", "bar" -> "foobar";
|
||||
default -> throw new IllegalArgumentException();
|
||||
};
|
||||
|
||||
return switchResult;
|
||||
}
|
||||
|
||||
private static String getThrowOrOne(String unknown) {
|
||||
final String switchResult =
|
||||
switch (unknown) {
|
||||
case "foo", "bar" -> throw new IllegalArgumentException();
|
||||
default -> "foobar";
|
||||
};
|
||||
|
||||
return switchResult;
|
||||
}
|
||||
|
||||
private static String getUnknownString(String unknown) {
|
||||
final String switchResult =
|
||||
switch (unknown) {
|
||||
case "foo", "bar" -> "foobar" + unknown;
|
||||
default -> "default" + unknown;
|
||||
};
|
||||
|
||||
return switchResult;
|
||||
}
|
||||
|
||||
private static int getOneInsideOrThrow(String unknown) {
|
||||
String known = "abc";
|
||||
|
||||
final int switchResult =
|
||||
switch (known) {
|
||||
case "foo":
|
||||
case "bar":
|
||||
break 0;
|
||||
default:
|
||||
if (unknown.length() > 0) {
|
||||
break 12;
|
||||
} else
|
||||
throw new IllegalArgumentException();
|
||||
};
|
||||
|
||||
return switchResult;
|
||||
}
|
||||
|
||||
|
||||
private static int getThrowOrOneInside(String unknown) {
|
||||
String known = "abc";
|
||||
|
||||
final int switchResult =
|
||||
switch (known) {
|
||||
case "foo":
|
||||
case "bar":
|
||||
break 0;
|
||||
default:
|
||||
if (unknown.length() <= 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
else if (unknown.equals("true")) {
|
||||
break 12;
|
||||
}
|
||||
else {
|
||||
break 18;
|
||||
}
|
||||
};
|
||||
|
||||
return switchResult;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
UFile (package = ) [public class Main {...]
|
||||
UClass (name = Main) [public class Main {...}]
|
||||
UMethod (name = getOneOrTwoString) [private static fun getOneOrTwoString(unknown: java.lang.String) : java.lang.String {...}]
|
||||
UParameter (name = unknown) [var unknown: java.lang.String]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [final var switchResult: java.lang.String = switch (unknown) ...] = Undetermined
|
||||
ULocalVariable (name = switchResult) [final var switchResult: java.lang.String = switch (unknown) ...]
|
||||
USwitchExpression [switch (unknown) ...] = Phi("foobar", "default")
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UExpressionList (switch) [ "foo", "bar" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo", "bar" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "foobar"] = UBreakResult("foobar")
|
||||
ULiteralExpression (value = "foobar") ["foobar"] = "foobar"
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "default"] = UBreakResult("default")
|
||||
ULiteralExpression (value = "default") ["default"] = "default"
|
||||
UReturnExpression [return switchResult] = Nothing
|
||||
USimpleNameReferenceExpression (identifier = switchResult) [switchResult] = (var switchResult = Phi("foobar", "default"))
|
||||
UMethod (name = getOneOrThrow) [private static fun getOneOrThrow(unknown: java.lang.String) : java.lang.String {...}]
|
||||
UParameter (name = unknown) [var unknown: java.lang.String]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [final var switchResult: java.lang.String = switch (unknown) ...] = Undetermined
|
||||
ULocalVariable (name = switchResult) [final var switchResult: java.lang.String = switch (unknown) ...]
|
||||
USwitchExpression [switch (unknown) ...] = "foobar"
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UExpressionList (switch) [ "foo", "bar" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo", "bar" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "foobar"] = UBreakResult("foobar")
|
||||
ULiteralExpression (value = "foobar") ["foobar"] = "foobar"
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UThrowExpression [throw IllegalArgumentException()] = Nothing
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [IllegalArgumentException()] = external IllegalArgumentException()()
|
||||
USimpleNameReferenceExpression (identifier = IllegalArgumentException) [IllegalArgumentException] = external IllegalArgumentException()
|
||||
UReturnExpression [return switchResult] = Nothing
|
||||
USimpleNameReferenceExpression (identifier = switchResult) [switchResult] = (var switchResult = "foobar")
|
||||
UMethod (name = getThrowOrOne) [private static fun getThrowOrOne(unknown: java.lang.String) : java.lang.String {...}]
|
||||
UParameter (name = unknown) [var unknown: java.lang.String]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [final var switchResult: java.lang.String = switch (unknown) ...] = Undetermined
|
||||
ULocalVariable (name = switchResult) [final var switchResult: java.lang.String = switch (unknown) ...]
|
||||
USwitchExpression [switch (unknown) ...] = "foobar"
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UExpressionList (switch) [ "foo", "bar" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo", "bar" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UThrowExpression [throw IllegalArgumentException()] = Nothing
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [IllegalArgumentException()] = external IllegalArgumentException()()
|
||||
USimpleNameReferenceExpression (identifier = IllegalArgumentException) [IllegalArgumentException] = external IllegalArgumentException()
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "foobar"] = UBreakResult("foobar")
|
||||
ULiteralExpression (value = "foobar") ["foobar"] = "foobar"
|
||||
UReturnExpression [return switchResult] = Nothing
|
||||
USimpleNameReferenceExpression (identifier = switchResult) [switchResult] = (var switchResult = "foobar")
|
||||
UMethod (name = getUnknownString) [private static fun getUnknownString(unknown: java.lang.String) : java.lang.String {...}]
|
||||
UParameter (name = unknown) [var unknown: java.lang.String]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [final var switchResult: java.lang.String = switch (unknown) ...] = Undetermined
|
||||
ULocalVariable (name = switchResult) [final var switchResult: java.lang.String = switch (unknown) ...]
|
||||
USwitchExpression [switch (unknown) ...] = Undetermined
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UExpressionList (switch) [ "foo", "bar" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo", "bar" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "foobar" + unknown] = UBreakResult(Undetermined)
|
||||
UBinaryExpression (operator = +) ["foobar" + unknown] = Undetermined
|
||||
ULiteralExpression (value = "foobar") ["foobar"] = "foobar"
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break "default" + unknown] = UBreakResult(Undetermined)
|
||||
UBinaryExpression (operator = +) ["default" + unknown] = Undetermined
|
||||
ULiteralExpression (value = "default") ["default"] = "default"
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UReturnExpression [return switchResult] = Nothing
|
||||
USimpleNameReferenceExpression (identifier = switchResult) [switchResult] = (var switchResult = Undetermined)
|
||||
UMethod (name = getOneInsideOrThrow) [private static fun getOneInsideOrThrow(unknown: java.lang.String) : int {...}]
|
||||
UParameter (name = unknown) [var unknown: java.lang.String]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [var known: java.lang.String = "abc"] = Undetermined
|
||||
ULocalVariable (name = known) [var known: java.lang.String = "abc"]
|
||||
ULiteralExpression (value = "abc") ["abc"] = "abc"
|
||||
UDeclarationsExpression [final var switchResult: int = switch (known) ...] = Undetermined
|
||||
ULocalVariable (name = switchResult) [final var switchResult: int = switch (known) ...]
|
||||
USwitchExpression [switch (known) ...] = 12
|
||||
USimpleNameReferenceExpression (identifier = known) [known] = (var known = "abc")
|
||||
UExpressionList (switch) [ "foo", "bar" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo", "bar" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break 0] = UBreakResult(0)
|
||||
ULiteralExpression (value = 0) [0] = 0
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UIfExpression [if (unknown.length() > 0) {...}else throw IllegalArgumentException()] = UBreakResult(12)
|
||||
UBinaryExpression (operator = >) [unknown.length() > 0] = Undetermined
|
||||
UQualifiedReferenceExpression [unknown.length()] = external length()()
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [length()] = external length()()
|
||||
UIdentifier (Identifier (length)) [UIdentifier (Identifier (length))]
|
||||
ULiteralExpression (value = 0) [0] = 0
|
||||
UBlockExpression [{...}] = UBreakResult(12)
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break 12] = UBreakResult(12)
|
||||
ULiteralExpression (value = 12) [12] = 12
|
||||
UThrowExpression [throw IllegalArgumentException()] = Nothing
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [IllegalArgumentException()] = external IllegalArgumentException()()
|
||||
USimpleNameReferenceExpression (identifier = IllegalArgumentException) [IllegalArgumentException] = external IllegalArgumentException()
|
||||
UReturnExpression [return switchResult] = Nothing
|
||||
USimpleNameReferenceExpression (identifier = switchResult) [switchResult] = (var switchResult = 12)
|
||||
UMethod (name = getThrowOrOneInside) [private static fun getThrowOrOneInside(unknown: java.lang.String) : int {...}]
|
||||
UParameter (name = unknown) [var unknown: java.lang.String]
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UDeclarationsExpression [var known: java.lang.String = "abc"] = Undetermined
|
||||
ULocalVariable (name = known) [var known: java.lang.String = "abc"]
|
||||
ULiteralExpression (value = "abc") ["abc"] = "abc"
|
||||
UDeclarationsExpression [final var switchResult: int = switch (known) ...] = Undetermined
|
||||
ULocalVariable (name = switchResult) [final var switchResult: int = switch (known) ...]
|
||||
USwitchExpression [switch (known) ...] = Phi(12, 18)
|
||||
USimpleNameReferenceExpression (identifier = known) [known] = (var known = "abc")
|
||||
UExpressionList (switch) [ "foo", "bar" -> {... ] = Undetermined
|
||||
USwitchClauseExpressionWithBody ["foo", "bar" -> {...] = Undetermined
|
||||
ULiteralExpression (value = "foo") ["foo"] = "foo"
|
||||
ULiteralExpression (value = "bar") ["bar"] = "bar"
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break 0] = UBreakResult(0)
|
||||
ULiteralExpression (value = 0) [0] = 0
|
||||
USwitchClauseExpressionWithBody [else -> {...] = Undetermined
|
||||
UDefaultCaseExpression [else] = Undetermined
|
||||
UExpressionList (switch_entry) [{...] = Undetermined
|
||||
UIfExpression [if (unknown.length() <= 0) {...}] = Phi(UBreakResult(12), UBreakResult(18))
|
||||
UBinaryExpression (operator = <=) [unknown.length() <= 0] = Undetermined
|
||||
UQualifiedReferenceExpression [unknown.length()] = external length()()
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 0)) [length()] = external length()()
|
||||
UIdentifier (Identifier (length)) [UIdentifier (Identifier (length))]
|
||||
ULiteralExpression (value = 0) [0] = 0
|
||||
UBlockExpression [{...}] = Nothing
|
||||
UThrowExpression [throw IllegalArgumentException()] = Nothing
|
||||
UCallExpression (kind = UastCallKind(name='constructor_call'), argCount = 0)) [IllegalArgumentException()] = external IllegalArgumentException()()
|
||||
USimpleNameReferenceExpression (identifier = IllegalArgumentException) [IllegalArgumentException] = external IllegalArgumentException()
|
||||
UIfExpression [if (unknown.equals("true")) {...}] = Phi(UBreakResult(12), UBreakResult(18))
|
||||
UQualifiedReferenceExpression [unknown.equals("true")] = external equals("true")("true")
|
||||
USimpleNameReferenceExpression (identifier = unknown) [unknown] = Undetermined
|
||||
UCallExpression (kind = UastCallKind(name='method_call'), argCount = 1)) [equals("true")] = external equals("true")("true")
|
||||
UIdentifier (Identifier (equals)) [UIdentifier (Identifier (equals))]
|
||||
ULiteralExpression (value = "true") ["true"] = "true"
|
||||
UBlockExpression [{...}] = UBreakResult(12)
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break 12] = UBreakResult(12)
|
||||
ULiteralExpression (value = 12) [12] = 12
|
||||
UBlockExpression [{...}] = UBreakResult(18)
|
||||
UBreakWithValueExpression (label = null, hasValue = true) [break 18] = UBreakResult(18)
|
||||
ULiteralExpression (value = 18) [18] = 18
|
||||
UReturnExpression [return switchResult] = Nothing
|
||||
USimpleNameReferenceExpression (identifier = switchResult) [switchResult] = (var switchResult = Phi(12, 18))
|
||||
@@ -81,6 +81,12 @@ class JavaValuesTest : AbstractJavaValuesTest() {
|
||||
@Test
|
||||
fun testEnumSwitch() = doTest("Simple/EnumSwitch.java")
|
||||
|
||||
@Test
|
||||
fun testEnhancedSwitch() = doTest("Simple/EnhancedSwitch.java")
|
||||
|
||||
@Test
|
||||
fun testEnhancedSwitchComplexEvaluations() = doTest("Simple/EnhancedSwitchComplexEvaluations.java")
|
||||
|
||||
@Test
|
||||
fun testEnumSwitchConditionalBreak() = doTest("Simple/EnumSwitchConditionalBreak.java")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user