Skip to content

Commit 4b8196f

Browse files
authored
fix: NPEs during validation (#727)
### Summary of Changes Fix several NPEs that could occur during validation because the node passed to the acceptor might be `undefined`. Instead of setting the `property`, as should normally be done, we access the child node directly, since this gives us the correct range.
1 parent 1d17900 commit 4b8196f

File tree

1 file changed

+9
-6
lines changed
  • packages/safe-ds-lang/src/language/validation

1 file changed

+9
-6
lines changed

packages/safe-ds-lang/src/language/validation/types.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { AstNode, getContainerOfType, ValidationAcceptor } from 'langium';
2+
import { isEmpty } from '../../helpers/collectionUtils.js';
3+
import { pluralize } from '../../helpers/stringUtils.js';
24
import {
35
isSdsAnnotation,
46
isSdsCallable,
@@ -21,8 +23,6 @@ import {
2123
} from '../generated/ast.js';
2224
import { getTypeArguments, getTypeParameters } from '../helpers/nodeProperties.js';
2325
import { SafeDsServices } from '../safe-ds-module.js';
24-
import { pluralize } from '../../helpers/stringUtils.js';
25-
import { isEmpty } from '../../helpers/collectionUtils.js';
2626

2727
export const CODE_TYPE_CALLABLE_RECEIVER = 'type/callable-receiver';
2828
export const CODE_TYPE_MISMATCH = 'type/mismatch';
@@ -76,12 +76,12 @@ export const callReceiverMustBeCallable = (services: SafeDsServices) => {
7676
}
7777

7878
const callable = nodeMapper.callToCallable(node);
79-
if (!callable || isSdsAnnotation(callable)) {
79+
if (node.receiver && (!callable || isSdsAnnotation(callable))) {
8080
accept('error', 'This expression is not callable.', {
8181
node: node.receiver,
8282
code: CODE_TYPE_CALLABLE_RECEIVER,
8383
});
84-
} else if (isSdsClass(callable) && !callable.parameterList) {
84+
} else if (node.receiver && isSdsClass(callable) && !callable.parameterList) {
8585
accept('error', 'Cannot instantiate a class that has no constructor.', {
8686
node: node.receiver,
8787
code: CODE_TYPE_CALLABLE_RECEIVER,
@@ -98,6 +98,7 @@ export const indexedAccessReceiverMustBeListOrMap = (services: SafeDsServices) =
9898
return (node: SdsIndexedAccess, accept: ValidationAcceptor): void => {
9999
const receiverType = typeComputer.computeType(node.receiver);
100100
if (
101+
node.receiver &&
101102
!typeChecker.isAssignableTo(receiverType, coreTypes.List) &&
102103
!typeChecker.isAssignableTo(receiverType, coreTypes.Map)
103104
) {
@@ -140,13 +141,13 @@ export const infixOperationOperandsMustHaveCorrectType = (services: SafeDsServic
140141
switch (node.operator) {
141142
case 'or':
142143
case 'and':
143-
if (!typeChecker.isAssignableTo(leftType, coreTypes.Boolean)) {
144+
if (node.leftOperand && !typeChecker.isAssignableTo(leftType, coreTypes.Boolean)) {
144145
accept('error', `Expected type '${coreTypes.Boolean}' but got '${leftType}'.`, {
145146
node: node.leftOperand,
146147
code: CODE_TYPE_MISMATCH,
147148
});
148149
}
149-
if (!typeChecker.isAssignableTo(rightType, coreTypes.Boolean)) {
150+
if (node.rightOperand && !typeChecker.isAssignableTo(rightType, coreTypes.Boolean)) {
150151
accept('error', `Expected type '${coreTypes.Boolean}' but got '${rightType}'.`, {
151152
node: node.rightOperand,
152153
code: CODE_TYPE_MISMATCH,
@@ -162,6 +163,7 @@ export const infixOperationOperandsMustHaveCorrectType = (services: SafeDsServic
162163
case '*':
163164
case '/':
164165
if (
166+
node.leftOperand &&
165167
!typeChecker.isAssignableTo(leftType, coreTypes.Float) &&
166168
!typeChecker.isAssignableTo(leftType, coreTypes.Int)
167169
) {
@@ -171,6 +173,7 @@ export const infixOperationOperandsMustHaveCorrectType = (services: SafeDsServic
171173
});
172174
}
173175
if (
176+
node.rightOperand &&
174177
!typeChecker.isAssignableTo(rightType, coreTypes.Float) &&
175178
!typeChecker.isAssignableTo(rightType, coreTypes.Int)
176179
) {

0 commit comments

Comments
 (0)