Skip to content

Commit

Permalink
Allow classes and native components in Typed Arrays (#919)
Browse files Browse the repository at this point in the history
  • Loading branch information
markwpearce authored Sep 25, 2023
1 parent 3d63bd4 commit b5db7d6
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 7 deletions.
62 changes: 62 additions & 0 deletions src/Scope.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { UnionType } from './types/UnionType';
import { isFunctionStatement, isNamespaceStatement } from './astUtils/reflection';
import { ArrayType } from './types/ArrayType';
import { AssociativeArrayType } from './types/AssociativeArrayType';
import { InterfaceType } from '.';
import { ComponentType } from './types/ComponentType';

describe('Scope', () => {
let sinon = sinonImport.createSandbox();
Expand Down Expand Up @@ -2940,6 +2942,66 @@ describe('Scope', () => {
expect((unionDefaultType as UnionType).types).to.include(StringType.instance);
expect((unionDefaultType as UnionType).types).to.include(IntegerType.instance);
});

it('should allow built in component types', () => {
let utilFile = program.setFile('source/util.bs', `
sub process(data as roAssociativeArray[])
for each datum in data
print datum
end for
end sub
`);
program.validate();
expectZeroDiagnostics(program);
const processFnScope = utilFile.getFunctionScopeAtPosition(util.createPosition(2, 24));
const symbolTable = processFnScope.symbolTable;
const opts = { flags: SymbolTypeFlag.runtime };
expectTypeToBe(symbolTable.getSymbolType('data', opts), ArrayType);
expectTypeToBe(symbolTable.getSymbolType('datum', opts), InterfaceType);
});

it('should allow class types', () => {
let utilFile = program.setFile('source/util.bs', `
sub process(data as Klass[])
for each datum in data
print datum.name
end for
end sub
class Klass
name as string
end class
`);
program.validate();
expectZeroDiagnostics(program);
const processFnScope = utilFile.getFunctionScopeAtPosition(util.createPosition(2, 24));
const symbolTable = processFnScope.symbolTable;
const opts = { flags: SymbolTypeFlag.runtime };
const dataType = symbolTable.getSymbolType('data', opts);
expectTypeToBe(dataType, ArrayType);
expectTypeToBe((dataType as ArrayType).defaultType, ClassType);
expect((dataType as ArrayType).defaultType.toString()).to.equal('Klass');
});

it('should allow component types', () => {
let utilFile = program.setFile('source/util.bs', `
sub process(labels as roSgNodeLabel[])
for each label in labels
print label.text
end for
end sub
`);
program.validate();
expectZeroDiagnostics(program);
const processFnScope = utilFile.getFunctionScopeAtPosition(util.createPosition(2, 24));
const symbolTable = processFnScope.symbolTable;
const opts = { flags: SymbolTypeFlag.runtime };
const dataType = symbolTable.getSymbolType('labels', opts);
expectTypeToBe(dataType, ArrayType);
expectTypeToBe((dataType as ArrayType).defaultType, ComponentType);
expect((dataType as ArrayType).defaultType.toString()).to.equal('roSGNodeLabel');
});
});

describe('callFunc invocations', () => {
Expand Down
5 changes: 4 additions & 1 deletion src/astUtils/reflection.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Body, AssignmentStatement, Block, ExpressionStatement, CommentStatement, ExitForStatement, ExitWhileStatement, FunctionStatement, IfStatement, IncrementStatement, PrintStatement, GotoStatement, LabelStatement, ReturnStatement, EndStatement, StopStatement, ForStatement, ForEachStatement, WhileStatement, DottedSetStatement, IndexedSetStatement, LibraryStatement, NamespaceStatement, ImportStatement, ClassStatement, InterfaceFieldStatement, InterfaceMethodStatement, InterfaceStatement, EnumStatement, EnumMemberStatement, TryCatchStatement, CatchStatement, ThrowStatement, MethodStatement, FieldStatement, ConstStatement, ContinueStatement } from '../parser/Statement';
import type { LiteralExpression, BinaryExpression, CallExpression, FunctionExpression, DottedGetExpression, XmlAttributeGetExpression, IndexedGetExpression, GroupingExpression, EscapedCharCodeLiteralExpression, ArrayLiteralExpression, AALiteralExpression, UnaryExpression, VariableExpression, SourceLiteralExpression, NewExpression, CallfuncExpression, TemplateStringQuasiExpression, TemplateStringExpression, TaggedTemplateStringExpression, AnnotationExpression, FunctionParameterExpression, AAMemberExpression, TypeExpression, TypeCastExpression } from '../parser/Expression';
import type { LiteralExpression, BinaryExpression, CallExpression, FunctionExpression, DottedGetExpression, XmlAttributeGetExpression, IndexedGetExpression, GroupingExpression, EscapedCharCodeLiteralExpression, ArrayLiteralExpression, AALiteralExpression, UnaryExpression, VariableExpression, SourceLiteralExpression, NewExpression, CallfuncExpression, TemplateStringQuasiExpression, TemplateStringExpression, TaggedTemplateStringExpression, AnnotationExpression, FunctionParameterExpression, AAMemberExpression, TypeExpression, TypeCastExpression, TypedArrayExpression } from '../parser/Expression';
import type { BrsFile } from '../files/BrsFile';
import type { XmlFile } from '../files/XmlFile';
import type { BscFile, File, TypedefProvider } from '../interfaces';
Expand Down Expand Up @@ -262,6 +262,9 @@ export function isTypeExpression(element: any): element is TypeExpression {
export function isTypeCastExpression(element: any): element is TypeCastExpression {
return element?.kind === AstNodeKind.TypeCastExpression;
}
export function isTypedArrayExpression(element: any): element is TypedArrayExpression {
return element?.kind === AstNodeKind.TypedArrayExpression;
}

// BscType reflection
export function isStringType(value: any): value is StringType {
Expand Down
10 changes: 6 additions & 4 deletions src/bscPlugin/validation/ScopeValidator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { URI } from 'vscode-uri';
import { isAssignmentStatement, isBinaryExpression, isBrsFile, isClassType, isDynamicType, isEnumMemberType, isEnumType, isFunctionExpression, isLiteralExpression, isNamespaceStatement, isObjectType, isPrimitiveType, isTypeExpression, isTypedFunctionType, isUnionType, isVariableExpression, isXmlScope } from '../../astUtils/reflection';
import { isAssignmentStatement, isBinaryExpression, isBrsFile, isClassType, isDynamicType, isEnumMemberType, isEnumType, isFunctionExpression, isLiteralExpression, isNamespaceStatement, isObjectType, isPrimitiveType, isTypeExpression, isTypedArrayExpression, isTypedFunctionType, isUnionType, isVariableExpression, isXmlScope } from '../../astUtils/reflection';
import { Cache } from '../../Cache';
import { DiagnosticMessages } from '../../DiagnosticMessages';
import type { BrsFile } from '../../files/BrsFile';
Expand Down Expand Up @@ -80,17 +80,19 @@ export class ScopeValidator {


private checkIfUsedAsTypeExpression(expression: AstNode): boolean {
//TODO: this is much faster than node.findAncestor(), but will not work for "complicated" type expressions like UnionTypes
//TODO: this is much faster than node.findAncestor(), but may need to be updated for "complicated" type expressions
if (isTypeExpression(expression) ||
isTypeExpression(expression.parent)) {
isTypeExpression(expression.parent) ||
isTypedArrayExpression(expression) ||
isTypedArrayExpression(expression.parent)) {
return true;
}
if (isBinaryExpression(expression.parent)) {
let currentExpr: AstNode = expression.parent;
while (isBinaryExpression(currentExpr) && currentExpr.operator.kind === TokenKind.Or) {
currentExpr = currentExpr.parent;
}
return isTypeExpression(currentExpr);
return isTypeExpression(currentExpr) || isTypedArrayExpression(currentExpr);
}
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion src/parser/AstNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,5 +237,5 @@ export enum AstNodeKind {
Block = 'Block',
TypeExpression = 'TypeExpression',
TypeCastExpression = 'TypeCastExpression',
ArrayTypeExpression = 'ArrayTypeExpression'
TypedArrayExpression = 'TypedArrayExpression'
}
2 changes: 1 addition & 1 deletion src/parser/Expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1819,7 +1819,7 @@ export class TypedArrayExpression extends Expression {
);
}

public readonly kind = AstNodeKind.ArrayTypeExpression;
public readonly kind = AstNodeKind.TypedArrayExpression;

public range: Range;

Expand Down

0 comments on commit b5db7d6

Please sign in to comment.