Skip to content

Commit

Permalink
Makes assignments of invalid act be typed as dynamic
Browse files Browse the repository at this point in the history
  • Loading branch information
markwpearce committed Jan 3, 2025
1 parent c2305b2 commit 72847dd
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 5 deletions.
4 changes: 2 additions & 2 deletions src/bscPlugin/validation/BrsFileValidator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isAliasStatement, isArrayType, isBlock, isBody, isClassStatement, isConditionalCompileConstStatement, isConditionalCompileErrorStatement, isConditionalCompileStatement, isConstStatement, isDottedGetExpression, isDottedSetStatement, isEnumStatement, isForEachStatement, isForStatement, isFunctionExpression, isFunctionStatement, isImportStatement, isIndexedGetExpression, isIndexedSetStatement, isInterfaceStatement, isInvalidType, isLibraryStatement, isLiteralExpression, isMethodStatement, isNamespaceStatement, isTypecastExpression, isTypecastStatement, isUnaryExpression, isVariableExpression, isWhileStatement } from '../../astUtils/reflection';
import { isAliasStatement, isArrayType, isBlock, isBody, isClassStatement, isConditionalCompileConstStatement, isConditionalCompileErrorStatement, isConditionalCompileStatement, isConstStatement, isDottedGetExpression, isDottedSetStatement, isEnumStatement, isForEachStatement, isForStatement, isFunctionExpression, isFunctionStatement, isImportStatement, isIndexedGetExpression, isIndexedSetStatement, isInterfaceStatement, isInvalidType, isLibraryStatement, isLiteralExpression, isMethodStatement, isNamespaceStatement, isTypecastExpression, isTypecastStatement, isUnaryExpression, isVariableExpression, isVoidType, isWhileStatement } from '../../astUtils/reflection';
import { createVisitor, WalkMode } from '../../astUtils/visitors';
import { DiagnosticMessages } from '../../DiagnosticMessages';
import type { BrsFile } from '../../files/BrsFile';
Expand Down Expand Up @@ -109,7 +109,7 @@ export class BrsFileValidator {
const data: ExtraSymbolData = {};
//register this variable
let nodeType = node.getType({ flags: SymbolTypeFlag.runtime, data: data });
if (isInvalidType(nodeType)) {
if (isInvalidType(nodeType) || isVoidType(nodeType)) {
nodeType = DynamicType.instance;
}
node.parent.getSymbolTable()?.addSymbol(node.tokens.name.text, { definingNode: node, isInstance: true, isFromDocComment: data.isFromDocComment }, nodeType, SymbolTypeFlag.runtime);
Expand Down
64 changes: 64 additions & 0 deletions src/bscPlugin/validation/ScopeValidator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2189,6 +2189,70 @@ describe('ScopeValidator', () => {
expectZeroDiagnostics(program);
});

it('allows access of properties of union with invalid', () => {
program.setFile<BrsFile>('source/main.bs', `
sub test()
channel = invalid
if true
channel = {
height: 123
}
end if
height = 0
if channel <> invalid then
height += channel.height
end if
end sub
`);
program.validate();
expectZeroDiagnostics(program);

});

it('sets default arg of invalid as dynamic', () => {
program.setFile<BrsFile>('source/main.bs', `
sub test(channel = invalid)
if true
channel = {
height: 123
}
end if
height = 0
if channel <> invalid then
height += channel.height
end if
end sub
`);
program.validate();
expectZeroDiagnostics(program);

});

it('sets assignment of function returning invalid as dynamic', () => {
program.setFile<BrsFile>('source/main.bs', `
sub test()
channel = noReturn()
if true
channel = {
height: 123
}
end if
height = 0
if channel <> invalid then
height += channel.height
end if
end sub
sub noReturn()
print "hello"
end sub
`);
program.validate();
expectZeroDiagnostics(program);
});
});

describe('itemCannotBeUsedAsVariable', () => {
Expand Down
7 changes: 6 additions & 1 deletion src/types/VoidType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { BscType } from './BscType';
import { BscTypeKind } from './BscTypeKind';
import { isUnionTypeCompatible } from './helpers';
import { BuiltInInterfaceAdder } from './BuiltInInterfaceAdder';
import type { TypeCompatibilityData } from '../interfaces';
import type { GetTypeOptions, TypeCompatibilityData } from '../interfaces';
import { DynamicType } from './DynamicType';

export class VoidType extends BscType {
constructor(
Expand Down Expand Up @@ -36,6 +37,10 @@ export class VoidType extends BscType {
public isEqual(targetType: BscType) {
return isVoidType(targetType);
}

getMemberType(memberName: string, options: GetTypeOptions) {
return DynamicType.instance;
}
}

BuiltInInterfaceAdder.primitiveTypeInstanceCache.set('void', VoidType.instance);
4 changes: 2 additions & 2 deletions src/types/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { TypeCompatibilityData } from '../interfaces';
import { isAnyReferenceType, isDynamicType, isEnumMemberType, isEnumType, isInheritableType, isInterfaceType, isReferenceType, isUnionType } from '../astUtils/reflection';
import { isAnyReferenceType, isDynamicType, isEnumMemberType, isEnumType, isInheritableType, isInterfaceType, isReferenceType, isUnionType, isVoidType } from '../astUtils/reflection';
import type { BscType } from './BscType';
import type { UnionType } from './UnionType';

Expand Down Expand Up @@ -126,7 +126,7 @@ export function getUniqueType(types: BscType[], unionTypeFactory: (types: BscTyp
if (!types || types.length === 0) {
return undefined;
}
const dynType = types.find((x) => !isAnyReferenceType(x) && isDynamicType(x));
const dynType = types.find((x) => !isAnyReferenceType(x) && (isDynamicType(x) || isVoidType(x)));
if (dynType) {
return dynType;
}
Expand Down

0 comments on commit 72847dd

Please sign in to comment.