diff --git a/packages/schema/src/cli/cli-util.ts b/packages/schema/src/cli/cli-util.ts index a5bb81627..a0611fac7 100644 --- a/packages/schema/src/cli/cli-util.ts +++ b/packages/schema/src/cli/cli-util.ts @@ -105,11 +105,10 @@ export async function loadDocument(fileName: string, validateOnly = false): Prom const imported = mergeImportsDeclarations(langiumDocuments, model); // remove imported documents - await services.shared.workspace.DocumentBuilder.update( - [], - imported.map((m) => m.$document!.uri) - ); + imported.forEach((model) => langiumDocuments.deleteDocument(model.$document!.uri)); + services.shared.workspace.IndexManager.remove(imported.map((model) => model.$document!.uri)); + // extra validation after merging imported declarations validationAfterImportMerge(model); // merge fields and attributes from base models diff --git a/packages/schema/src/language-server/validator/utils.ts b/packages/schema/src/language-server/validator/utils.ts index 3dd5b537b..032bf9a5e 100644 --- a/packages/schema/src/language-server/validator/utils.ts +++ b/packages/schema/src/language-server/validator/utils.ts @@ -1,20 +1,12 @@ import { - AttributeArg, - AttributeParam, BuiltinType, - DataModelAttribute, - DataModelFieldAttribute, Expression, ExpressionType, - InternalAttribute, - isArrayExpr, isDataModelField, - isEnum, isMemberAccessExpr, - isReferenceExpr, isStringLiteral, } from '@zenstackhq/language/ast'; -import { isAuthInvocation, resolved } from '@zenstackhq/sdk'; +import { isAuthInvocation } from '@zenstackhq/sdk'; import { AstNode, ValidationAcceptor } from 'langium'; /** @@ -109,80 +101,6 @@ export function mapBuiltinTypeToExpressionType( } } -/** - * Determines if the given attribute argument is assignable to the given attribute parameter - */ -export function assignableToAttributeParam( - arg: AttributeArg, - param: AttributeParam, - attr: DataModelAttribute | DataModelFieldAttribute | InternalAttribute -): boolean { - const argResolvedType = arg.$resolvedType; - if (!argResolvedType) { - return false; - } - - let dstType = param.type.type; - let dstIsArray = param.type.array; - const dstRef = param.type.reference; - - if (dstType === 'Any' && !dstIsArray) { - return true; - } - - // destination is field reference or transitive field reference, check if - // argument is reference or array or reference - if (dstType === 'FieldReference' || dstType === 'TransitiveFieldReference') { - if (dstIsArray) { - return ( - isArrayExpr(arg.value) && - !arg.value.items.find((item) => !isReferenceExpr(item) || !isDataModelField(item.target.ref)) - ); - } else { - return isReferenceExpr(arg.value) && isDataModelField(arg.value.target.ref); - } - } - - if (isEnum(argResolvedType.decl)) { - // enum type - - let attrArgDeclType = dstRef?.ref; - if (dstType === 'ContextType' && isDataModelField(attr.$container) && attr.$container?.type?.reference) { - // attribute parameter type is ContextType, need to infer type from - // the attribute's container - attrArgDeclType = resolved(attr.$container.type.reference); - dstIsArray = attr.$container.type.array; - } - return attrArgDeclType === argResolvedType.decl && dstIsArray === argResolvedType.array; - } else if (dstType) { - // scalar type - - if (typeof argResolvedType?.decl !== 'string') { - // destination type is not a reference, so argument type must be a plain expression - return false; - } - - if (dstType === 'ContextType') { - // attribute parameter type is ContextType, need to infer type from - // the attribute's container - if (isDataModelField(attr.$container)) { - if (!attr.$container?.type?.type) { - return false; - } - dstType = mapBuiltinTypeToExpressionType(attr.$container.type.type); - dstIsArray = attr.$container.type.array; - } else { - dstType = 'Any'; - } - } - - return typeAssignable(dstType, argResolvedType.decl, arg.value) && dstIsArray === argResolvedType.array; - } else { - // reference type - return (dstRef?.ref === argResolvedType.decl || dstType === 'Any') && dstIsArray === argResolvedType.array; - } -} - export function isAuthOrAuthMemberAccess(expr: Expression): boolean { return isAuthInvocation(expr) || (isMemberAccessExpr(expr) && isAuthOrAuthMemberAccess(expr.operand)); } diff --git a/tests/regression/tests/issue-1849.test.ts b/tests/regression/tests/issue-1849.test.ts new file mode 100644 index 000000000..2362ac668 --- /dev/null +++ b/tests/regression/tests/issue-1849.test.ts @@ -0,0 +1,24 @@ +import { FILE_SPLITTER, loadSchema } from '@zenstackhq/testtools'; + +describe('issue 1849', () => { + it('regression', async () => { + await loadSchema( + `schema.zmodel + import './enum' + + model Post { + id Int @id + status Status @default(PUBLISHED) + } + + ${FILE_SPLITTER}enum.zmodel + + enum Status { + PENDING + PUBLISHED + } + `, + { provider: 'postgresql', pushDb: false } + ); + }); +});