diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java index 94f6652418d..bfab6875415 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitor.java @@ -66,7 +66,10 @@ public int getPriority() { * @param ctx AST выражения * @return дерево вычисления выражения */ - public static @Nullable BslExpression buildExpressionTree(BSLParser.ExpressionContext ctx) { + public static @Nullable BslExpression buildExpressionTree(BSLParser.@Nullable ExpressionContext ctx) { + if (ctx == null) { + return null; + } var instance = new ExpressionTreeBuildingVisitor(); instance.visitExpression(ctx); return instance.getExpressionTree(); @@ -419,11 +422,19 @@ public ParseTree visitAccessCall(BSLParser.AccessCallContext ctx) { @Override public ParseTree visitTernaryOperator(BSLParser.TernaryOperatorContext ctx) { - var ternary = TernaryOperatorNode.create( - Objects.requireNonNull(makeSubexpression(ctx.expression(0))), - Objects.requireNonNull(makeSubexpression(ctx.expression(1))), - Objects.requireNonNull(makeSubexpression(ctx.expression(2))) - ); + var condition = makeSubexpression(ctx.expression(0)); + var truePart = makeSubexpression(ctx.expression(1)); + var falsePart = makeSubexpression(ctx.expression(2)); + + // If any expression is null (which happens when the parser encounters syntax errors + // in incomplete ternary operators like "?" or "Возврат ?"), create an error node + // instead of attempting to create a TernaryOperatorNode to avoid NullPointerException + if (condition == null || truePart == null || falsePart == null) { + operands.push(new ErrorExpressionNode(ctx)); + return ctx; + } + + var ternary = TernaryOperatorNode.create(condition, truePart, falsePart); ternary.setRepresentingAst(ctx); operands.push(ternary); diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitorTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitorTest.java index 0bbae0aed78..80979820246 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitorTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/utils/expressiontree/ExpressionTreeBuildingVisitorTest.java @@ -88,7 +88,8 @@ static Stream errorHandlingTestCases() { createIfStatementTestCase("New expression", "Новый"), createIfStatementTestCase("New expression with parenthes", "Новый ("), createIfStatementTestCase("New expression with two parantheses", "Новый ()"), - createIfStatementTestCase("New expression with NOT", "Новый Структура(\"\", Не)", ConstructorCallNode.class) + createIfStatementTestCase("New expression with NOT", "Новый Структура(\"\", Не)", ConstructorCallNode.class), + createIfStatementTestCase("Incomplete ternary operator - only question mark", "?") ); }