Skip to content

Commit

Permalink
Does not validate unknown members of a component in BrightScript mode
Browse files Browse the repository at this point in the history
  • Loading branch information
markwpearce committed Oct 19, 2024
1 parent 65d0479 commit 7b91eb0
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
37 changes: 37 additions & 0 deletions src/bscPlugin/validation/ScopeValidator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1836,6 +1836,43 @@ describe('ScopeValidator', () => {
expectZeroDiagnostics(program);
});

it('does not have diagnostic when accessing unknown member of node in Brightscript mode', () => {
program.setFile('source/main.brs', `
' @param {roSGNode} node
function testNodeMember(node)
x = node.whatever
return x
end function
`);
program.validate();
expectZeroDiagnostics(program);
});

it('does not have diagnostic when accessing unknown member of contentnode in Brightscript mode', () => {
program.setFile('source/main.brs', `
' @param {roSgNodeCOntentNode} node
function testNodeMember(node)
x = node.whatever
return x
end function
`);
program.validate();
expectZeroDiagnostics(program);
});

it('does not have diagnostic when accessing unknown member of created node in Brightscript mode', () => {
program.setFile('source/main.brs', `
' @param {string} nodeSubtype
function testNodeMember(nodeSubtype)
x = createObject("roSgNode",nodeSubtype)
x.whatever = true
return x
end function
`);
program.validate();
expectZeroDiagnostics(program);
});

it('allows anything on m in an anonymous function', () => {
program.setFile('source/main.bs', `
function test()
Expand Down
9 changes: 8 additions & 1 deletion src/bscPlugin/validation/ScopeValidator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DiagnosticTag, type Range } from 'vscode-languageserver';
import { isAliasStatement, isAssignmentStatement, isAssociativeArrayType, isBinaryExpression, isBooleanType, isBrsFile, isCallExpression, isCallableType, isClassStatement, isClassType, isComponentType, isDottedGetExpression, isDynamicType, isEnumMemberType, isEnumType, isFunctionExpression, isFunctionParameterExpression, isLiteralExpression, isNamespaceStatement, isNamespaceType, isNewExpression, isNumberType, isObjectType, isPrimitiveType, isReferenceType, isReturnStatement, isStringType, isTypedFunctionType, isUnionType, isVariableExpression, isVoidType, isXmlScope } from '../../astUtils/reflection';
import { isAliasStatement, isAssignmentStatement, isAssociativeArrayType, isBinaryExpression, isBooleanType, isBrsFile, isCallExpression, isCallableType, isClassStatement, isClassType, isComponentType, isDottedGetExpression, isDynamicType, isEnumMemberType, isEnumType, isFunctionExpression, isFunctionParameterExpression, isInterfaceType, isLiteralExpression, isNamespaceStatement, isNamespaceType, isNewExpression, isNumberType, isObjectType, isPrimitiveType, isReferenceType, isReturnStatement, isStringType, isTypedFunctionType, isUnionType, isVariableExpression, isVoidType, isXmlScope } from '../../astUtils/reflection';

Check failure on line 2 in src/bscPlugin/validation/ScopeValidator.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest)

'isInterfaceType' is declared but its value is never read.
import type { DiagnosticInfo } from '../../DiagnosticMessages';
import { DiagnosticMessages } from '../../DiagnosticMessages';
import type { BrsFile } from '../../files/BrsFile';
Expand Down Expand Up @@ -1239,6 +1239,8 @@ export class ScopeValidator {
* In particular, since BrightScript does not support Unions, and there's no way to cast them to something else
* if the result of .getType() is a union, and we're in a .brs (brightScript) file, treat the result as Dynamic
*
* Also, for BrightScript parse-mode, if .getType() returns a node type, do not validate unknown members.
*
* In most cases, this returns the result of node.getType()
*
* @param file the current file being processed
Expand All @@ -1265,6 +1267,11 @@ export class ScopeValidator {
//this is a union
return DynamicType.instance;
}

if (isComponentType(type)) {
// modify type to allow any member access for Node types
type.changeUnknownMemberToDynamic = true;
}
}

// by default return the result of node.getType()
Expand Down
11 changes: 9 additions & 2 deletions src/types/InheritableType.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { GetTypeOptions, TypeCompatibilityData } from '../interfaces';
import { isInheritableType, isReferenceType } from '../astUtils/reflection';
import { isAnyReferenceType, isInheritableType, isReferenceType } from '../astUtils/reflection';

Check failure on line 2 in src/types/InheritableType.ts

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest)

'isAnyReferenceType' is declared but its value is never read.
import { SymbolTypeFlag } from '../SymbolTypeFlag';
import { BscType } from './BscType';
import type { ReferenceType } from './ReferenceType';
Expand All @@ -14,14 +14,21 @@ export abstract class InheritableType extends BscType {
}
}

changeUnknownMemberToDynamic = false;

getMemberType(memberName: string, options: GetTypeOptions) {
let hasRoAssociativeArrayAsAncestor = this.name.toLowerCase() === 'roassociativearray' || this.getAncestorTypeList()?.find(ancestorType => ancestorType.name.toLowerCase() === 'roassociativearray');

if (hasRoAssociativeArrayAsAncestor) {
return super.getMemberType(memberName, options) ?? DynamicType.instance;
}

return super.getMemberType(memberName, { ...options, fullName: memberName, tableProvider: () => this.memberTable });
const resultType = super.getMemberType(memberName, { ...options, fullName: memberName, tableProvider: () => this.memberTable });

if (this.changeUnknownMemberToDynamic && !resultType.isResolvable()) {
return DynamicType.instance;
}
return resultType;
}

public toString() {
Expand Down

0 comments on commit 7b91eb0

Please sign in to comment.