Skip to content

Commit

Permalink
Fixed AQL validation NPE.
Browse files Browse the repository at this point in the history
  • Loading branch information
ylussaud committed Feb 26, 2024
1 parent bc5661b commit f276844
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,11 @@ private void noRecognitionException(Recognizer<?, ?> recognizer, Object offendin
*/
private Deque<Expression> lambdaVariableExpression = new ArrayDeque<>();

/**
* Tells if the last argument was a {@link Lambda}.
*/
private boolean lastArgumentIsLambda;

/**
* Creates a new {@link AstBuilderListener}.
*
Expand Down Expand Up @@ -1380,6 +1385,11 @@ private void pushBinary(String service, ParserRuleContext ctx) {
@Override
public void exitServiceCall(ServiceCallContext ctx) {
if (errorRule != QueryParser.RULE_navigationSegment) {
boolean missinEndParenthesis = ctx.getChild(ctx.getChildCount() - 1) instanceof ErrorNode || !")"
.equals(ctx.getChild(ctx.getChildCount() - 1).getText());
if (missinEndParenthesis && lastArgumentIsLambda) {
popErrorExpression();
}
final int argc = getNumberOfArgs(ctx.getChild(2).getChildCount());
final Expression[] args = new Expression[argc];
for (int i = argc - 1; i >= 0; i--) {
Expand All @@ -1396,7 +1406,7 @@ public void exitServiceCall(ServiceCallContext ctx) {
}

final Call call;
if (ctx.getChild(ctx.getChildCount() - 1) instanceof ErrorNode) {
if (missinEndParenthesis) {
call = builder.errorCall(serviceName, true, args);
pushError((Error)call, "missing ')'");
} else {
Expand All @@ -1414,11 +1424,13 @@ public void exitServiceCall(ServiceCallContext ctx) {

@Override
public void enterArguments(ArgumentsContext ctx) {
lastArgumentIsLambda = false;
lambdaVariableExpression.addLast((Expression)stack.getLast());
}

@Override
public void exitArguments(ArgumentsContext ctx) {
lastArgumentIsLambda = stack.getLast() instanceof Lambda;
lambdaVariableExpression.removeLast();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3420,4 +3420,30 @@ public void superCall() {
assertExpression(build, VarRef.class, 0, 0, 0, 4, 0, 4, ((Call)ast).getArguments().get(0));
}

@Test
public void enumLiteralInSelectWithMissingClosingParenthesis() {
AstResult build = engine.build("self->select(s | s = anydsl::Color::black");
Expression ast = build.getAst();

assertEquals(1, build.getErrors().size());
assertEquals(Diagnostic.ERROR, build.getDiagnostic().getSeverity());
assertExpression(build, ErrorCall.class, 0, 0, 0, 41, 0, 41, ast);
assertEquals("select", ((ErrorCall)ast).getServiceName());
assertFalse(((ErrorCall)ast).isSuperCall());
assertTrue(((ErrorCall)ast).isMissingEndParenthesis());
assertEquals(CallType.COLLECTIONCALL, ((ErrorCall)ast).getType());
assertEquals(2, ((ErrorCall)ast).getArguments().size());
assertExpression(build, VarRef.class, 0, 0, 0, 4, 0, 4, ((ErrorCall)ast).getArguments().get(0));
assertExpression(build, Lambda.class, 13, 0, 13, 41, 0, 41, ((ErrorCall)ast).getArguments().get(1));
final Lambda lambda = (Lambda)((ErrorCall)ast).getArguments().get(1);
assertExpression(build, Call.class, 17, 0, 17, 41, 0, 41, lambda.getExpression());
assertFalse(((Call)lambda.getExpression()).isSuperCall());
assertEquals("equals", ((Call)lambda.getExpression()).getServiceName());
assertEquals(2, ((Call)lambda.getExpression()).getArguments().size());
assertExpression(build, VarRef.class, 17, 0, 17, 18, 0, 18, ((Call)lambda.getExpression())
.getArguments().get(0));
assertExpression(build, EnumLiteral.class, 21, 0, 21, 41, 0, 41, ((Call)lambda.getExpression())
.getArguments().get(1));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,28 @@ public void enumLiteral() {
assertEquals(0, validationResult.getMessages(ast).size());
}

@Test
public void enumLiteralInSelectWithMissingClosingParenthesis() {
final IValidationResult validationResult = engine.validate(
"self->select(s | s = anydsl::Color::black", variableTypes);
final Expression ast = validationResult.getAstResult().getAst();
final Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);

assertEquals(1, possibleTypes.size());
final Iterator<IType> it = possibleTypes.iterator();
IType possibleType = it.next();
assertTrue(possibleType instanceof NothingType);
assertEquals("missing ')'", ((NothingType)possibleType).getMessage());

assertEquals(1, validationResult.getMessages().size());
assertValidationMessage(validationResult.getMessages().get(0), ValidationMessageLevel.ERROR,
"missing ')'", 4, 41);

assertEquals(1, validationResult.getMessages(ast).size());
assertValidationMessage(validationResult.getMessages(ast).get(0), ValidationMessageLevel.ERROR,
"missing ')'", 4, 41);
}

@Test
public void enumLiteralError() {
final IValidationResult validationResult = engine.validate("anydsl::Part::NotExisting",
Expand Down

0 comments on commit f276844

Please sign in to comment.