// TODO: check rhs is "rvalue"
}
@Check
public void checkSelectorExpression(SelectorExpression o) {
Expression lhs = o.getLeftExpr();
// -- non null lhs, and must be an acceptable lhs value for selector
if(lhs == null)
acceptor.acceptError(
"A selector expression must have a left expression", o,
PPPackage.Literals.PARAMETERIZED_EXPRESSION__LEFT_EXPR, INSIGNIFICANT_INDEX,
IPPDiagnostics.ISSUE__NULL_EXPRESSION);
else if(!isSELECTOR_LHS(lhs))
acceptor.acceptError(
"Not an acceptable selector left hand side expression", o,
PPPackage.Literals.PARAMETERIZED_EXPRESSION__LEFT_EXPR, INSIGNIFICANT_INDEX,
IPPDiagnostics.ISSUE__UNSUPPORTED_EXPRESSION);
// -- there must be at least one parameter
if(o.getParameters().size() < 1)
acceptor.acceptError(
"A selector expression must have at least one right side entry", o,
PPPackage.Literals.PARAMETERIZED_EXPRESSION__PARAMETERS, INSIGNIFICANT_INDEX,
IPPDiagnostics.ISSUE__NULL_EXPRESSION);
// -- all parameters must be SelectorEntry instances
// -- one of them should have LiteralDefault as left expr
// -- there should only be one default
boolean theDefaultIsSeen = false;
IValidationAdvisor advisor = advisor();
// collect unreachable entries to avoid multiple unreachable markers for an entry
Set<Integer> unreachables = Sets.newHashSet();
Set<Integer> duplicates = Sets.newHashSet();
List<Expression> caseExpressions = Lists.newArrayList();
for(Expression e : o.getParameters()) {
if(!(e instanceof SelectorEntry)) {
acceptor.acceptError(
"Must be a selector entry. Was:" + expressionTypeNameProvider.doToString(e), o,
PPPackage.Literals.PARAMETERIZED_EXPRESSION__PARAMETERS, o.getParameters().indexOf(e),
IPPDiagnostics.ISSUE__UNSUPPORTED_EXPRESSION);
caseExpressions.add(null); // to be skipped later
}
else {
// it is a selector entry
SelectorEntry se = (SelectorEntry) e;
Expression e1 = se.getLeftExpr();
caseExpressions.add(e1);
if(e1 instanceof LiteralDefault)
theDefaultIsSeen = true;
}
}
ValidationPreference defaultLast = advisor.selectorDefaultShouldAppearLast();
if(defaultLast.isWarningOrError() && theDefaultIsSeen) {
for(int i = 0; i < caseExpressions.size() - 1; i++) {
Expression e1 = caseExpressions.get(i);
if(e1 == null)
continue;
if(e1 instanceof LiteralDefault) {
acceptor.accept(
severity(defaultLast), "A 'default' should be placed last", e1,
IPPDiagnostics.ISSUE__DEFAULT_NOT_LAST);
}
}
}
// check that there is a default
if(!theDefaultIsSeen) {
ValidationPreference missingDefaultInSelector = advisor.missingDefaultInSelector();
if(missingDefaultInSelector.isWarningOrError())
acceptor.accept(
severity(missingDefaultInSelector), "Missing 'default' selector case", o,
IPPDiagnostics.ISSUE__MISSING_DEFAULT);
}
// Check unreachable by equivalence
// If a case expr is the same as the switch, all other are unreachable
// Check for duplicates
for(int i = 0; i < caseExpressions.size(); i++) {
Expression e1 = caseExpressions.get(i);
if(e1 == null)
continue;
if(eqCalculator.isEquivalent(e1, o.getLeftExpr()))
for(int u = 0; u < caseExpressions.size(); u++) {
if(i == u || caseExpressions.get(u) == null)
continue;
unreachables.add(u);
}
for(int j = i + 1; j < caseExpressions.size(); j++) {
Expression e2 = caseExpressions.get(j);
if(e2 == null)
continue;
if(eqCalculator.isEquivalent(e1, e2)) {
duplicates.add(i);
duplicates.add(j);
}
}
}
for(Integer i : unreachables)
if(caseExpressions.get(i) != null)
acceptor.acceptWarning("Unreachable", caseExpressions.get(i), IPPDiagnostics.ISSUE__UNREACHABLE);
for(Integer i : duplicates)
if(caseExpressions.get(i) != null)
acceptor.acceptError(
"Duplicate selector case", caseExpressions.get(i), IPPDiagnostics.ISSUE__DUPLICATE_CASE);
// check missing comma between entries
final int count = o.getParameters().size();
EList<Expression> params = o.getParameters();
for(int i = 0; i < count - 1; i++) {
// do not complain about missing ',' if expression is not a selector entry
Expression e1 = params.get(i);
if(e1 instanceof SelectorEntry == false)
continue;
INode n = NodeModelUtils.getNode(e1);
INode n2 = NodeModelUtils.getNode(params.get(i + 1));