Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/files/BrsFile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4299,6 +4299,73 @@ describe('BrsFile', () => {
});
});

describe('union types', () => {

it('use dynamic for union of unlike primitives', async () => {
await testTranspile(`
function test1() as string or integer
return "hello"
end function

function test2() as double or float
return 1.23
end function

function test3() as integer or longinteger
return 5
end function

function test4() as integer or integer or integer
return 5
end function
`, `
function test1() as dynamic
return "hello"
end function

function test2() as dynamic
return 1.23
end function

function test3() as dynamic
return 5
end function

function test4() as integer
return 5
end function
`);
});

it('use object for union of object', async () => {
await testTranspile(`
function test1() as object
return 1
end function

function test2() as object or object
return 1
end function

function test3() as object or object or object
return 1
end function
`, `
function test1() as object
return 1
end function

function test2() as object
return 1
end function

function test3() as object
return 1
end function
`);
});
});

describe('callfunc operator', () => {
describe('transpile', () => {
it('does not produce diagnostics on plain roSGNode', () => {
Expand Down
47 changes: 47 additions & 0 deletions src/types/UnionType.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { isReferenceType, isTypePropertyReferenceType, isUnionType } from '../as
import { TypedFunctionType } from './TypedFunctionType';
import { SymbolTable } from '../SymbolTable';
import { ReferenceType } from './ReferenceType';
import { DoubleType } from './DoubleType';
import { LongIntegerType } from './LongIntegerType';
import { ObjectType } from './ObjectType';


describe('UnionType', () => {
Expand Down Expand Up @@ -190,4 +193,48 @@ describe('UnionType', () => {
expect((returnType as UnionType).types).includes(IntegerType.instance);
});
});

describe('toTypeString', () => {
it('should give single type when unions of same type', () => {
let ut = new UnionType([FloatType.instance, FloatType.instance]);
expect(ut.toTypeString()).to.eq('float');
ut = new UnionType([IntegerType.instance, IntegerType.instance, IntegerType.instance]);
expect(ut.toTypeString()).to.eq('integer');
ut = new UnionType([LongIntegerType.instance, LongIntegerType.instance]);
expect(ut.toTypeString()).to.eq('longinteger');
ut = new UnionType([DoubleType.instance, DoubleType.instance]);
expect(ut.toTypeString()).to.eq('double');
});

it('should give dynamic if types are not the same', () => {
let ut = new UnionType([FloatType.instance, IntegerType.instance]);
expect(ut.toTypeString()).to.eq('dynamic');
ut = new UnionType([FloatType.instance, IntegerType.instance, DoubleType.instance]);
expect(ut.toTypeString()).to.eq('dynamic');
ut = new UnionType([LongIntegerType.instance, IntegerType.instance]);
expect(ut.toTypeString()).to.eq('dynamic');
ut = new UnionType([DoubleType.instance, LongIntegerType.instance]);
expect(ut.toTypeString()).to.eq('dynamic');
});

it('should reduce object types to object', () => {
let ut = new UnionType([ObjectType.instance, ObjectType.instance]);
expect(ut.toTypeString()).to.eq('object');
ut = new UnionType([ObjectType.instance, ObjectType.instance, ObjectType.instance, ObjectType.instance]);
expect(ut.toTypeString()).to.eq('object');
});

it('should reduce to dynamic if non-reducible', () => {
let ut = new UnionType([FloatType.instance, StringType.instance]);
expect(ut.toTypeString()).to.eq('dynamic');
ut = new UnionType([FloatType.instance, IntegerType.instance, ObjectType.instance]);
expect(ut.toTypeString()).to.eq('dynamic');
ut = new UnionType([LongIntegerType.instance, new InterfaceType('test')]);
expect(ut.toTypeString()).to.eq('dynamic');
ut = new UnionType([ObjectType.instance, ObjectType.instance, StringType.instance, ObjectType.instance]);
expect(ut.toTypeString()).to.eq('dynamic');
ut = new UnionType([ObjectType.instance, new InterfaceType('test')]);
expect(ut.toTypeString()).to.eq('dynamic');
});
});
});
11 changes: 10 additions & 1 deletion src/types/UnionType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { GetTypeOptions, TypeCompatibilityData } from '../interfaces';
import { isDynamicType, isObjectType, isTypedFunctionType, isUnionType } from '../astUtils/reflection';
import { BscType } from './BscType';
import { ReferenceType } from './ReferenceType';
import { addAssociatedTypesTableAsSiblingToMemberTable, findTypeUnion, findTypeUnionDeepCheck, getUniqueType, isEnumTypeCompatible } from './helpers';
import { addAssociatedTypesTableAsSiblingToMemberTable, findTypeUnion, findTypeUnionDeepCheck, getAllTypesFromUnionType, getUniqueType, isEnumTypeCompatible } from './helpers';
import { BscTypeKind } from './BscTypeKind';
import type { TypeCacheEntry } from '../SymbolTable';
import { SymbolTable } from '../SymbolTable';
Expand Down Expand Up @@ -144,7 +144,16 @@ export class UnionType extends BscType {
toString(): string {
return joinTypesString(this.types);
}

/**
* Used for transpilation
*/
toTypeString(): string {
const uniqueTypeStrings = new Set<string>(getAllTypesFromUnionType(this).map(t => t.toTypeString()));

if (uniqueTypeStrings.size === 1) {
return uniqueTypeStrings.values().next().value;
}
return 'dynamic';
}

Expand Down
Loading