@@ -7,13 +7,7 @@ import {
77 isEnum ,
88 isStringLiteral ,
99} from '@zenstackhq/language/ast' ;
10- import {
11- getLiteral ,
12- getModelFieldsWithBases ,
13- getModelIdFields ,
14- getModelUniqueFields ,
15- isDelegateModel ,
16- } from '@zenstackhq/sdk' ;
10+ import { getModelFieldsWithBases , getModelIdFields , getModelUniqueFields , isDelegateModel } from '@zenstackhq/sdk' ;
1711import { AstNode , DiagnosticInfo , ValidationAcceptor , getDocument } from 'langium' ;
1812import { findUpInheritance } from '../../utils/ast-utils' ;
1913import { IssueCodes , SCALAR_TYPES } from '../constants' ;
@@ -147,15 +141,15 @@ export default class DataModelValidator implements AstValidator<DataModel> {
147141 }
148142 }
149143
144+ if ( ! fields && ! references ) {
145+ return { attr : relAttr , name, fields, references, valid : true } ;
146+ }
147+
150148 if ( ! fields || ! references ) {
151- if ( this . isSelfRelation ( field , name ) ) {
152- // self relations are partial
153- // https://www.prisma.io/docs/concepts/components/prisma-schema/relations/self-relations
154- } else {
155- if ( accept ) {
156- accept ( 'error' , `Both "fields" and "references" must be provided` , { node : relAttr } ) ;
157- }
149+ if ( accept ) {
150+ accept ( 'error' , `"fields" and "references" must be provided together` , { node : relAttr } ) ;
158151 }
152+ // }
159153 } else {
160154 // validate "fields" and "references" typing consistency
161155 if ( fields . length !== references . length ) {
@@ -203,34 +197,8 @@ export default class DataModelValidator implements AstValidator<DataModel> {
203197 return { attr : relAttr , name, fields, references, valid } ;
204198 }
205199
206- private isSelfRelation ( field : DataModelField , relationName ?: string ) {
207- if ( field . type . reference ?. ref === field . $container ) {
208- // field directly references back to its type
209- return true ;
210- }
211-
212- if ( relationName ) {
213- // field's relation points to another type, and that type's opposite relation field
214- // points back
215- const oppositeModel = field . type . reference ?. ref as DataModel ;
216- if ( oppositeModel ) {
217- const oppositeModelFields = getModelFieldsWithBases ( oppositeModel ) ;
218- for ( const oppositeField of oppositeModelFields ) {
219- // find the opposite relation with the matching name
220- const relAttr = oppositeField . attributes . find ( ( a ) => a . decl . ref ?. name === '@relation' ) ;
221- if ( relAttr ) {
222- const relNameExpr = relAttr . args . find ( ( a ) => ! a . name || a . name === 'name' ) ;
223- const relName = getLiteral < string > ( relNameExpr ?. value ) ;
224- if ( relName === relationName && oppositeField . type . reference ?. ref === field . $container ) {
225- // found an opposite relation field that points back to this field's type
226- return true ;
227- }
228- }
229- }
230- }
231- }
232-
233- return false ;
200+ private isSelfRelation ( field : DataModelField ) {
201+ return field . type . reference ?. ref === field . $container ;
234202 }
235203
236204 private validateRelationField ( contextModel : DataModel , field : DataModelField , accept : ValidationAcceptor ) {
@@ -330,10 +298,10 @@ export default class DataModelValidator implements AstValidator<DataModel> {
330298 // if both the field is array, then it's an implicit many-to-many relation
331299 if ( ! ( field . type . array && oppositeField . type . array ) ) {
332300 [ field , oppositeField ] . forEach ( ( f ) => {
333- if ( ! this . isSelfRelation ( f , thisRelation . name ) ) {
301+ if ( ! this . isSelfRelation ( f ) ) {
334302 accept (
335303 'error' ,
336- 'Field for one side of relation must carry @relation attribute with both "fields" and "references" fields ' ,
304+ 'Field for one side of relation must carry @relation attribute with both "fields" and "references"' ,
337305 { node : f }
338306 ) ;
339307 }
0 commit comments