diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java index 74fba50045d8..6a5b103f6dda 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java @@ -707,32 +707,6 @@ public class CFGBuilder { } } - /** - * Return true if given expression contains return statement (which could be inside switch expression) - * @param expression expression to analyze - * @return true if it has nested return - */ - private static boolean hasNestedReturn(@NotNull PsiExpression expression) { - class Visitor extends JavaRecursiveElementWalkingVisitor { - boolean hasReturn; - - @Override - public void visitLambdaExpression(PsiLambdaExpression expression) {} - - @Override - public void visitClass(PsiClass aClass) {} - - @Override - public void visitReturnStatement(PsiReturnStatement statement) { - hasReturn = true; - stopWalking(); - } - } - Visitor visitor = new Visitor(); - expression.accept(visitor); - return visitor.hasReturn; - } - /** * Inlines given lambda. Lambda parameters are assumed to be assigned already (if necessary). *
@@ -748,20 +722,14 @@ public class CFGBuilder {
PsiElement body = lambda.getBody();
PsiExpression expression = LambdaUtil.extractSingleExpressionFromBody(body);
if (expression != null) {
- if (hasNestedReturn(expression)) {
- DfaVariableValue variable = createTempVariable(LambdaUtil.getFunctionalInterfaceReturnType(lambda));
- myAnalyzer.inlineExpression(lambda, expression, resultNullability, variable);
- push(variable);
- } else {
- pushExpression(expression);
- boxUnbox(expression, LambdaUtil.getFunctionalInterfaceReturnType(lambda));
- if (resultNullability == Nullability.NOT_NULL) {
- checkNotNull(expression, NullabilityProblemKind.nullableFunctionReturn);
- }
+ pushExpression(expression);
+ boxUnbox(expression, LambdaUtil.getFunctionalInterfaceReturnType(lambda));
+ if (resultNullability == Nullability.NOT_NULL) {
+ checkNotNull(expression, NullabilityProblemKind.nullableFunctionReturn);
}
} else if(body instanceof PsiCodeBlock) {
DfaVariableValue variable = createTempVariable(LambdaUtil.getFunctionalInterfaceReturnType(lambda));
- myAnalyzer.inlineBlock(lambda, (PsiCodeBlock)body, resultNullability, variable);
+ myAnalyzer.inlineBlock((PsiCodeBlock)body, resultNullability, variable);
push(variable);
} else {
pushUnknown();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
index c66dddc8c453..b97b6fd73f9e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
@@ -801,24 +801,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
PsiExpression returnValue = statement.getReturnValue();
InlinedBlockContext context = myInlinedBlockContext;
- while (context != null && context.isSwitch()) {
- context = context.myPreviousBlock;
- }
if (context != null) {
- if (returnValue != null) {
- DfaVariableValue var = context.myTarget;
- addInstruction(new PushInstruction(var, null, true));
- returnValue.accept(this);
- generateBoxingUnboxingInstructionFor(returnValue, var.getType());
- if (context.myForceNonNullBlockResult) {
- addInstruction(new CheckNotNullInstruction(NullabilityProblemKind.nullableFunctionReturn.problem(returnValue)));
- }
- addInstruction(new AssignInstruction(returnValue, null));
- addInstruction(new PopInstruction());
- }
-
- controlTransfer(new InstructionTransfer(getEndOffset(context.myCodeBlock), getVariablesInside(context.myCodeBlock)),
- getTrapsInsideElement(context.myCodeBlock));
+ // We treat return inside switch expression (which is disallowed syntax) as break-with-value
+ context.generateReturn(returnValue, this);
} else {
if (returnValue != null) {
@@ -850,52 +835,48 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
@Override
public void visitSwitchLabeledRuleStatement(PsiSwitchLabeledRuleStatement statement) {
+ PsiSwitchBlock switchBlock = statement.getEnclosingSwitchBlock();
+ if (switchBlock == null) return;
startElement(statement);
PsiStatement body = statement.getBody();
+ PsiCodeBlock switchBody = switchBlock.getBody();
+ boolean expressionSwitch = myInlinedBlockContext != null && myInlinedBlockContext.myCodeBlock == switchBody;
+ if (expressionSwitch && body instanceof PsiExpressionStatement) {
+ myInlinedBlockContext.generateReturn(((PsiExpressionStatement)body).getExpression(), this);
+ }
if (body != null) {
- if (body instanceof PsiExpressionStatement && myInlinedBlockContext != null &&
- myInlinedBlockContext.myCodeBlock == statement.getEnclosingSwitchBlock()) {
- addInstruction(new PushInstruction(myInlinedBlockContext.myTarget, null, true));
- PsiExpression expression = ((PsiExpressionStatement)body).getExpression();
- expression.accept(this);
- generateBoxingUnboxingInstructionFor(expression, myInlinedBlockContext.myTarget.getType());
- addInstruction(new AssignInstruction(null, myInlinedBlockContext.myTarget));
- addInstruction(new PopInstruction());
- } else {
- body.accept(this);
- }
- if (!(body instanceof PsiThrowStatement)) {
- jumpOut(statement.getEnclosingSwitchBlock());
- }
+ body.accept(this);
+ }
+ if (!(body instanceof PsiThrowStatement)) {
+ jumpOut(expressionSwitch ? switchBody : switchBlock);
}
finishElement(statement);
}
@Override public void visitSwitchStatement(PsiSwitchStatement switchStmt) {
- processSwitch(switchStmt, null);
+ startElement(switchStmt);
+ processSwitch(switchStmt);
+ finishElement(switchStmt);
}
@Override
public void visitSwitchExpression(PsiSwitchExpression expression) {
PsiCodeBlock body = expression.getBody();
if (body == null) {
- PsiExpression selector = expression.getExpression();
- if (selector != null) {
- selector.accept(this);
- }
- addInstruction(new PopInstruction());
+ processSwitch(expression);
pushUnknown();
} else {
+ startElement(expression);
DfaVariableValue resultVariable = createTempVariable(expression.getType());
- enterInlinedBlock(expression, Nullability.UNKNOWN, resultVariable);
- processSwitch(expression, resultVariable);
+ enterInlinedBlock(body, Nullability.UNKNOWN, resultVariable);
+ processSwitch(expression);
exitInlinedBlock();
addInstruction(new PushInstruction(resultVariable, expression));
+ finishElement(expression);
}
}
- private void processSwitch(@NotNull PsiSwitchBlock switchBlock, @Nullable DfaVariableValue resultVariable) {
- startElement(switchBlock);
+ private void processSwitch(@NotNull PsiSwitchBlock switchBlock) {
PsiExpression caseExpression = switchBlock.getExpression();
Set