Skip to content

Commit e518d39

Browse files
committed
chore: disallow this in collection predicate
1 parent 35b4be9 commit e518d39

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

packages/schema/src/language-server/validator/expression-validator.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import {
1313
isThisExpr,
1414
} from '@zenstackhq/language/ast';
1515
import { isAuthInvocation, isDataModelFieldReference, isEnumFieldReference } from '@zenstackhq/sdk';
16-
import { ValidationAcceptor } from 'langium';
17-
import { findUpAst, getContainingDataModel, isCollectionPredicate } from '../../utils/ast-utils';
16+
import { ValidationAcceptor, streamAst } from 'langium';
17+
import { findUpAst, getContainingDataModel } from '../../utils/ast-utils';
1818
import { AstValidator } from '../types';
1919
import { typeAssignable } from './utils';
2020

@@ -32,8 +32,6 @@ export default class ExpressionValidator implements AstValidator<Expression> {
3232
'auth() cannot be resolved because no model marked wth "@@auth()" or named "User" is found',
3333
{ node: expr }
3434
);
35-
} else if (isCollectionPredicate(expr)) {
36-
accept('error', 'collection predicate can only be used on an array of model type', { node: expr });
3735
} else {
3836
accept('error', 'expression cannot be resolved', {
3937
node: expr,
@@ -221,6 +219,29 @@ export default class ExpressionValidator implements AstValidator<Expression> {
221219
}
222220
break;
223221
}
222+
223+
case '?':
224+
case '!':
225+
case '^':
226+
this.validateCollectionPredicate(expr, accept);
227+
break;
228+
}
229+
}
230+
231+
private validateCollectionPredicate(expr: BinaryExpr, accept: ValidationAcceptor) {
232+
if (!expr.$resolvedType) {
233+
accept('error', 'collection predicate can only be used on an array of model type', { node: expr });
234+
return;
235+
}
236+
237+
// TODO: revisit this when we implement lambda inside collection predicate
238+
const thisExpr = streamAst(expr).find(isThisExpr);
239+
if (thisExpr) {
240+
accept(
241+
'error',
242+
'using `this` in collection predicate is not supported. To compare entity identity, use id field comparison instead.',
243+
{ node: thisExpr }
244+
);
224245
}
225246
}
226247

packages/schema/tests/schema/validation/datamodel-validation.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,29 @@ describe('Data Model Validation Tests', () => {
7878
).toMatchObject(errorLike('Field of "Unsupported" type cannot be used in expressions'));
7979
});
8080

81+
it('Using `this` in collection predicate', async () => {
82+
expect(
83+
await safelyLoadModel(`
84+
${prelude}
85+
model User {
86+
id String @id
87+
members User[]
88+
@@allow('all', members?[this == auth()])
89+
}
90+
`)
91+
).toMatchObject(errorLike('using `this` in collection predicate is not supported'));
92+
93+
expect(
94+
await loadModel(`
95+
model User {
96+
id String @id
97+
members User[]
98+
@@allow('all', members?[id == auth().id])
99+
}
100+
`)
101+
).toBeTruthy();
102+
});
103+
81104
it('mix array and optional', async () => {
82105
expect(
83106
await safelyLoadModel(`

0 commit comments

Comments
 (0)