@@ -30,7 +30,6 @@ import {
3030 UnaryExpr ,
3131 isAliasDecl ,
3232 isArrayExpr ,
33- isBinaryExpr ,
3433 isBooleanLiteral ,
3534 isDataModel ,
3635 isDataModelField ,
@@ -41,7 +40,6 @@ import {
4140 isReferenceExpr ,
4241 isStringLiteral ,
4342 isTypeDefField ,
44- isUnaryExpr ,
4543} from '@zenstackhq/language/ast' ;
4644import { getAuthDecl , getModelFieldsWithBases , isAuthInvocation , isFutureExpr } from '@zenstackhq/sdk' ;
4745import {
@@ -171,7 +169,6 @@ export class ZModelLinker extends DefaultLinker {
171169 break ;
172170
173171 case MemberAccessExpr :
174- // TODO: check from alias ?
175172 this . resolveMemberAccess ( node as MemberAccessExpr , document , extraScopes ) ;
176173 break ;
177174
@@ -207,6 +204,10 @@ export class ZModelLinker extends DefaultLinker {
207204 this . resolveDataModelField ( node as DataModelField , document , extraScopes ) ;
208205 break ;
209206
207+ case AliasDecl :
208+ // Don't resolve alias declarations - they will be resolved when used
209+ break ;
210+
210211 default :
211212 this . resolveDefault ( node , document , extraScopes ) ;
212213 break ;
@@ -267,18 +268,13 @@ export class ZModelLinker extends DefaultLinker {
267268 }
268269
269270 private resolveReference ( node : ReferenceExpr , document : LangiumDocument < AstNode > , extraScopes : ScopeProvider [ ] ) {
270- // If the reference comes from an alias, we resolve it against the first matching data model
271- if ( getContainerOfType ( node , isAliasDecl ) ) {
272- this . resolveAliasExpr ( node as ReferenceExpr , document ) ;
273- }
274271 this . resolveDefault ( node , document , extraScopes ) ;
275272
276273 if ( node . target . ref ) {
277274 // resolve type
278275 if ( node . target . ref . $type === EnumField ) {
279276 this . resolveToBuiltinTypeOrDecl ( node , node . target . ref . $container ) ;
280277 } else {
281- // TODO: if the reference is from an alias, we should resolve it against the first matching data model
282278 this . resolveToDeclaredType ( node , ( node . target . ref as DataModelField | FunctionParam ) . type ) ;
283279 }
284280 }
@@ -329,6 +325,18 @@ export class ZModelLinker extends DefaultLinker {
329325
330326 if ( matchingAlias ) {
331327 node . $resolvedType = { decl : matchingAlias , nullable : false } ;
328+
329+ // Resolve the alias expression in the context of the containing model
330+ const containingModel = getContainingDataModel ( node ) ;
331+ if ( containingModel && matchingAlias . expression ) {
332+ const scopeProvider = ( name : string ) =>
333+ getModelFieldsWithBases ( containingModel ) . find ( ( field ) => field . name === name ) ;
334+
335+ // Ensure the alias expression is fully resolved in the current context
336+ this . resolveExpressionInContext ( matchingAlias . expression , document , containingModel , [
337+ scopeProvider ,
338+ ] ) ;
339+ }
332340 }
333341 } else {
334342 this . resolveToDeclaredType ( node , ( funcDecl as FunctionDecl ) . returnType ) ;
@@ -464,44 +472,14 @@ export class ZModelLinker extends DefaultLinker {
464472 node . $resolvedType = node . value . $resolvedType ;
465473 }
466474
467- private resolveAliasExpr ( node : AstNode , document : LangiumDocument < AstNode > ) {
468- const container = getContainerOfType ( node , isAliasDecl ) ;
469- if ( ! container ) {
470- return ;
471- }
472- const model = getContainerOfType ( node , isModel ) ;
473- const models = model ?. declarations . filter ( isDataModel ) ?? [ ] ;
474- // Find the first model that has the alias reference as a field
475- const matchingModel = models . find ( ( model ) => model . fields . some ( ( f ) => f . name === node . $cstNode ?. text ) ) ;
476- if ( ! matchingModel ) {
477- return ;
478- }
479-
480- const scopeProvider = ( name : string ) =>
481- getModelFieldsWithBases ( matchingModel ) . find ( ( field ) => field . name === name ) ;
482-
483- const visitExpr = ( node : Expression ) => {
484- if ( isReferenceExpr ( node ) ) {
485- // enums in alias expressions are already resolved
486- if ( isEnum ( node . target . ref ?. $container ) ) {
487- return ;
488- }
489-
490- const resolved = this . resolveFromScopeProviders ( node , 'target' , document , [ scopeProvider ] ) ;
491- if ( resolved ) {
492- this . resolveToDeclaredType ( node , ( resolved as DataModelField ) . type ) ;
493- } else {
494- this . unresolvableRefExpr ( node ) ;
495- }
496- } else if ( isBinaryExpr ( node ) ) {
497- visitExpr ( node . left ) ;
498- visitExpr ( node . right ) ;
499- } else if ( isUnaryExpr ( node ) ) {
500- visitExpr ( node . operand ) ;
501- }
502- } ;
503-
504- visitExpr ( container . expression ) ;
475+ private resolveExpressionInContext (
476+ expr : Expression ,
477+ document : LangiumDocument < AstNode > ,
478+ contextModel : DataModel ,
479+ extraScopes : ScopeProvider [ ]
480+ ) {
481+ // Resolve the expression with the model context scope
482+ this . resolve ( expr , document , extraScopes ) ;
505483 }
506484
507485 private unresolvableRefExpr ( item : ReferenceExpr ) {
0 commit comments