Skip to content

Commit ad07053

Browse files
authored
fix(cli): bogus validation error when merging imported enums (#1861)
1 parent 85a8d5d commit ad07053

File tree

3 files changed

+28
-87
lines changed

3 files changed

+28
-87
lines changed

packages/schema/src/cli/cli-util.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,10 @@ export async function loadDocument(fileName: string, validateOnly = false): Prom
105105
const imported = mergeImportsDeclarations(langiumDocuments, model);
106106

107107
// remove imported documents
108-
await services.shared.workspace.DocumentBuilder.update(
109-
[],
110-
imported.map((m) => m.$document!.uri)
111-
);
108+
imported.forEach((model) => langiumDocuments.deleteDocument(model.$document!.uri));
109+
services.shared.workspace.IndexManager.remove(imported.map((model) => model.$document!.uri));
112110

111+
// extra validation after merging imported declarations
113112
validationAfterImportMerge(model);
114113

115114
// merge fields and attributes from base models

packages/schema/src/language-server/validator/utils.ts

Lines changed: 1 addition & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
import {
2-
AttributeArg,
3-
AttributeParam,
42
BuiltinType,
5-
DataModelAttribute,
6-
DataModelFieldAttribute,
73
Expression,
84
ExpressionType,
9-
InternalAttribute,
10-
isArrayExpr,
115
isDataModelField,
12-
isEnum,
136
isMemberAccessExpr,
14-
isReferenceExpr,
157
isStringLiteral,
168
} from '@zenstackhq/language/ast';
17-
import { isAuthInvocation, resolved } from '@zenstackhq/sdk';
9+
import { isAuthInvocation } from '@zenstackhq/sdk';
1810
import { AstNode, ValidationAcceptor } from 'langium';
1911

2012
/**
@@ -109,80 +101,6 @@ export function mapBuiltinTypeToExpressionType(
109101
}
110102
}
111103

112-
/**
113-
* Determines if the given attribute argument is assignable to the given attribute parameter
114-
*/
115-
export function assignableToAttributeParam(
116-
arg: AttributeArg,
117-
param: AttributeParam,
118-
attr: DataModelAttribute | DataModelFieldAttribute | InternalAttribute
119-
): boolean {
120-
const argResolvedType = arg.$resolvedType;
121-
if (!argResolvedType) {
122-
return false;
123-
}
124-
125-
let dstType = param.type.type;
126-
let dstIsArray = param.type.array;
127-
const dstRef = param.type.reference;
128-
129-
if (dstType === 'Any' && !dstIsArray) {
130-
return true;
131-
}
132-
133-
// destination is field reference or transitive field reference, check if
134-
// argument is reference or array or reference
135-
if (dstType === 'FieldReference' || dstType === 'TransitiveFieldReference') {
136-
if (dstIsArray) {
137-
return (
138-
isArrayExpr(arg.value) &&
139-
!arg.value.items.find((item) => !isReferenceExpr(item) || !isDataModelField(item.target.ref))
140-
);
141-
} else {
142-
return isReferenceExpr(arg.value) && isDataModelField(arg.value.target.ref);
143-
}
144-
}
145-
146-
if (isEnum(argResolvedType.decl)) {
147-
// enum type
148-
149-
let attrArgDeclType = dstRef?.ref;
150-
if (dstType === 'ContextType' && isDataModelField(attr.$container) && attr.$container?.type?.reference) {
151-
// attribute parameter type is ContextType, need to infer type from
152-
// the attribute's container
153-
attrArgDeclType = resolved(attr.$container.type.reference);
154-
dstIsArray = attr.$container.type.array;
155-
}
156-
return attrArgDeclType === argResolvedType.decl && dstIsArray === argResolvedType.array;
157-
} else if (dstType) {
158-
// scalar type
159-
160-
if (typeof argResolvedType?.decl !== 'string') {
161-
// destination type is not a reference, so argument type must be a plain expression
162-
return false;
163-
}
164-
165-
if (dstType === 'ContextType') {
166-
// attribute parameter type is ContextType, need to infer type from
167-
// the attribute's container
168-
if (isDataModelField(attr.$container)) {
169-
if (!attr.$container?.type?.type) {
170-
return false;
171-
}
172-
dstType = mapBuiltinTypeToExpressionType(attr.$container.type.type);
173-
dstIsArray = attr.$container.type.array;
174-
} else {
175-
dstType = 'Any';
176-
}
177-
}
178-
179-
return typeAssignable(dstType, argResolvedType.decl, arg.value) && dstIsArray === argResolvedType.array;
180-
} else {
181-
// reference type
182-
return (dstRef?.ref === argResolvedType.decl || dstType === 'Any') && dstIsArray === argResolvedType.array;
183-
}
184-
}
185-
186104
export function isAuthOrAuthMemberAccess(expr: Expression): boolean {
187105
return isAuthInvocation(expr) || (isMemberAccessExpr(expr) && isAuthOrAuthMemberAccess(expr.operand));
188106
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { FILE_SPLITTER, loadSchema } from '@zenstackhq/testtools';
2+
3+
describe('issue 1849', () => {
4+
it('regression', async () => {
5+
await loadSchema(
6+
`schema.zmodel
7+
import './enum'
8+
9+
model Post {
10+
id Int @id
11+
status Status @default(PUBLISHED)
12+
}
13+
14+
${FILE_SPLITTER}enum.zmodel
15+
16+
enum Status {
17+
PENDING
18+
PUBLISHED
19+
}
20+
`,
21+
{ provider: 'postgresql', pushDb: false }
22+
);
23+
});
24+
});

0 commit comments

Comments
 (0)