Skip to content

Commit

Permalink
Prevent errors when using enums in a file that's not included in any …
Browse files Browse the repository at this point in the history
…scopes (#995)

* Use a fake scope when a file is not in any scope

* refactor to use null Scope static method

* try two

* remove vestigial changes

* more vestigial changes

* remove yet another

* change import to use specific file
  • Loading branch information
josephjunker committed Dec 24, 2023
1 parent 6f31ae2 commit 8be28cd
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/Program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ export class Program {
/**
* Get the first found scope for a file.
*/
public getFirstScopeForFile(file: XmlFile | BrsFile): Scope {
public getFirstScopeForFile(file: XmlFile | BrsFile): Scope | undefined {
for (let key in this.scopes) {
let scope = this.scopes[key];

Expand Down
2 changes: 1 addition & 1 deletion src/Scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,7 @@ export class Scope {
}
}

interface NamespaceContainer {
export interface NamespaceContainer {
file: BscFile;
fullName: string;
nameRange: Range;
Expand Down
9 changes: 5 additions & 4 deletions src/bscPlugin/CallExpressionInfo.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { Expression } from '../parser/AstNode';
import type { CallExpression, CallfuncExpression, NewExpression } from '../parser/Expression';
import type { ClassStatement, NamespaceStatement } from '../parser/Statement';
import type { ClassStatement } from '../parser/Statement';
import { isCallExpression, isCallfuncExpression, isVariableExpression, isDottedGetExpression, isClassStatement, isNewExpression } from '../astUtils/reflection';
import type { BrsFile } from '../files/BrsFile';
import type { Position } from 'vscode-languageserver-protocol';
import { util } from '../util';
import { ParseMode } from '../parser/Parser';
import type { NamespaceContainer } from '../Scope';


export enum CallExpressionType {
Expand All @@ -29,7 +30,7 @@ export class CallExpressionInfo {

file: BrsFile;
myClass: ClassStatement;
namespace: NamespaceStatement;
namespace?: NamespaceContainer;
dotPart: string;
name: string;
isCallingMethodOnMyClass: boolean;
Expand Down Expand Up @@ -80,7 +81,7 @@ export class CallExpressionInfo {
let parts = util.getAllDottedGetParts(callExpression.callee);
parts.splice(parts?.length - 1, 1);
this.dotPart = parts.map(x => x.text).join('.');
this.namespace = this.getNamespace(this.dotPart, this.file);
this.namespace = this.getNamespace();
}
}

Expand Down Expand Up @@ -142,7 +143,7 @@ export class CallExpressionInfo {

}

private getNamespace(dotPart: string, file: BrsFile): any {
private getNamespace(): NamespaceContainer {
let scope = this.file.program.getFirstScopeForFile(this.file);
return scope.namespaceLookup.get(this.dotPart);
}
Expand Down
17 changes: 16 additions & 1 deletion src/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import * as fsExtra from 'fs-extra';
import { Program } from '../../Program';
import { standardizePath as s } from '../../util';
import { tempDir, rootDir } from '../../testHelpers.spec';
import { Logger, LogLevel } from '../../Logger';
import PluginInterface from '../../PluginInterface';
const sinon = createSandbox();

describe('BrsFile', () => {
Expand All @@ -11,8 +13,13 @@ describe('BrsFile', () => {

beforeEach(() => {
fsExtra.emptyDirSync(tempDir);
program = new Program({ rootDir: rootDir, sourceMap: true });
const logger = new Logger(LogLevel.warn);
program = new Program({ rootDir: rootDir, sourceMap: true }, logger, new PluginInterface([], {
logger: logger,
suppressErrors: false
}));
});

afterEach(() => {
sinon.restore();
program.dispose();
Expand All @@ -21,11 +28,19 @@ describe('BrsFile', () => {
describe('BrsFilePreTranspileProcessor', () => {
it('does not crash when operating on a file not included by any scope', async () => {
program.setFile('components/lib.brs', `
enum Direction
up
down
left
right
end enum
sub doSomething()
a = { b: "c"}
print a.b
print Direction.up
end sub
`);

await program.transpile([], s`${tempDir}/out`);
});
});
Expand Down
6 changes: 3 additions & 3 deletions src/bscPlugin/transpile/BrsFilePreTranspileProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ export class BrsFilePreTranspileProcessor {
* Given a string optionally separated by dots, find an enum related to it.
* For example, all of these would return the enum: `SomeNamespace.SomeEnum.SomeMember`, SomeEnum.SomeMember, `SomeEnum`
*/
private getEnumInfo(name: string, containingNamespace: string, scope: Scope) {
private getEnumInfo(name: string, containingNamespace: string, scope: Scope | undefined) {

//do we have an enum MEMBER reference? (i.e. SomeEnum.someMember or SomeNamespace.SomeEnum.SomeMember)
let memberLink = scope.getEnumMemberFileLink(name, containingNamespace);
let memberLink = scope?.getEnumMemberFileLink(name, containingNamespace);
if (memberLink) {
const value = memberLink.item.getValue();
return {
Expand All @@ -65,7 +65,7 @@ export class BrsFilePreTranspileProcessor {

}

private processExpression(expression: Expression, scope: Scope) {
private processExpression(expression: Expression, scope: Scope | undefined) {
let containingNamespace = this.event.file.getNamespaceStatementForPosition(expression.range.start)?.getName(ParseMode.BrighterScript);

const parts = util.splitExpression(expression);
Expand Down

0 comments on commit 8be28cd

Please sign in to comment.