Skip to content

Commit

Permalink
Respect declared type of data type rules (#1478)
Browse files Browse the repository at this point in the history
  • Loading branch information
msujew authored Jun 10, 2024
1 parent 1ed839a commit c8e01a2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
13 changes: 12 additions & 1 deletion packages/langium/src/grammar/type-system/type-collector/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,18 @@ function isTypeAssignableInternal(from: PropertyType | undefined, to: PropertyTy
result = isArrayType(to) && isTypeAssignableInternal(from.elementType, to.elementType, visited);
} else if (isValueType(from)) {
if (isUnionType(from.value)) {
result = isTypeAssignableInternal(from.value.type, to, visited);
if (from.value.dataType) {
// We can test the primitive data type directly
// This potentially skips a expensive recursive call
// This also helps in case the computed internal data type does not fit the declared data type
const primitiveType: PrimitiveType = {
primitive: from.value.dataType
};
result = isTypeAssignableInternal(primitiveType, to, visited);
}
if (!result) {
result = isTypeAssignableInternal(from.value.type, to, visited);
}
} else if (!isValueType(to)) {
result = false;
} else if (isUnionType(to.value)) {
Expand Down
24 changes: 24 additions & 0 deletions packages/langium/test/grammar/type-system/type-validator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,30 @@ describe('validate declared types', () => {
property: 'name'
});
});

test('Can assign a data type rule to a property with its base type #1', async () => {
const validationResult = await validate(`
interface RuleType { prop : string };
Rule returns RuleType: prop = MyDataType;
// The computed type for 'MyDataType' is INT, but its declared is string
// The type system should respect the declared type
MyDataType returns string: INT;
terminal INT returns number: /[0-9]+/;
`);
expectNoIssues(validationResult);
});

test('Can assign a data type rule to a property with its base type #2', async () => {
const validationResult = await validate(`
interface RuleType { prop : number };
Rule returns RuleType: prop = MyDataType;
// The computed type for 'MyDataType' is INT, but its declared is number
// The type system should respect the declared type
MyDataType returns number: INT;
terminal INT returns string: /[0-9]+/;
`);
expectNoIssues(validationResult);
});
});

describe('validate declared default value properties', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('WorkerThreadAsyncParser', () => {
expect(parseResult.value.name).toBe('Test');
expect(GrammarUtils.findNodeForProperty(parseResult.value.$cstNode, 'name')!.offset).toBe(8);
}
});
}, 20000);

test('async parsing can be cancelled', async () => {
const services = getServices();
Expand Down

0 comments on commit c8e01a2

Please sign in to comment.