diff --git a/packages/schema/src/language-server/zmodel-linker.ts b/packages/schema/src/language-server/zmodel-linker.ts index ef97cf4b6..69fdf67c2 100644 --- a/packages/schema/src/language-server/zmodel-linker.ts +++ b/packages/schema/src/language-server/zmodel-linker.ts @@ -519,12 +519,17 @@ export class ZModelLinker extends DefaultLinker { private resolveDataModel(node: DataModel, document: LangiumDocument, extraScopes: ScopeProvider[]) { if (node.superTypes.length > 0) { - const providers = node.superTypes.map( - (superType) => (name: string) => superType.ref?.fields.find((f) => f.name === name) - ); - extraScopes = [...providers, ...extraScopes]; + const superTypeProviders: ScopeProvider[] = []; + // build scope providers for super types recursively with breadth-first search + const queue = node.superTypes.map((t) => t.ref!); + while (queue.length > 0) { + const superType = queue.shift()!; + const provider = (name: string) => superType.fields.find((f) => f.name === name); + superTypeProviders.push(provider); + queue.push(...superType.superTypes.map((t) => t.ref!)); + } + extraScopes = [...superTypeProviders, ...extraScopes]; } - return this.resolveDefault(node, document, extraScopes); } diff --git a/tests/integration/tests/regression/issue-971.test.ts b/tests/integration/tests/regression/issue-971.test.ts new file mode 100644 index 000000000..40990aa6a --- /dev/null +++ b/tests/integration/tests/regression/issue-971.test.ts @@ -0,0 +1,23 @@ +import { loadSchema } from '@zenstackhq/testtools'; + +describe('Regression: issue 971', () => { + it('regression', async () => { + await loadSchema( + ` + abstract model Level1 { + id String @id @default(cuid()) + URL String? + @@validate(URL != null, "URL must be provided") // works + } + abstract model Level2 extends Level1 { + @@validate(URL != null, "URL must be provided") // works + } + abstract model Level3 extends Level2 { + @@validate(URL != null, "URL must be provided") // doesn't work + } + model Foo extends Level3 { + } + ` + ); + }); +});