diff --git a/src/files/BrsFile.spec.ts b/src/files/BrsFile.spec.ts index 9d9751192..7bd87ad81 100644 --- a/src/files/BrsFile.spec.ts +++ b/src/files/BrsFile.spec.ts @@ -16,7 +16,7 @@ import { DiagnosticMessages } from '../DiagnosticMessages'; import type { StandardizedFileEntry } from 'roku-deploy'; import util, { standardizePath as s } from '../util'; import PluginInterface from '../PluginInterface'; -import { trim, trimMap } from '../testHelpers.spec'; +import { expectZeroDiagnostics, trim, trimMap } from '../testHelpers.spec'; import { ParseMode } from '../parser/Parser'; import { Logger } from '../Logger'; @@ -383,6 +383,18 @@ describe('BrsFile', () => { }); describe('parse', () => { + it('supports iife in assignment', () => { + program.addOrReplaceFile('source/main.brs', ` + sub main() + result = sub() + end sub() + result = (sub() + end sub)() + end sub + `); + expectZeroDiagnostics(program); + }); + it('uses the proper parse mode based on file extension', () => { function testParseMode(destPath: string, expectedParseMode: ParseMode) { const file = program.addOrReplaceFile(destPath, ''); diff --git a/src/files/BrsFile.ts b/src/files/BrsFile.ts index f082b1e9b..41ef20ec3 100644 --- a/src/files/BrsFile.ts +++ b/src/files/BrsFile.ts @@ -648,12 +648,13 @@ export class BrsFile { for (let func of this._parser.references.functionExpressions) { //for all function calls in this function for (let expression of func.callExpressions) { - if ( //filter out dotted function invocations (i.e. object.doSomething()) (not currently supported. TODO support it) (expression.callee as any).obj || //filter out method calls on method calls for now (i.e. getSomething().getSomethingElse()) - (expression.callee as any).callee + (expression.callee as any).callee || + //filter out callees without a name (immediately-invoked function expressions) + !(expression.callee as any).name ) { continue; } diff --git a/src/parser/Parser.spec.ts b/src/parser/Parser.spec.ts index c990c1eae..c4d6fa7dc 100644 --- a/src/parser/Parser.spec.ts +++ b/src/parser/Parser.spec.ts @@ -7,6 +7,7 @@ import { PrintStatement, FunctionStatement, NamespaceStatement, ImportStatement import { Range } from 'vscode-languageserver'; import { DiagnosticMessages } from '../DiagnosticMessages'; import { isBlock, isCommentStatement, isFunctionStatement, isIfStatement } from '../astUtils'; +import { expectZeroDiagnostics } from '../testHelpers.spec'; describe('parser', () => { it('emits empty object when empty token list is provided', () => { @@ -95,6 +96,40 @@ describe('parser', () => { }); describe('parse', () => { + it('supports ungrouped iife in assignment', () => { + const parser = parse(` + sub main() + result = sub() + end sub() + result = function() + end function() + end sub + `); + expectZeroDiagnostics(parser); + }); + + it('supports grouped iife in assignment', () => { + const parser = parse(` + sub main() + result = (sub() + end sub)() + result = (function() + end function)() + end sub + `); + expectZeroDiagnostics(parser); + }); + + it('supports returning iife call', () => { + const parser = parse(` + sub main() + return (sub() + end sub)() + end sub + `); + expectZeroDiagnostics(parser); + }); + it('supports using "interface" as parameter name', () => { expect(parse(` sub main(interface as object) diff --git a/src/parser/Parser.ts b/src/parser/Parser.ts index 8cd0f4608..a13a34dbe 100644 --- a/src/parser/Parser.ts +++ b/src/parser/Parser.ts @@ -1937,7 +1937,13 @@ export class Parser { private anonymousFunction(): Expression { if (this.checkAny(TokenKind.Sub, TokenKind.Function)) { - return this.functionDeclaration(true); + const func = this.functionDeclaration(true); + //if there's an open paren after this, this is an IIFE + if (this.check(TokenKind.LeftParen)) { + return this.finishCall(this.advance(), func); + } else { + return func; + } } //template string