diff --git a/packages/schema/src/language-server/zmodel-linker.ts b/packages/schema/src/language-server/zmodel-linker.ts index ba6396695..75c191e8f 100644 --- a/packages/schema/src/language-server/zmodel-linker.ts +++ b/packages/schema/src/language-server/zmodel-linker.ts @@ -92,9 +92,10 @@ export class ZModelLinker extends DefaultLinker { container: AstNode, property: string, document: LangiumDocument, - extraScopes: ScopeProvider[] + extraScopes: ScopeProvider[], + onlyFromExtraScopes = false ) { - if (!this.resolveFromScopeProviders(container, property, document, extraScopes)) { + if (!this.resolveFromScopeProviders(container, property, document, extraScopes) && !onlyFromExtraScopes) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const reference: Reference = (container as any)[property]; this.doLink({ reference, container, property }, document); @@ -327,12 +328,11 @@ export class ZModelLinker extends DefaultLinker { if (operandResolved && !operandResolved.array && isDataModel(operandResolved.decl)) { const modelDecl = operandResolved.decl as DataModel; const provider = (name: string) => modelDecl.$resolvedFields.find((f) => f.name === name); - extraScopes = [provider, ...extraScopes]; - } - - this.linkReference(node, 'member', document, extraScopes); - if (node.member.ref) { - this.resolveToDeclaredType(node, node.member.ref.type); + // member access is resolved only in the context of the operand type + this.linkReference(node, 'member', document, [provider], true); + if (node.member.ref) { + this.resolveToDeclaredType(node, node.member.ref.type); + } } } diff --git a/packages/schema/tests/schema/validation/attribute-validation.test.ts b/packages/schema/tests/schema/validation/attribute-validation.test.ts index 5c638a841..6f81dabc2 100644 --- a/packages/schema/tests/schema/validation/attribute-validation.test.ts +++ b/packages/schema/tests/schema/validation/attribute-validation.test.ts @@ -1017,7 +1017,7 @@ describe('Attribute tests', () => { @@allow('all', auth().email != null) } `) - ).toContain(`Could not resolve reference to DataModelField named 'email'.`); + ).toContain(`expression cannot be resolved`); }); it('collection predicate expression check', async () => { diff --git a/tests/integration/tests/regression/issue-756.test.ts b/tests/integration/tests/regression/issue-756.test.ts new file mode 100644 index 000000000..b10e60af2 --- /dev/null +++ b/tests/integration/tests/regression/issue-756.test.ts @@ -0,0 +1,33 @@ +import { loadModel, loadModelWithError } from '@zenstackhq/testtools'; + +describe('Regression: issue 756', () => { + it('regression', async () => { + expect( + await loadModelWithError( + ` + generator client { + provider = "prisma-client-js" + } + + datasource db { + provider = "postgresql" + url = env("DATABASE_URL") + } + + model User { + id Int @id @default(autoincrement()) + email Int + posts Post[] + } + + model Post { + id Int @id @default(autoincrement()) + author User? @relation(fields: [authorId], references: [id]) + authorId Int + @@allow('all', auth().posts.authorId == authorId) + } + ` + ) + ).toContain('expression cannot be resolved'); + }); +});