Skip to content

Commit

Permalink
Merge 066cdbb into 9b81e77
Browse files Browse the repository at this point in the history
  • Loading branch information
markwpearce committed Jun 7, 2024
2 parents 9b81e77 + 066cdbb commit eb33609
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/DiagnosticMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,11 @@ export const defaultMaximumTruncationLength = 160;

export function typeCompatibilityMessage(actualTypeString: string, expectedTypeString: string, data: TypeCompatibilityData) {
let message = '';
actualTypeString = data?.actualType?.toString() ?? actualTypeString;
expectedTypeString = data?.expectedType?.toString() ?? expectedTypeString;

if (data?.missingFields?.length > 0) {
message = `\n Type '${actualTypeString}' is missing the following members: ` + util.truncate({
message = `\n Type '${actualTypeString}' is missing the following members of type '${expectedTypeString}': ` + util.truncate({
leadingText: ``,
trailingText: '',
itemSeparator: ', ',
Expand Down
87 changes: 87 additions & 0 deletions src/bscPlugin/validation/ScopeValidator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2397,6 +2397,93 @@ describe('ScopeValidator', () => {
program.validate();
expectZeroDiagnostics(program);
});


it('allows assigning to rect2d fields', () => {
program.setFile('components/widget.xml', trim`
<?xml version="1.0" encoding="utf-8" ?>
<component name="Widget" extends="Group">
<interface>
<field id="rectangle" type="rect2d" />
</interface>
</component>
`);

program.setFile('source/util.bs', `
sub test()
node = createObject("roSGNode", "Widget")
myRectangle = {x: 0, y: 0, width: 100, height: 100}
node.rectangle = myRectangle
end sub
`);
program.validate();
expectZeroDiagnostics(program);
});

it('allows assigning to rect2dArray fields', () => {
program.setFile('components/widget.xml', trim`
<?xml version="1.0" encoding="utf-8" ?>
<component name="Widget" extends="Group">
<interface>
<field id="rectangles" type="rect2dArray" />
</interface>
</component>
`);

program.setFile('source/util.bs', `
sub test()
node = createObject("roSGNode", "Widget")
myRectangles = [
{x: 0, y: 0, width: 100, height: 100},
{x: 100, y: 100, width: 200, height: 200},
]
node.rectangles = myRectangles
end sub
`);
program.validate();
expectZeroDiagnostics(program);
});

it('allows assigning to roSGNodeTargetSet.targetRects fields', () => {
program.setFile('source/util.bs', `
sub test()
targetSet = createObject("roSGNode", "TargetSet")
targets = [
{x: 0, y: 0, width: 100, height: 100},
{x: 100, y: 100, width: 200, height: 200},
]
targetSet.targetRects = targets
end sub
`);
program.validate();
expectZeroDiagnostics(program);
});

it('has diagnostic if invalid data is assigned to roSGNodeTargetSet.targetRects fields', () => {
program.setFile('source/util.bs', `
sub test()
targetSet = createObject("roSGNode", "TargetSet")
targets = ["hello", "world"]
targetSet.targetRects = targets
end sub
`);

// make up the assignability data for the diagnostic:
const rectType = new AssociativeArrayType();
rectType.addMember('height', null, FloatType.instance, SymbolTypeFlag.runtime);
rectType.addMember('width', null, FloatType.instance, SymbolTypeFlag.runtime);
rectType.addMember('x', null, FloatType.instance, SymbolTypeFlag.runtime);
rectType.addMember('y', null, FloatType.instance, SymbolTypeFlag.runtime);
const typeCompatData = {} as TypeCompatibilityData;
rectType.isTypeCompatible(StringType.instance, typeCompatData);
typeCompatData.actualType = StringType.instance;
typeCompatData.expectedType = rectType;

program.validate();
expectDiagnostics(program, [
DiagnosticMessages.assignmentTypeMismatch('Array<string>', 'Array<roAssociativeArray>', typeCompatData).message
]);
});
});
});

Expand Down
3 changes: 3 additions & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,9 @@ export interface TypeCompatibilityData {
missingFields?: { name: string; expectedType: BscType }[];
fieldMismatches?: { name: string; expectedType: BscType; actualType: BscType }[];
depth?: number;
// override for diagnostic message - useful for Arrays with different default types
actualType?: BscType;
expectedType?: BscType;
}

export interface NamespaceContainer {
Expand Down
7 changes: 6 additions & 1 deletion src/types/ArrayType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ export class ArrayType extends BscType {
} else if (isUnionTypeCompatible(this, targetType)) {
return true;
} else if (isArrayType(targetType)) {
return this.defaultType.isTypeCompatible(targetType.defaultType, data);
const compatible = this.defaultType.isTypeCompatible(targetType.defaultType, data);
if (data) {
data.actualType = targetType.defaultType;
data.expectedType = this.defaultType;
}
return compatible;
} else if (this.checkCompatibilityBasedOnMembers(targetType, SymbolTypeFlag.runtime, data)) {
return true;
}
Expand Down
3 changes: 3 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,9 @@ export class Util {
// remove "'" in "float's", etc.
arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
}
if (arrayOfTypeName === 'rectangle') {
arrayOfTypeName = 'rect2d';
}
let arrayType = this.getNodeFieldType(arrayOfTypeName, lookupTable);
return new ArrayType(arrayType);
} else if (typeDescriptorLower.startsWith('option ')) {
Expand Down

0 comments on commit eb33609

Please sign in to comment.