use of org.eclipse.jdt.internal.compiler.flow.SwitchFlowContext in project bazel-jdt-java-toolchain by salesforce.
the class SwitchStatement method analyseCode.
@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
try {
flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
if (isNullHostile()) {
this.expression.checkNPE(currentScope, flowContext, flowInfo, 1);
}
SwitchFlowContext switchContext = new SwitchFlowContext(flowContext, this, (this.breakLabel = new BranchLabel()), true, true);
switchContext.isExpression = this instanceof SwitchExpression;
// analyse the block by considering specially the case/default statements (need to bind them
// to the entry point)
FlowInfo caseInits = FlowInfo.DEAD_END;
// in case of statements before the first case
this.preSwitchInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
int caseIndex = 0;
if (this.statements != null) {
int initialComplaintLevel = (flowInfo.reachMode() & FlowInfo.UNREACHABLE) != 0 ? Statement.COMPLAINED_FAKE_REACHABLE : Statement.NOT_COMPLAINED;
int complaintLevel = initialComplaintLevel;
int fallThroughState = CASE;
for (int i = 0, max = this.statements.length; i < max; i++) {
Statement statement = this.statements[i];
if ((caseIndex < this.caseCount) && (statement == this.cases[caseIndex])) {
// statement is a case
// record entering in a switch case block
this.scope.enclosingCase = this.cases[caseIndex];
caseIndex++;
if (fallThroughState == FALLTHROUGH) {
if (((CaseStatement) statement).containsPatternVariable())
this.scope.problemReporter().IllegalFallThroughToPattern(this.scope.enclosingCase);
else if ((statement.bits & ASTNode.DocumentedFallthrough) == 0) {
// the case is not fall-through protected by a line comment
this.scope.problemReporter().possibleFallThroughCase(this.scope.enclosingCase);
}
}
caseInits = caseInits.mergedWith(flowInfo.unconditionalInits());
// reset complaint
complaintLevel = initialComplaintLevel;
fallThroughState = this.containsPatterns ? FALLTHROUGH : CASE;
} else if (statement == this.defaultCase) {
// statement is the default case
// record entering in a switch case block
this.scope.enclosingCase = this.defaultCase;
if (fallThroughState == FALLTHROUGH && (statement.bits & ASTNode.DocumentedFallthrough) == 0) {
this.scope.problemReporter().possibleFallThroughCase(this.scope.enclosingCase);
}
caseInits = caseInits.mergedWith(flowInfo.unconditionalInits());
if ((this.switchBits & LabeledRules) != 0 && this.expression.resolvedType instanceof ReferenceBinding) {
if (this.expression instanceof NameReference) {
// default case does not apply to null => mark the variable being switched over as nonnull:
NameReference reference = (NameReference) this.expression;
if (reference.localVariableBinding() != null) {
caseInits.markAsDefinitelyNonNull(reference.localVariableBinding());
} else if (reference.lastFieldBinding() != null) {
if (this.scope.compilerOptions().enableSyntacticNullAnalysisForFields)
// survive this case statement and into the next
switchContext.recordNullCheckedFieldReference(reference, 2);
}
} else if (this.expression instanceof FieldReference) {
if (this.scope.compilerOptions().enableSyntacticNullAnalysisForFields)
// survive this case statement and into the next
switchContext.recordNullCheckedFieldReference((FieldReference) this.expression, 2);
}
}
// reset complaint
complaintLevel = initialComplaintLevel;
fallThroughState = this.containsPatterns ? FALLTHROUGH : CASE;
} else {
if (!(this instanceof SwitchExpression) && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK14 && statement instanceof YieldStatement && ((YieldStatement) statement).isImplicit) {
YieldStatement y = (YieldStatement) statement;
Expression e = ((YieldStatement) statement).expression;
/* JLS 13 14.11.2
Switch labeled rules in switch statements differ from those in switch expressions (15.28).
In switch statements they must be switch labeled statement expressions, ... */
if (!y.expression.statementExpression()) {
this.scope.problemReporter().invalidExpressionAsStatement(e);
}
}
// reset below if needed
fallThroughState = getFallThroughState(statement, currentScope);
}
if ((complaintLevel = statement.complainIfUnreachable(caseInits, this.scope, complaintLevel, true)) < Statement.COMPLAINED_UNREACHABLE) {
caseInits = statement.analyseCode(this.scope, switchContext, caseInits);
if (caseInits == FlowInfo.DEAD_END) {
fallThroughState = ESCAPING;
}
switchContext.expireNullCheckedFieldInfo();
}
}
completeNormallyCheck(currentScope);
}
final TypeBinding resolvedTypeBinding = this.expression.resolvedType;
if (resolvedTypeBinding.isEnum()) {
final SourceTypeBinding sourceTypeBinding = currentScope.classScope().referenceContext.binding;
this.synthetic = sourceTypeBinding.addSyntheticMethodForSwitchEnum(resolvedTypeBinding, this);
}
// if no default case, then record it may jump over the block directly to the end
if (this.defaultCase == null && needToCheckFlowInAbsenceOfDefaultBranch()) {
// only retain the potential initializations
flowInfo.addPotentialInitializationsFrom(caseInits.mergedWith(switchContext.initsOnBreak));
this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(flowInfo);
return flowInfo;
}
// merge all branches inits
FlowInfo mergedInfo = caseInits.mergedWith(switchContext.initsOnBreak);
this.mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
return mergedInfo;
} finally {
// no longer inside switch case block
if (this.scope != null)
this.scope.enclosingCase = null;
}
}
Aggregations