brighterscript 0.72.0 → 0.72.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bsconfig.schema.json +62 -0
- package/dist/BsConfig.d.ts +56 -1
- package/dist/CommentFlagProcessor.d.ts +16 -12
- package/dist/CommentFlagProcessor.js +141 -59
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +27 -1
- package/dist/DiagnosticMessages.js +32 -2
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/Program.d.ts +4 -0
- package/dist/Program.js +2 -0
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +1 -8
- package/dist/ProgramBuilder.js +31 -11
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +38 -0
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +257 -14
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.js +13 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/cli.js +13 -0
- package/dist/cli.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +51 -1
- package/dist/diagnosticUtils.js +222 -1
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/files/BrsFile.js +4 -2
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/XmlFile.js +2 -1
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/interfaces.d.ts +15 -1
- package/dist/lexer/TokenKind.d.ts +8 -0
- package/dist/lexer/TokenKind.js +21 -1
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/lsp/LspProject.d.ts +19 -0
- package/dist/lsp/Project.d.ts +14 -0
- package/dist/lsp/Project.js +9 -1
- package/dist/lsp/Project.js.map +1 -1
- package/dist/lsp/ProjectManager.js +15 -1
- package/dist/lsp/ProjectManager.js.map +1 -1
- package/dist/lsp/worker/WorkerThreadProject.d.ts +14 -0
- package/dist/lsp/worker/WorkerThreadProject.js +7 -0
- package/dist/lsp/worker/WorkerThreadProject.js.map +1 -1
- package/dist/parser/Parser.d.ts +13 -1
- package/dist/parser/Parser.js +40 -14
- package/dist/parser/Parser.js.map +1 -1
- package/dist/util.js +20 -9
- package/dist/util.js.map +1 -1
- package/package.json +17 -14
- package/dist/astUtils/AstEditor.spec.d.ts +0 -1
- package/dist/astUtils/AstEditor.spec.js +0 -254
- package/dist/astUtils/AstEditor.spec.js.map +0 -1
- package/dist/astUtils/creators.spec.d.ts +0 -1
- package/dist/astUtils/creators.spec.js +0 -21
- package/dist/astUtils/creators.spec.js.map +0 -1
- package/dist/astUtils/reflection.spec.d.ts +0 -1
- package/dist/astUtils/reflection.spec.js +0 -308
- package/dist/astUtils/reflection.spec.js.map +0 -1
- package/dist/astUtils/stackedVisitor.spec.d.ts +0 -1
- package/dist/astUtils/stackedVisitor.spec.js +0 -79
- package/dist/astUtils/stackedVisitor.spec.js.map +0 -1
- package/dist/astUtils/visitors.spec.d.ts +0 -1
- package/dist/astUtils/visitors.spec.js +0 -1197
- package/dist/astUtils/visitors.spec.js.map +0 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +0 -887
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/definition/DefinitionProvider.spec.d.ts +0 -1
- package/dist/bscPlugin/definition/DefinitionProvider.spec.js +0 -171
- package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +0 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +0 -201
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/references/ReferencesProvider.spec.d.ts +0 -1
- package/dist/bscPlugin/references/ReferencesProvider.spec.js +0 -51
- package/dist/bscPlugin/references/ReferencesProvider.spec.js.map +0 -1
- package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.spec.js +0 -298
- package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +0 -399
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js +0 -290
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js +0 -245
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -46
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +0 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +0 -487
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +0 -1
- package/dist/common/Sequencer.spec.d.ts +0 -1
- package/dist/common/Sequencer.spec.js +0 -75
- package/dist/common/Sequencer.spec.js.map +0 -1
- package/dist/files/BrsFile.Class.spec.d.ts +0 -1
- package/dist/files/BrsFile.Class.spec.js +0 -1805
- package/dist/files/BrsFile.Class.spec.js.map +0 -1
- package/dist/files/BrsFile.spec.d.ts +0 -1
- package/dist/files/BrsFile.spec.js +0 -4420
- package/dist/files/BrsFile.spec.js.map +0 -1
- package/dist/files/XmlFile.spec.d.ts +0 -1
- package/dist/files/XmlFile.spec.js +0 -1169
- package/dist/files/XmlFile.spec.js.map +0 -1
- package/dist/files/tests/imports.spec.d.ts +0 -1
- package/dist/files/tests/imports.spec.js +0 -241
- package/dist/files/tests/imports.spec.js.map +0 -1
- package/dist/files/tests/optionalChaning.spec.d.ts +0 -1
- package/dist/files/tests/optionalChaning.spec.js +0 -152
- package/dist/files/tests/optionalChaning.spec.js.map +0 -1
- package/dist/lexer/Character.spec.d.ts +0 -1
- package/dist/lexer/Character.spec.js +0 -27
- package/dist/lexer/Character.spec.js.map +0 -1
- package/dist/lexer/Lexer.spec.d.ts +0 -1
- package/dist/lexer/Lexer.spec.js +0 -1300
- package/dist/lexer/Lexer.spec.js.map +0 -1
- package/dist/lsp/ActionQueue.spec.d.ts +0 -1
- package/dist/lsp/ActionQueue.spec.js +0 -80
- package/dist/lsp/ActionQueue.spec.js.map +0 -1
- package/dist/lsp/DocumentManager.spec.d.ts +0 -1
- package/dist/lsp/DocumentManager.spec.js +0 -103
- package/dist/lsp/DocumentManager.spec.js.map +0 -1
- package/dist/lsp/PathFilterer.spec.d.ts +0 -1
- package/dist/lsp/PathFilterer.spec.js +0 -182
- package/dist/lsp/PathFilterer.spec.js.map +0 -1
- package/dist/lsp/Project.spec.d.ts +0 -1
- package/dist/lsp/Project.spec.js +0 -400
- package/dist/lsp/Project.spec.js.map +0 -1
- package/dist/lsp/ProjectManager.spec.d.ts +0 -1
- package/dist/lsp/ProjectManager.spec.js +0 -1147
- package/dist/lsp/ProjectManager.spec.js.map +0 -1
- package/dist/lsp/worker/MessageHandler.spec.d.ts +0 -1
- package/dist/lsp/worker/MessageHandler.spec.js +0 -64
- package/dist/lsp/worker/MessageHandler.spec.js.map +0 -1
- package/dist/lsp/worker/WorkerPool.spec.d.ts +0 -1
- package/dist/lsp/worker/WorkerPool.spec.js +0 -59
- package/dist/lsp/worker/WorkerPool.spec.js.map +0 -1
- package/dist/lsp/worker/WorkerThreadProject.spec.d.ts +0 -2
- package/dist/lsp/worker/WorkerThreadProject.spec.js +0 -72
- package/dist/lsp/worker/WorkerThreadProject.spec.js.map +0 -1
- package/dist/parser/AstNode.spec.d.ts +0 -1
- package/dist/parser/AstNode.spec.js +0 -1452
- package/dist/parser/AstNode.spec.js.map +0 -1
- package/dist/parser/Expression.spec.d.ts +0 -1
- package/dist/parser/Expression.spec.js +0 -40
- package/dist/parser/Expression.spec.js.map +0 -1
- package/dist/parser/Parser.Class.spec.d.ts +0 -1
- package/dist/parser/Parser.Class.spec.js +0 -495
- package/dist/parser/Parser.Class.spec.js.map +0 -1
- package/dist/parser/Parser.spec.d.ts +0 -4
- package/dist/parser/Parser.spec.js +0 -1857
- package/dist/parser/Parser.spec.js.map +0 -1
- package/dist/parser/SGParser.spec.d.ts +0 -1
- package/dist/parser/SGParser.spec.js +0 -131
- package/dist/parser/SGParser.spec.js.map +0 -1
- package/dist/parser/Statement.spec.d.ts +0 -1
- package/dist/parser/Statement.spec.js +0 -118
- package/dist/parser/Statement.spec.js.map +0 -1
- package/dist/parser/tests/Parser.spec.d.ts +0 -19
- package/dist/parser/tests/Parser.spec.js +0 -38
- package/dist/parser/tests/Parser.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/For.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/For.spec.js +0 -161
- package/dist/parser/tests/controlFlow/For.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +0 -106
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/If.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/If.spec.js +0 -570
- package/dist/parser/tests/controlFlow/If.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/While.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/While.spec.js +0 -107
- package/dist/parser/tests/controlFlow/While.spec.js.map +0 -1
- package/dist/parser/tests/expression/Additive.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Additive.spec.js +0 -99
- package/dist/parser/tests/expression/Additive.spec.js.map +0 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.d.ts +0 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +0 -291
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +0 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.d.ts +0 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +0 -401
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +0 -1
- package/dist/parser/tests/expression/Boolean.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Boolean.spec.js +0 -83
- package/dist/parser/tests/expression/Boolean.spec.js.map +0 -1
- package/dist/parser/tests/expression/Call.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Call.spec.js +0 -242
- package/dist/parser/tests/expression/Call.spec.js.map +0 -1
- package/dist/parser/tests/expression/Exponential.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Exponential.spec.js +0 -37
- package/dist/parser/tests/expression/Exponential.spec.js.map +0 -1
- package/dist/parser/tests/expression/Function.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Function.spec.js +0 -403
- package/dist/parser/tests/expression/Function.spec.js.map +0 -1
- package/dist/parser/tests/expression/Indexing.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Indexing.spec.js +0 -289
- package/dist/parser/tests/expression/Indexing.spec.js.map +0 -1
- package/dist/parser/tests/expression/Multiplicative.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +0 -67
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +0 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +0 -346
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.d.ts +0 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +0 -105
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +0 -1
- package/dist/parser/tests/expression/Primary.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Primary.spec.js +0 -149
- package/dist/parser/tests/expression/Primary.spec.js.map +0 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +0 -171
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/Relational.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Relational.spec.js +0 -83
- package/dist/parser/tests/expression/Relational.spec.js.map +0 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +0 -201
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +0 -389
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +0 -876
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/UnaryExpression.spec.js +0 -52
- package/dist/parser/tests/expression/UnaryExpression.spec.js.map +0 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.d.ts +0 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +0 -79
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +0 -1
- package/dist/parser/tests/statement/ConstStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/ConstStatement.spec.js +0 -708
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/Continue.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Continue.spec.js +0 -119
- package/dist/parser/tests/statement/Continue.spec.js.map +0 -1
- package/dist/parser/tests/statement/Declaration.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Declaration.spec.js +0 -108
- package/dist/parser/tests/statement/Declaration.spec.js.map +0 -1
- package/dist/parser/tests/statement/Dim.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Dim.spec.js +0 -73
- package/dist/parser/tests/statement/Dim.spec.js.map +0 -1
- package/dist/parser/tests/statement/Enum.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Enum.spec.js +0 -1307
- package/dist/parser/tests/statement/Enum.spec.js.map +0 -1
- package/dist/parser/tests/statement/For.spec.d.ts +0 -1
- package/dist/parser/tests/statement/For.spec.js +0 -45
- package/dist/parser/tests/statement/For.spec.js.map +0 -1
- package/dist/parser/tests/statement/ForEach.spec.d.ts +0 -1
- package/dist/parser/tests/statement/ForEach.spec.js +0 -36
- package/dist/parser/tests/statement/ForEach.spec.js.map +0 -1
- package/dist/parser/tests/statement/Function.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Function.spec.js +0 -342
- package/dist/parser/tests/statement/Function.spec.js.map +0 -1
- package/dist/parser/tests/statement/Goto.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Goto.spec.js +0 -51
- package/dist/parser/tests/statement/Goto.spec.js.map +0 -1
- package/dist/parser/tests/statement/Increment.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Increment.spec.js +0 -117
- package/dist/parser/tests/statement/Increment.spec.js.map +0 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +0 -102
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.js +0 -74
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/Misc.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Misc.spec.js +0 -335
- package/dist/parser/tests/statement/Misc.spec.js.map +0 -1
- package/dist/parser/tests/statement/PrintStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +0 -195
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +0 -94
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/Set.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Set.spec.js +0 -218
- package/dist/parser/tests/statement/Set.spec.js.map +0 -1
- package/dist/parser/tests/statement/Stop.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Stop.spec.js +0 -38
- package/dist/parser/tests/statement/Stop.spec.js.map +0 -1
- package/dist/parser/tests/statement/Throw.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Throw.spec.js +0 -35
- package/dist/parser/tests/statement/Throw.spec.js.map +0 -1
- package/dist/parser/tests/statement/TryCatch.spec.d.ts +0 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +0 -142
- package/dist/parser/tests/statement/TryCatch.spec.js.map +0 -1
- package/dist/preprocessor/Manifest.spec.d.ts +0 -1
- package/dist/preprocessor/Manifest.spec.js +0 -80
- package/dist/preprocessor/Manifest.spec.js.map +0 -1
- package/dist/preprocessor/Preprocessor.spec.d.ts +0 -1
- package/dist/preprocessor/Preprocessor.spec.js +0 -152
- package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
- package/dist/preprocessor/PreprocessorParser.spec.d.ts +0 -1
- package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
- package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
- package/dist/types/ArrayType.spec.d.ts +0 -1
- package/dist/types/ArrayType.spec.js +0 -30
- package/dist/types/ArrayType.spec.js.map +0 -1
- package/dist/types/BooleanType.spec.d.ts +0 -1
- package/dist/types/BooleanType.spec.js +0 -12
- package/dist/types/BooleanType.spec.js.map +0 -1
- package/dist/types/DoubleType.spec.d.ts +0 -1
- package/dist/types/DoubleType.spec.js +0 -12
- package/dist/types/DoubleType.spec.js.map +0 -1
- package/dist/types/DynamicType.spec.d.ts +0 -1
- package/dist/types/DynamicType.spec.js +0 -12
- package/dist/types/DynamicType.spec.js.map +0 -1
- package/dist/types/FloatType.spec.d.ts +0 -1
- package/dist/types/FloatType.spec.js +0 -12
- package/dist/types/FloatType.spec.js.map +0 -1
- package/dist/types/FunctionType.spec.d.ts +0 -1
- package/dist/types/FunctionType.spec.js +0 -23
- package/dist/types/FunctionType.spec.js.map +0 -1
- package/dist/types/IntegerType.spec.d.ts +0 -1
- package/dist/types/IntegerType.spec.js +0 -12
- package/dist/types/IntegerType.spec.js.map +0 -1
- package/dist/types/InterfaceType.spec.d.ts +0 -1
- package/dist/types/InterfaceType.spec.js +0 -175
- package/dist/types/InterfaceType.spec.js.map +0 -1
- package/dist/types/InvalidType.spec.d.ts +0 -1
- package/dist/types/InvalidType.spec.js +0 -12
- package/dist/types/InvalidType.spec.js.map +0 -1
- package/dist/types/LongIntegerType.spec.d.ts +0 -1
- package/dist/types/LongIntegerType.spec.js +0 -12
- package/dist/types/LongIntegerType.spec.js.map +0 -1
- package/dist/types/ObjectType.spec.d.ts +0 -1
- package/dist/types/ObjectType.spec.js +0 -12
- package/dist/types/ObjectType.spec.js.map +0 -1
- package/dist/types/StringType.spec.d.ts +0 -1
- package/dist/types/StringType.spec.js +0 -12
- package/dist/types/StringType.spec.js.map +0 -1
- package/dist/types/VoidType.spec.d.ts +0 -1
- package/dist/types/VoidType.spec.js +0 -12
- package/dist/types/VoidType.spec.js.map +0 -1
|
@@ -1,4420 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const chai_config_spec_1 = require("../chai-config.spec");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const sinonImport = require("sinon");
|
|
6
|
-
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
7
|
-
const Program_1 = require("../Program");
|
|
8
|
-
const BooleanType_1 = require("../types/BooleanType");
|
|
9
|
-
const DynamicType_1 = require("../types/DynamicType");
|
|
10
|
-
const FunctionType_1 = require("../types/FunctionType");
|
|
11
|
-
const IntegerType_1 = require("../types/IntegerType");
|
|
12
|
-
const StringType_1 = require("../types/StringType");
|
|
13
|
-
const BrsFile_1 = require("./BrsFile");
|
|
14
|
-
const source_map_1 = require("source-map");
|
|
15
|
-
const Lexer_1 = require("../lexer/Lexer");
|
|
16
|
-
const TokenKind_1 = require("../lexer/TokenKind");
|
|
17
|
-
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
18
|
-
const util_1 = require("../util");
|
|
19
|
-
const PluginInterface_1 = require("../PluginInterface");
|
|
20
|
-
const testHelpers_spec_1 = require("../testHelpers.spec");
|
|
21
|
-
const Parser_1 = require("../parser/Parser");
|
|
22
|
-
const logging_1 = require("../logging");
|
|
23
|
-
const Statement_1 = require("../parser/Statement");
|
|
24
|
-
const creators_1 = require("../astUtils/creators");
|
|
25
|
-
const fsExtra = require("fs-extra");
|
|
26
|
-
const vscode_uri_1 = require("vscode-uri");
|
|
27
|
-
const undent_1 = require("undent");
|
|
28
|
-
const testHelpers_spec_2 = require("../testHelpers.spec");
|
|
29
|
-
const fileUrl = require("file-url");
|
|
30
|
-
const Expression_1 = require("../parser/Expression");
|
|
31
|
-
let sinon = sinonImport.createSandbox();
|
|
32
|
-
describe('BrsFile', () => {
|
|
33
|
-
let program;
|
|
34
|
-
let srcPath = (0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.brs`;
|
|
35
|
-
let destPath = 'source/main.brs';
|
|
36
|
-
let file;
|
|
37
|
-
let testTranspile = (0, testHelpers_spec_1.getTestTranspile)(() => [program, testHelpers_spec_2.rootDir]);
|
|
38
|
-
let testGetTypedef = (0, testHelpers_spec_1.getTestGetTypedef)(() => [program, testHelpers_spec_2.rootDir]);
|
|
39
|
-
beforeEach(() => {
|
|
40
|
-
fsExtra.emptyDirSync(testHelpers_spec_2.tempDir);
|
|
41
|
-
program = new Program_1.Program({ rootDir: testHelpers_spec_2.rootDir, sourceMap: true });
|
|
42
|
-
file = new BrsFile_1.BrsFile(srcPath, destPath, program);
|
|
43
|
-
});
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
sinon.restore();
|
|
46
|
-
program.dispose();
|
|
47
|
-
});
|
|
48
|
-
describe('dispose', () => {
|
|
49
|
-
it('does not crash the program after it has been disposed', () => {
|
|
50
|
-
const file = program.setFile('source/main.bs', `sub main(): end sub`);
|
|
51
|
-
file.dispose();
|
|
52
|
-
program.validate();
|
|
53
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
describe('allowBrighterScriptInBrightScript', () => {
|
|
57
|
-
it('is false by default', () => {
|
|
58
|
-
program.setFile('source/main.brs', `
|
|
59
|
-
namespace CustomApp
|
|
60
|
-
end namespace
|
|
61
|
-
`);
|
|
62
|
-
program.validate();
|
|
63
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.bsFeatureNotSupportedInBrsFiles('namespace'))]);
|
|
64
|
-
});
|
|
65
|
-
it('allows bs features in brs', () => {
|
|
66
|
-
program.options.allowBrighterScriptInBrightScript = true;
|
|
67
|
-
program.setFile('source/main.brs', `
|
|
68
|
-
namespace CustomApp
|
|
69
|
-
end namespace
|
|
70
|
-
`);
|
|
71
|
-
program.validate();
|
|
72
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
describe('line continuation', () => {
|
|
76
|
-
it('does not allow binary operator continuation in .brs files by default', () => {
|
|
77
|
-
program.setFile('source/main.brs', `
|
|
78
|
-
sub main()
|
|
79
|
-
result = 1 +
|
|
80
|
-
2
|
|
81
|
-
end sub
|
|
82
|
-
`);
|
|
83
|
-
program.validate();
|
|
84
|
-
(0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [
|
|
85
|
-
DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('\n'),
|
|
86
|
-
DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()
|
|
87
|
-
]);
|
|
88
|
-
});
|
|
89
|
-
it('allows binary operator continuation in .bs files', () => {
|
|
90
|
-
program.setFile('source/main.bs', `
|
|
91
|
-
sub main()
|
|
92
|
-
result = 1 +
|
|
93
|
-
2
|
|
94
|
-
end sub
|
|
95
|
-
`);
|
|
96
|
-
program.validate();
|
|
97
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
98
|
-
});
|
|
99
|
-
it('transpiles binary operator continuation in .bs files to a single line', () => {
|
|
100
|
-
testTranspile(`
|
|
101
|
-
sub main()
|
|
102
|
-
result = 1 +
|
|
103
|
-
2
|
|
104
|
-
end sub
|
|
105
|
-
`, `
|
|
106
|
-
sub main()
|
|
107
|
-
result = 1 + 2
|
|
108
|
-
end sub
|
|
109
|
-
`);
|
|
110
|
-
});
|
|
111
|
-
it('allows binary operator continuation in .brs files when allowBrighterScriptInBrightScript is enabled', () => {
|
|
112
|
-
program.options.allowBrighterScriptInBrightScript = true;
|
|
113
|
-
program.setFile('source/main.brs', `
|
|
114
|
-
sub main()
|
|
115
|
-
result = 1 +
|
|
116
|
-
2
|
|
117
|
-
end sub
|
|
118
|
-
`);
|
|
119
|
-
program.validate();
|
|
120
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
121
|
-
});
|
|
122
|
-
it('does not allow multi-line function call args in .brs files by default', () => {
|
|
123
|
-
program.setFile('source/main.brs', `
|
|
124
|
-
sub main()
|
|
125
|
-
foo(
|
|
126
|
-
1,
|
|
127
|
-
2
|
|
128
|
-
)
|
|
129
|
-
end sub
|
|
130
|
-
sub foo(a, b)
|
|
131
|
-
end sub
|
|
132
|
-
`);
|
|
133
|
-
program.validate();
|
|
134
|
-
(0, testHelpers_spec_1.expectDiagnosticsIncludes)(program, [
|
|
135
|
-
DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('\n'),
|
|
136
|
-
DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
|
|
137
|
-
DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()
|
|
138
|
-
]);
|
|
139
|
-
});
|
|
140
|
-
it('allows multi-line array literals as function call args in .brs files by default', () => {
|
|
141
|
-
program.setFile('source/main.brs', `
|
|
142
|
-
sub main()
|
|
143
|
-
foo([
|
|
144
|
-
1,
|
|
145
|
-
2
|
|
146
|
-
])
|
|
147
|
-
end sub
|
|
148
|
-
sub foo(arg)
|
|
149
|
-
end sub
|
|
150
|
-
`);
|
|
151
|
-
program.validate();
|
|
152
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
153
|
-
});
|
|
154
|
-
it('allows multi-line associative array literals as function call args in .brs files by default', () => {
|
|
155
|
-
program.setFile('source/main.brs', `
|
|
156
|
-
sub main()
|
|
157
|
-
foo({
|
|
158
|
-
name: "bob",
|
|
159
|
-
age: 1
|
|
160
|
-
})
|
|
161
|
-
end sub
|
|
162
|
-
sub foo(arg)
|
|
163
|
-
end sub
|
|
164
|
-
`);
|
|
165
|
-
program.validate();
|
|
166
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
167
|
-
});
|
|
168
|
-
it('allows multi-line function call args in .bs files', () => {
|
|
169
|
-
program.setFile('source/main.bs', `
|
|
170
|
-
sub main()
|
|
171
|
-
foo(
|
|
172
|
-
1,
|
|
173
|
-
2
|
|
174
|
-
)
|
|
175
|
-
end sub
|
|
176
|
-
sub foo(a, b)
|
|
177
|
-
end sub
|
|
178
|
-
`);
|
|
179
|
-
program.validate();
|
|
180
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
181
|
-
});
|
|
182
|
-
it('transpiles multi-line function call args in .bs files to a single line', () => {
|
|
183
|
-
testTranspile(`
|
|
184
|
-
sub main()
|
|
185
|
-
foo(
|
|
186
|
-
1,
|
|
187
|
-
2
|
|
188
|
-
)
|
|
189
|
-
end sub
|
|
190
|
-
|
|
191
|
-
sub foo(a, b)
|
|
192
|
-
end sub
|
|
193
|
-
`, `
|
|
194
|
-
sub main()
|
|
195
|
-
foo(1, 2)
|
|
196
|
-
end sub
|
|
197
|
-
|
|
198
|
-
sub foo(a, b)
|
|
199
|
-
end sub
|
|
200
|
-
`);
|
|
201
|
-
});
|
|
202
|
-
it('allows multi-line function call args in .brs files when allowBrighterScriptInBrightScript is enabled', () => {
|
|
203
|
-
program.options.allowBrighterScriptInBrightScript = true;
|
|
204
|
-
program.setFile('source/main.brs', `
|
|
205
|
-
sub main()
|
|
206
|
-
foo(
|
|
207
|
-
1,
|
|
208
|
-
2
|
|
209
|
-
)
|
|
210
|
-
end sub
|
|
211
|
-
sub foo(a, b)
|
|
212
|
-
end sub
|
|
213
|
-
`);
|
|
214
|
-
program.validate();
|
|
215
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
216
|
-
});
|
|
217
|
-
});
|
|
218
|
-
it('does not show "missing function" diagnostic for `call().dottedGet` as a statement', () => {
|
|
219
|
-
program.setFile(`source/main.brs`, `
|
|
220
|
-
sub main()
|
|
221
|
-
test().disabled
|
|
222
|
-
end sub
|
|
223
|
-
sub test()
|
|
224
|
-
end sub
|
|
225
|
-
`);
|
|
226
|
-
program.validate();
|
|
227
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
228
|
-
{
|
|
229
|
-
range: util_1.default.createRange(2, 22, 2, 31),
|
|
230
|
-
message: DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('Property').message
|
|
231
|
-
}
|
|
232
|
-
]);
|
|
233
|
-
});
|
|
234
|
-
it('does not show "missing function" diagnostic for `call()["indexedGet"]` as a statement', () => {
|
|
235
|
-
program.setFile(`source/main.brs`, `
|
|
236
|
-
sub main()
|
|
237
|
-
test()["disabled"]
|
|
238
|
-
end sub
|
|
239
|
-
sub test()
|
|
240
|
-
end sub
|
|
241
|
-
`);
|
|
242
|
-
program.validate();
|
|
243
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
244
|
-
{
|
|
245
|
-
range: util_1.default.createRange(2, 22, 2, 34),
|
|
246
|
-
message: DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('Index').message
|
|
247
|
-
}
|
|
248
|
-
]);
|
|
249
|
-
});
|
|
250
|
-
it('does not show "missing function" diagnostic for `call()@xmlAttr` as a statement', () => {
|
|
251
|
-
program.setFile(`source/main.brs`, `
|
|
252
|
-
sub main()
|
|
253
|
-
test()@disabled
|
|
254
|
-
end sub
|
|
255
|
-
sub test()
|
|
256
|
-
end sub
|
|
257
|
-
`);
|
|
258
|
-
program.validate();
|
|
259
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
260
|
-
{
|
|
261
|
-
range: util_1.default.createRange(2, 22, 2, 31),
|
|
262
|
-
message: DiagnosticMessages_1.DiagnosticMessages.propAccessNotPermittedAfterFunctionCallInExpressionStatement('XML attribute').message
|
|
263
|
-
}
|
|
264
|
-
]);
|
|
265
|
-
});
|
|
266
|
-
it('does not flag two chained calls together', () => {
|
|
267
|
-
program.setFile(`source/main.brs`, `
|
|
268
|
-
sub main()
|
|
269
|
-
test().test()
|
|
270
|
-
end sub
|
|
271
|
-
function test()
|
|
272
|
-
print "test"
|
|
273
|
-
return {
|
|
274
|
-
test: test
|
|
275
|
-
}
|
|
276
|
-
end function
|
|
277
|
-
`);
|
|
278
|
-
program.validate();
|
|
279
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, []);
|
|
280
|
-
});
|
|
281
|
-
it('flags namespaces used as variables', () => {
|
|
282
|
-
program.setFile('source/main.bs', `
|
|
283
|
-
sub main()
|
|
284
|
-
alpha.beta.charlie.test()
|
|
285
|
-
print alpha
|
|
286
|
-
print alpha.beta
|
|
287
|
-
print alpha.beta.charlie
|
|
288
|
-
end sub
|
|
289
|
-
|
|
290
|
-
namespace alpha
|
|
291
|
-
namespace beta
|
|
292
|
-
namespace charlie
|
|
293
|
-
sub test()
|
|
294
|
-
end sub
|
|
295
|
-
end namespace
|
|
296
|
-
end namespace
|
|
297
|
-
end namespace
|
|
298
|
-
`);
|
|
299
|
-
program.validate();
|
|
300
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { range: util_1.default.createRange(3, 22, 3, 27) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { range: util_1.default.createRange(4, 22, 4, 32) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { range: util_1.default.createRange(5, 22, 5, 40) })]);
|
|
301
|
-
});
|
|
302
|
-
it('allows namespaces with the name `optional`', () => {
|
|
303
|
-
program.setFile('source/main.bs', `
|
|
304
|
-
namespace optional
|
|
305
|
-
namespace optional
|
|
306
|
-
end namespace
|
|
307
|
-
end namespace
|
|
308
|
-
namespace alpha
|
|
309
|
-
namespace optional
|
|
310
|
-
end namespace
|
|
311
|
-
end namespace
|
|
312
|
-
namespace alpha.beta.optional
|
|
313
|
-
end namespace
|
|
314
|
-
`);
|
|
315
|
-
program.validate();
|
|
316
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
317
|
-
});
|
|
318
|
-
it('supports the third parameter in CreateObject', () => {
|
|
319
|
-
program.setFile('source/main.brs', `
|
|
320
|
-
sub main()
|
|
321
|
-
regexp = CreateObject("roRegex", "[a-z]+", "i")
|
|
322
|
-
end sub
|
|
323
|
-
`);
|
|
324
|
-
program.validate();
|
|
325
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
326
|
-
});
|
|
327
|
-
it('supports the 6 params in CreateObject for roRegion', () => {
|
|
328
|
-
program.setFile('source/main.brs', `
|
|
329
|
-
sub createRegion(bitmap as object)
|
|
330
|
-
region = CreateObject("roRegion", bitmap, 20, 40, 100, 200)
|
|
331
|
-
end sub
|
|
332
|
-
`);
|
|
333
|
-
program.validate();
|
|
334
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
335
|
-
});
|
|
336
|
-
it('supports roUtils as a brightscript object', () => {
|
|
337
|
-
program.setFile('source/main.brs', `
|
|
338
|
-
sub test()
|
|
339
|
-
utils = CreateObject("roUtils")
|
|
340
|
-
end sub
|
|
341
|
-
`);
|
|
342
|
-
program.validate();
|
|
343
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
344
|
-
});
|
|
345
|
-
it('supports roRenderThreadQueue as a brightscript object', () => {
|
|
346
|
-
program.setFile('source/main.brs', `
|
|
347
|
-
sub test()
|
|
348
|
-
utils = CreateObject("roRenderThreadQueue")
|
|
349
|
-
end sub
|
|
350
|
-
`);
|
|
351
|
-
program.validate();
|
|
352
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
353
|
-
});
|
|
354
|
-
it('sets needsTranspiled to true for .bs files', () => {
|
|
355
|
-
//BrightScript
|
|
356
|
-
(0, chai_config_spec_1.expect)(new BrsFile_1.BrsFile(`${testHelpers_spec_2.rootDir}/source/main.brs`, 'source/main.brs', program).needsTranspiled).to.be.false;
|
|
357
|
-
//BrighterScript
|
|
358
|
-
(0, chai_config_spec_1.expect)(new BrsFile_1.BrsFile(`${testHelpers_spec_2.rootDir}/source/main.bs`, 'source/main.bs', program).needsTranspiled).to.be.true;
|
|
359
|
-
});
|
|
360
|
-
it('computes new import statements after clearing parser references', () => {
|
|
361
|
-
const file = program.setFile('source/main.bs', ``);
|
|
362
|
-
(0, chai_config_spec_1.expect)(file.ownScriptImports).to.be.empty;
|
|
363
|
-
file.parser.ast.statements.push(new Statement_1.ImportStatement((0, creators_1.createToken)(TokenKind_1.TokenKind.Import), (0, creators_1.createToken)(TokenKind_1.TokenKind.StringLiteral, 'pkg:/source/lib.brs')));
|
|
364
|
-
(0, chai_config_spec_1.expect)(file.ownScriptImports).to.be.empty;
|
|
365
|
-
file.parser.invalidateReferences();
|
|
366
|
-
(0, chai_config_spec_1.expect)(file.ownScriptImports.map(x => x.text)).to.eql(['pkg:/source/lib.brs']);
|
|
367
|
-
});
|
|
368
|
-
it('allows adding diagnostics', () => {
|
|
369
|
-
const expected = [{
|
|
370
|
-
message: 'message',
|
|
371
|
-
file: undefined,
|
|
372
|
-
range: undefined
|
|
373
|
-
}];
|
|
374
|
-
file.addDiagnostics(expected);
|
|
375
|
-
(0, testHelpers_spec_1.expectDiagnostics)(file, expected);
|
|
376
|
-
});
|
|
377
|
-
describe('getPartialVariableName', () => {
|
|
378
|
-
let entry = {
|
|
379
|
-
src: `${testHelpers_spec_2.rootDir}/source/lib.brs`,
|
|
380
|
-
dest: `source/lib.brs`
|
|
381
|
-
};
|
|
382
|
-
it('creates proper tokens', () => {
|
|
383
|
-
file = program.setFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
|
|
384
|
-
(0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
|
|
385
|
-
(0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
|
|
386
|
-
(0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
|
|
387
|
-
(0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[4])).to.equal('ModuleA.ModuleB');
|
|
388
|
-
(0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[3])).to.equal('ModuleA.');
|
|
389
|
-
(0, chai_config_spec_1.expect)(file['getPartialVariableName'](file.parser.tokens[2])).to.equal('ModuleA');
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
describe('canBePruned', () => {
|
|
393
|
-
it('returns false is target file has contains a function statement', () => {
|
|
394
|
-
program.setFile('source/main.brs', `
|
|
395
|
-
sub main()
|
|
396
|
-
print \`pkg:\`
|
|
397
|
-
end sub
|
|
398
|
-
`);
|
|
399
|
-
const file = program.getFile('source/main.brs');
|
|
400
|
-
(0, chai_config_spec_1.expect)(file.canBePruned).to.be.false;
|
|
401
|
-
});
|
|
402
|
-
it('returns false if target file contains a class statement', () => {
|
|
403
|
-
program.setFile('source/main.brs', `
|
|
404
|
-
class Animal
|
|
405
|
-
public name as string
|
|
406
|
-
end class
|
|
407
|
-
`);
|
|
408
|
-
const file = program.getFile('source/main.brs');
|
|
409
|
-
(0, chai_config_spec_1.expect)(file.canBePruned).to.be.false;
|
|
410
|
-
});
|
|
411
|
-
it('returns false if target file contains a class statement', () => {
|
|
412
|
-
program.setFile('source/main.brs', `
|
|
413
|
-
namespace Vertibrates.Birds
|
|
414
|
-
function GetDucks()
|
|
415
|
-
end function
|
|
416
|
-
end namespace
|
|
417
|
-
`);
|
|
418
|
-
const file = program.getFile('source/main.brs');
|
|
419
|
-
(0, chai_config_spec_1.expect)(file.canBePruned).to.be.false;
|
|
420
|
-
});
|
|
421
|
-
it('returns true if target file contains only enum', () => {
|
|
422
|
-
program.setFile('source/main.brs', `
|
|
423
|
-
enum Direction
|
|
424
|
-
up
|
|
425
|
-
down
|
|
426
|
-
left
|
|
427
|
-
right
|
|
428
|
-
end enum
|
|
429
|
-
`);
|
|
430
|
-
const file = program.getFile('source/main.brs');
|
|
431
|
-
(0, chai_config_spec_1.expect)(file.canBePruned).to.be.true;
|
|
432
|
-
});
|
|
433
|
-
it('returns true if target file is empty', () => {
|
|
434
|
-
program.setFile('source/main.brs', '');
|
|
435
|
-
const file = program.getFile('source/main.brs');
|
|
436
|
-
(0, chai_config_spec_1.expect)(file.canBePruned).to.be.true;
|
|
437
|
-
});
|
|
438
|
-
it('returns true if target file only has comments', () => {
|
|
439
|
-
program.setFile('source/main.brs', `
|
|
440
|
-
' this is an interesting comment
|
|
441
|
-
`);
|
|
442
|
-
const file = program.getFile('source/main.brs');
|
|
443
|
-
(0, chai_config_spec_1.expect)(file.canBePruned).to.be.true;
|
|
444
|
-
});
|
|
445
|
-
});
|
|
446
|
-
describe('getScopesForFile', () => {
|
|
447
|
-
it('finds the scope for the file', () => {
|
|
448
|
-
var _a;
|
|
449
|
-
let file = program.setFile('source/main.brs', ``);
|
|
450
|
-
(0, chai_config_spec_1.expect)((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
|
|
451
|
-
});
|
|
452
|
-
});
|
|
453
|
-
describe('getCompletions', () => {
|
|
454
|
-
it('does not crash for callfunc on a function call', () => {
|
|
455
|
-
const file = program.setFile('source/main.brs', `
|
|
456
|
-
sub main()
|
|
457
|
-
getManager()@.
|
|
458
|
-
end sub
|
|
459
|
-
`);
|
|
460
|
-
(0, chai_config_spec_1.expect)(() => {
|
|
461
|
-
program.getCompletions(file.srcPath, util_1.default.createPosition(2, 34));
|
|
462
|
-
}).not.to.throw;
|
|
463
|
-
});
|
|
464
|
-
it('suggests pkg paths in strings that match that criteria', () => {
|
|
465
|
-
program.setFile('source/main.brs', `
|
|
466
|
-
sub main()
|
|
467
|
-
print "pkg:"
|
|
468
|
-
end sub
|
|
469
|
-
`);
|
|
470
|
-
const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
|
|
471
|
-
const names = result.map(x => x.label);
|
|
472
|
-
(0, chai_config_spec_1.expect)(names.sort()).to.eql([
|
|
473
|
-
'pkg:/source/main.brs'
|
|
474
|
-
]);
|
|
475
|
-
});
|
|
476
|
-
it('suggests libpkg paths in strings that match that criteria', () => {
|
|
477
|
-
program.setFile('source/main.brs', `
|
|
478
|
-
sub main()
|
|
479
|
-
print "libpkg:"
|
|
480
|
-
end sub
|
|
481
|
-
`);
|
|
482
|
-
const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
|
|
483
|
-
const names = result.map(x => x.label);
|
|
484
|
-
(0, chai_config_spec_1.expect)(names.sort()).to.eql([
|
|
485
|
-
'libpkg:/source/main.brs'
|
|
486
|
-
]);
|
|
487
|
-
});
|
|
488
|
-
it('suggests pkg paths in template strings', () => {
|
|
489
|
-
program.setFile('source/main.brs', `
|
|
490
|
-
sub main()
|
|
491
|
-
print \`pkg:\`
|
|
492
|
-
end sub
|
|
493
|
-
`);
|
|
494
|
-
const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
|
|
495
|
-
const names = result.map(x => x.label);
|
|
496
|
-
(0, chai_config_spec_1.expect)(names.sort()).to.eql([
|
|
497
|
-
'pkg:/source/main.brs'
|
|
498
|
-
]);
|
|
499
|
-
});
|
|
500
|
-
it('waits for the file to be processed before collecting completions', () => {
|
|
501
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
502
|
-
program.setFile('source/main.brs', `
|
|
503
|
-
sub Main()
|
|
504
|
-
print "hello"
|
|
505
|
-
Say
|
|
506
|
-
end sub
|
|
507
|
-
|
|
508
|
-
sub SayHello()
|
|
509
|
-
end sub
|
|
510
|
-
`);
|
|
511
|
-
let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 23));
|
|
512
|
-
let names = result.map(x => x.label);
|
|
513
|
-
(0, chai_config_spec_1.expect)(names).to.includes('Main');
|
|
514
|
-
(0, chai_config_spec_1.expect)(names).to.includes('SayHello');
|
|
515
|
-
});
|
|
516
|
-
it('includes every type of item at base level', () => {
|
|
517
|
-
program.setFile('source/main.bs', `
|
|
518
|
-
sub main()
|
|
519
|
-
print
|
|
520
|
-
end sub
|
|
521
|
-
sub speak()
|
|
522
|
-
end sub
|
|
523
|
-
namespace stuff
|
|
524
|
-
end namespace
|
|
525
|
-
class Person
|
|
526
|
-
end class
|
|
527
|
-
enum Direction
|
|
528
|
-
end enum
|
|
529
|
-
`);
|
|
530
|
-
(0, testHelpers_spec_1.expectCompletionsIncludes)(program.getCompletions('source/main.bs', util_1.default.createPosition(2, 26)), [{
|
|
531
|
-
label: 'main',
|
|
532
|
-
kind: vscode_languageserver_1.CompletionItemKind.Function
|
|
533
|
-
}, {
|
|
534
|
-
label: 'speak',
|
|
535
|
-
kind: vscode_languageserver_1.CompletionItemKind.Function
|
|
536
|
-
}, {
|
|
537
|
-
label: 'stuff',
|
|
538
|
-
kind: vscode_languageserver_1.CompletionItemKind.Module
|
|
539
|
-
}, {
|
|
540
|
-
label: 'Person',
|
|
541
|
-
kind: vscode_languageserver_1.CompletionItemKind.Class
|
|
542
|
-
}, {
|
|
543
|
-
label: 'Direction',
|
|
544
|
-
kind: vscode_languageserver_1.CompletionItemKind.Enum
|
|
545
|
-
}]);
|
|
546
|
-
});
|
|
547
|
-
describe('namespaces', () => {
|
|
548
|
-
it('gets full namespace completions at any point through the leading identifier', () => {
|
|
549
|
-
program.setFile('source/main.bs', `
|
|
550
|
-
sub main()
|
|
551
|
-
foo.bar
|
|
552
|
-
end sub
|
|
553
|
-
|
|
554
|
-
namespace foo.bar
|
|
555
|
-
end namespace
|
|
556
|
-
|
|
557
|
-
class Person
|
|
558
|
-
end class
|
|
559
|
-
`);
|
|
560
|
-
const result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(2, 24)).map(x => x.label);
|
|
561
|
-
(0, chai_config_spec_1.expect)(result).includes('main');
|
|
562
|
-
(0, chai_config_spec_1.expect)(result).includes('foo');
|
|
563
|
-
(0, chai_config_spec_1.expect)(result).includes('Person');
|
|
564
|
-
});
|
|
565
|
-
it('gets namespace completions', () => {
|
|
566
|
-
program.setFile('source/main.bs', `
|
|
567
|
-
namespace foo.bar
|
|
568
|
-
function sayHello()
|
|
569
|
-
end function
|
|
570
|
-
end namespace
|
|
571
|
-
|
|
572
|
-
sub Main()
|
|
573
|
-
print "hello"
|
|
574
|
-
foo.ba
|
|
575
|
-
foo.bar.
|
|
576
|
-
end sub
|
|
577
|
-
`);
|
|
578
|
-
let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(8, 30));
|
|
579
|
-
let names = result.map(x => x.label);
|
|
580
|
-
(0, chai_config_spec_1.expect)(names).to.includes('bar');
|
|
581
|
-
result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(9, 32));
|
|
582
|
-
names = result.map(x => x.label);
|
|
583
|
-
(0, chai_config_spec_1.expect)(names).to.includes('sayHello');
|
|
584
|
-
});
|
|
585
|
-
});
|
|
586
|
-
it('always includes `m`', () => {
|
|
587
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
588
|
-
program.setFile('source/main.brs', `
|
|
589
|
-
sub Main()
|
|
590
|
-
|
|
591
|
-
end sub
|
|
592
|
-
`);
|
|
593
|
-
let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
|
|
594
|
-
let names = result.map(x => x.label);
|
|
595
|
-
(0, chai_config_spec_1.expect)(names).to.contain('m');
|
|
596
|
-
});
|
|
597
|
-
it('does not fail for missing previousToken', () => {
|
|
598
|
-
//add a single character to the file, and get completions after it
|
|
599
|
-
program.setFile('source/main.brs', `i`);
|
|
600
|
-
(0, chai_config_spec_1.expect)(() => {
|
|
601
|
-
program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(0, 1)).map(x => x.label);
|
|
602
|
-
}).not.to.throw;
|
|
603
|
-
});
|
|
604
|
-
it('includes all keywords`', () => {
|
|
605
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
606
|
-
program.setFile('source/main.brs', `
|
|
607
|
-
sub Main()
|
|
608
|
-
|
|
609
|
-
end sub
|
|
610
|
-
`);
|
|
611
|
-
let keywords = Object.keys(TokenKind_1.Keywords).filter(x => !x.includes(' '));
|
|
612
|
-
//inside the function
|
|
613
|
-
let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
|
|
614
|
-
let names = result.map(x => x.label);
|
|
615
|
-
for (let keyword of keywords) {
|
|
616
|
-
(0, chai_config_spec_1.expect)(names).to.include(keyword);
|
|
617
|
-
}
|
|
618
|
-
//outside the function
|
|
619
|
-
result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(4, 8));
|
|
620
|
-
names = result.map(x => x.label);
|
|
621
|
-
for (let keyword of keywords) {
|
|
622
|
-
(0, chai_config_spec_1.expect)(names).to.include(keyword);
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
it('does not provide completions within a comment', () => {
|
|
626
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
627
|
-
program.setFile('source/main.brs', `
|
|
628
|
-
sub Main()
|
|
629
|
-
'some comment
|
|
630
|
-
end sub
|
|
631
|
-
`);
|
|
632
|
-
//inside the function
|
|
633
|
-
let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 33));
|
|
634
|
-
(0, chai_config_spec_1.expect)(result).to.be.lengthOf(0);
|
|
635
|
-
});
|
|
636
|
-
it('does not provide duplicate entries for variables', () => {
|
|
637
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
638
|
-
program.setFile('source/main.brs', `
|
|
639
|
-
sub Main()
|
|
640
|
-
name = "bob"
|
|
641
|
-
age = 12
|
|
642
|
-
name = "john"
|
|
643
|
-
end sub
|
|
644
|
-
`);
|
|
645
|
-
let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 23));
|
|
646
|
-
let count = result.reduce((total, x) => {
|
|
647
|
-
return x.label === 'name' ? total + 1 : total;
|
|
648
|
-
}, 0);
|
|
649
|
-
(0, chai_config_spec_1.expect)(count).to.equal(1);
|
|
650
|
-
});
|
|
651
|
-
it('does not include `as` and `string` text options when used in function params', () => {
|
|
652
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
653
|
-
program.setFile('source/main.brs', `
|
|
654
|
-
sub Main(name as string)
|
|
655
|
-
|
|
656
|
-
end sub
|
|
657
|
-
`);
|
|
658
|
-
let result = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
|
|
659
|
-
(0, chai_config_spec_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('as');
|
|
660
|
-
(0, chai_config_spec_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('string');
|
|
661
|
-
});
|
|
662
|
-
it('does not provide intellisense results when inside a comment', () => {
|
|
663
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
664
|
-
program.setFile('source/main.brs', `
|
|
665
|
-
sub Main(name as string)
|
|
666
|
-
'this is a comment
|
|
667
|
-
end sub
|
|
668
|
-
`);
|
|
669
|
-
let results = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 30));
|
|
670
|
-
(0, chai_config_spec_1.expect)(results).to.be.empty;
|
|
671
|
-
});
|
|
672
|
-
it('does provide intellisence for labels only after a goto keyword', () => {
|
|
673
|
-
var _a;
|
|
674
|
-
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
675
|
-
program.setFile('source/main.brs', `
|
|
676
|
-
sub Main(name as string)
|
|
677
|
-
something:
|
|
678
|
-
goto \nend sub
|
|
679
|
-
`);
|
|
680
|
-
let results = program.getCompletions(`${testHelpers_spec_2.rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 25));
|
|
681
|
-
(0, chai_config_spec_1.expect)(results.length).to.equal(1);
|
|
682
|
-
(0, chai_config_spec_1.expect)((_a = results[0]) === null || _a === void 0 ? void 0 : _a.label).to.equal('something');
|
|
683
|
-
});
|
|
684
|
-
});
|
|
685
|
-
describe('comment flags', () => {
|
|
686
|
-
describe('bs:disable-next-line', () => {
|
|
687
|
-
it('disables critical diagnostic issues', () => {
|
|
688
|
-
program.setFile('source/main.brs', `
|
|
689
|
-
sub main()
|
|
690
|
-
Dim requestData
|
|
691
|
-
end sub
|
|
692
|
-
`);
|
|
693
|
-
//should have an error
|
|
694
|
-
program.validate();
|
|
695
|
-
(0, testHelpers_spec_1.expectHasDiagnostics)(program);
|
|
696
|
-
program.setFile('source/main.brs', `
|
|
697
|
-
sub main()
|
|
698
|
-
'bs:disable-next-line
|
|
699
|
-
Dim requestData
|
|
700
|
-
end sub
|
|
701
|
-
`);
|
|
702
|
-
//should not have an error
|
|
703
|
-
program.validate();
|
|
704
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
705
|
-
});
|
|
706
|
-
it('works with leading whitespace', () => {
|
|
707
|
-
program.setFile('source/main.brs', `
|
|
708
|
-
sub main()
|
|
709
|
-
' bs:disable-next-line
|
|
710
|
-
=asdf=sadf=
|
|
711
|
-
end sub
|
|
712
|
-
`);
|
|
713
|
-
//should have an error
|
|
714
|
-
program.validate();
|
|
715
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
716
|
-
});
|
|
717
|
-
it('works for all', () => {
|
|
718
|
-
let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
719
|
-
sub Main()
|
|
720
|
-
'bs:disable-next-line
|
|
721
|
-
name = "bob
|
|
722
|
-
end sub
|
|
723
|
-
`);
|
|
724
|
-
(0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
|
|
725
|
-
(0, chai_config_spec_1.expect)(file.commentFlags[0]).to.deep.include({
|
|
726
|
-
codes: null,
|
|
727
|
-
range: vscode_languageserver_1.Range.create(2, 24, 2, 45),
|
|
728
|
-
affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
|
|
729
|
-
});
|
|
730
|
-
program.validate();
|
|
731
|
-
//the "unterminated string" error should be filtered out
|
|
732
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
733
|
-
});
|
|
734
|
-
it('works for specific codes', () => {
|
|
735
|
-
let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
736
|
-
sub Main()
|
|
737
|
-
'bs:disable-next-line: 1083, 1001
|
|
738
|
-
name = "bob
|
|
739
|
-
end sub
|
|
740
|
-
`);
|
|
741
|
-
(0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
|
|
742
|
-
(0, chai_config_spec_1.expect)(file.commentFlags[0]).to.deep.include({
|
|
743
|
-
codes: [1083, 1001],
|
|
744
|
-
range: vscode_languageserver_1.Range.create(2, 24, 2, 57),
|
|
745
|
-
affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
|
|
746
|
-
});
|
|
747
|
-
//the "unterminated string" error should be filtered out
|
|
748
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
749
|
-
});
|
|
750
|
-
it('recognizes non-numeric codes', () => {
|
|
751
|
-
let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
752
|
-
sub Main()
|
|
753
|
-
'bs:disable-next-line: LINT9999
|
|
754
|
-
name = "bob
|
|
755
|
-
end sub
|
|
756
|
-
`);
|
|
757
|
-
(0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
|
|
758
|
-
(0, testHelpers_spec_1.expectHasDiagnostics)(program);
|
|
759
|
-
});
|
|
760
|
-
it('supports disabling non-numeric error codes', () => {
|
|
761
|
-
const program = new Program_1.Program({});
|
|
762
|
-
const file = program.setFile('source/main.brs', `
|
|
763
|
-
sub main()
|
|
764
|
-
something = true 'bs:disable-line: LINT1005
|
|
765
|
-
end sub
|
|
766
|
-
`);
|
|
767
|
-
file.addDiagnostics([{
|
|
768
|
-
code: 'LINT1005',
|
|
769
|
-
file: file,
|
|
770
|
-
message: 'Something is not right',
|
|
771
|
-
range: util_1.default.createRange(2, 16, 2, 26)
|
|
772
|
-
}]);
|
|
773
|
-
const scope = program.getScopesForFile(file)[0];
|
|
774
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
|
|
775
|
-
});
|
|
776
|
-
it('adds diagnostics for unknown numeric diagnostic codes', () => {
|
|
777
|
-
program.setFile('source/main.brs', `
|
|
778
|
-
sub main()
|
|
779
|
-
print "hi" 'bs:disable-line: 123456 999999 aaaab
|
|
780
|
-
end sub
|
|
781
|
-
`);
|
|
782
|
-
program.validate();
|
|
783
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownDiagnosticCode(123456)), { range: vscode_languageserver_1.Range.create(2, 53, 2, 59) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownDiagnosticCode(999999)), { range: vscode_languageserver_1.Range.create(2, 60, 2, 66) })]);
|
|
784
|
-
});
|
|
785
|
-
});
|
|
786
|
-
describe('bs:disable-line', () => {
|
|
787
|
-
it('works for all', () => {
|
|
788
|
-
let file = program.setFile({ src: `${testHelpers_spec_2.rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
789
|
-
sub Main()
|
|
790
|
-
z::;;%%%%%% 'bs:disable-line
|
|
791
|
-
end sub
|
|
792
|
-
`);
|
|
793
|
-
(0, chai_config_spec_1.expect)(file.commentFlags[0]).to.exist;
|
|
794
|
-
(0, chai_config_spec_1.expect)(file.commentFlags[0]).to.deep.include({
|
|
795
|
-
codes: null,
|
|
796
|
-
range: vscode_languageserver_1.Range.create(2, 36, 2, 52),
|
|
797
|
-
affectedRange: vscode_languageserver_1.Range.create(2, 0, 2, 36)
|
|
798
|
-
});
|
|
799
|
-
program.validate();
|
|
800
|
-
//the "unterminated string" error should be filtered out
|
|
801
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
802
|
-
});
|
|
803
|
-
it('works for specific codes', () => {
|
|
804
|
-
program.setFile('source/main.brs', `
|
|
805
|
-
sub main()
|
|
806
|
-
'should not have any errors
|
|
807
|
-
DoSomething(1) 'bs:disable-line:1002
|
|
808
|
-
'should have an error because the param-count error is not being suppressed
|
|
809
|
-
DoSomething(1) 'bs:disable-line:1000
|
|
810
|
-
end sub
|
|
811
|
-
sub DoSomething()
|
|
812
|
-
end sub
|
|
813
|
-
`);
|
|
814
|
-
program.validate();
|
|
815
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [{
|
|
816
|
-
range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
|
|
817
|
-
}]);
|
|
818
|
-
});
|
|
819
|
-
it('handles the erraneous `stop` keyword', () => {
|
|
820
|
-
//the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
|
|
821
|
-
//the program should ignore all diagnostics found in brs:* comment lines EXCEPT
|
|
822
|
-
//for the diagnostics about using unknown error codes
|
|
823
|
-
program.setFile('source/main.brs', `
|
|
824
|
-
sub main()
|
|
825
|
-
stop 'bs:disable-line
|
|
826
|
-
print "need a valid line to fix stop error"
|
|
827
|
-
end sub
|
|
828
|
-
`);
|
|
829
|
-
program.validate();
|
|
830
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
831
|
-
});
|
|
832
|
-
});
|
|
833
|
-
});
|
|
834
|
-
describe('parse', () => {
|
|
835
|
-
it('allows class as parameter type', () => {
|
|
836
|
-
program.setFile(`source/main.bs`, `
|
|
837
|
-
class Person
|
|
838
|
-
name as string
|
|
839
|
-
end class
|
|
840
|
-
|
|
841
|
-
sub PrintPerson(p as Person)
|
|
842
|
-
end sub
|
|
843
|
-
`);
|
|
844
|
-
program.validate();
|
|
845
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
846
|
-
});
|
|
847
|
-
it('allows interface as parameter type', () => {
|
|
848
|
-
program.setFile(`source/main.bs`, `
|
|
849
|
-
interface Person
|
|
850
|
-
name as string
|
|
851
|
-
end interface
|
|
852
|
-
|
|
853
|
-
sub PrintPerson(p as Person)
|
|
854
|
-
end sub
|
|
855
|
-
`);
|
|
856
|
-
program.validate();
|
|
857
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
858
|
-
});
|
|
859
|
-
it('allows enum as parameter type', () => {
|
|
860
|
-
program.setFile(`source/main.bs`, `
|
|
861
|
-
enum Direction
|
|
862
|
-
up
|
|
863
|
-
down
|
|
864
|
-
end enum
|
|
865
|
-
|
|
866
|
-
sub PrintDirection(d as Direction)
|
|
867
|
-
end sub
|
|
868
|
-
`);
|
|
869
|
-
program.validate();
|
|
870
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
871
|
-
});
|
|
872
|
-
it('supports iife in assignment', () => {
|
|
873
|
-
program.setFile('source/main.brs', `
|
|
874
|
-
sub main()
|
|
875
|
-
result = sub()
|
|
876
|
-
end sub()
|
|
877
|
-
result = (sub()
|
|
878
|
-
end sub)()
|
|
879
|
-
end sub
|
|
880
|
-
`);
|
|
881
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
882
|
-
});
|
|
883
|
-
it('uses the proper parse mode based on file extension', () => {
|
|
884
|
-
function testParseMode(destPath, expectedParseMode) {
|
|
885
|
-
const file = program.setFile(destPath, '');
|
|
886
|
-
(0, chai_config_spec_1.expect)(file.parseMode).to.equal(expectedParseMode);
|
|
887
|
-
}
|
|
888
|
-
testParseMode('source/main.brs', Parser_1.ParseMode.BrightScript);
|
|
889
|
-
testParseMode('source/main.spec.brs', Parser_1.ParseMode.BrightScript);
|
|
890
|
-
testParseMode('source/main.d.brs', Parser_1.ParseMode.BrightScript);
|
|
891
|
-
testParseMode('source/main.bs', Parser_1.ParseMode.BrighterScript);
|
|
892
|
-
testParseMode('source/main.d.bs', Parser_1.ParseMode.BrighterScript);
|
|
893
|
-
testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
|
|
894
|
-
});
|
|
895
|
-
it('supports labels and goto statements', () => {
|
|
896
|
-
let file = program.setFile('source/main.brs', `
|
|
897
|
-
sub Main()
|
|
898
|
-
'multiple goto statements on one line
|
|
899
|
-
goto myLabel : goto myLabel
|
|
900
|
-
myLabel:
|
|
901
|
-
end sub
|
|
902
|
-
`);
|
|
903
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
904
|
-
});
|
|
905
|
-
it('supports empty print statements', () => {
|
|
906
|
-
let file = program.setFile('source/main.brs', `
|
|
907
|
-
sub main()
|
|
908
|
-
print
|
|
909
|
-
end sub
|
|
910
|
-
`);
|
|
911
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
912
|
-
});
|
|
913
|
-
describe('conditional compile', () => {
|
|
914
|
-
it('supports whitespace-separated directives', () => {
|
|
915
|
-
const file = program.setFile('source/main.bs', `
|
|
916
|
-
sub main()
|
|
917
|
-
#\t const thing=true
|
|
918
|
-
#\t if thing
|
|
919
|
-
print "if"
|
|
920
|
-
#\t elseif false
|
|
921
|
-
print "elseif"
|
|
922
|
-
#\t error crash
|
|
923
|
-
#\t else
|
|
924
|
-
print "else"
|
|
925
|
-
#\t endif
|
|
926
|
-
end sub
|
|
927
|
-
`);
|
|
928
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
929
|
-
testTranspile(file.fileContents, `
|
|
930
|
-
sub main()
|
|
931
|
-
print "if"
|
|
932
|
-
end sub
|
|
933
|
-
`);
|
|
934
|
-
});
|
|
935
|
-
it('supports case-insensitive bs_const variables', () => {
|
|
936
|
-
fsExtra.outputFileSync(`${testHelpers_spec_2.rootDir}/manifest`, (0, undent_1.default) `
|
|
937
|
-
bs_const=SomeKey=true
|
|
938
|
-
`);
|
|
939
|
-
program.setFile('source/main.brs', `
|
|
940
|
-
sub something()
|
|
941
|
-
#if somekey
|
|
942
|
-
print "lower"
|
|
943
|
-
#end if
|
|
944
|
-
#if SOMEKEY
|
|
945
|
-
print "UPPER"
|
|
946
|
-
#end if
|
|
947
|
-
#if SomeKey
|
|
948
|
-
print "MiXeD"
|
|
949
|
-
#end if
|
|
950
|
-
end sub
|
|
951
|
-
`);
|
|
952
|
-
program.validate();
|
|
953
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
954
|
-
});
|
|
955
|
-
it('works for upper case keywords', () => {
|
|
956
|
-
let file = program.setFile('source/main.brs', `
|
|
957
|
-
sub main()
|
|
958
|
-
#CONST someFlag = true
|
|
959
|
-
#IF someFlag
|
|
960
|
-
'code to execute when someFlag is true
|
|
961
|
-
#ELSEIF someFlag
|
|
962
|
-
'code to execute when anotherFlag is true
|
|
963
|
-
#ELSE
|
|
964
|
-
'code
|
|
965
|
-
#ENDIF
|
|
966
|
-
end sub
|
|
967
|
-
`);
|
|
968
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
969
|
-
});
|
|
970
|
-
it('supports single-word #elseif and #endif', () => {
|
|
971
|
-
let file = program.setFile('source/main.brs', `
|
|
972
|
-
sub main()
|
|
973
|
-
#const someFlag = true
|
|
974
|
-
#if someFlag
|
|
975
|
-
'code to execute when someFlag is true
|
|
976
|
-
#elseif someFlag
|
|
977
|
-
'code to execute when anotherFlag is true
|
|
978
|
-
#endif
|
|
979
|
-
end sub
|
|
980
|
-
`);
|
|
981
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
982
|
-
});
|
|
983
|
-
it('supports multi-word #else if and #end if', () => {
|
|
984
|
-
let file = program.setFile('source/main.brs', `
|
|
985
|
-
sub main()
|
|
986
|
-
#const someFlag = true
|
|
987
|
-
#if someFlag
|
|
988
|
-
'code to execute when someFlag is true
|
|
989
|
-
#else if someFlag
|
|
990
|
-
'code to execute when anotherFlag is true
|
|
991
|
-
#end if
|
|
992
|
-
end sub
|
|
993
|
-
`);
|
|
994
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
995
|
-
});
|
|
996
|
-
it('does not choke on invalid code inside a false conditional compile', () => {
|
|
997
|
-
let file = program.setFile('source/main.brs', `
|
|
998
|
-
sub main()
|
|
999
|
-
#if false
|
|
1000
|
-
non-commented code here should not cause parse errors
|
|
1001
|
-
#end if
|
|
1002
|
-
end sub
|
|
1003
|
-
`);
|
|
1004
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1005
|
-
});
|
|
1006
|
-
it('detects syntax error in #if', () => {
|
|
1007
|
-
let file = program.setFile('source/main.brs', `
|
|
1008
|
-
sub main()
|
|
1009
|
-
#if true1
|
|
1010
|
-
print "true"
|
|
1011
|
-
#end if
|
|
1012
|
-
end sub
|
|
1013
|
-
`);
|
|
1014
|
-
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
1015
|
-
DiagnosticMessages_1.DiagnosticMessages.referencedConstDoesNotExist()
|
|
1016
|
-
]);
|
|
1017
|
-
});
|
|
1018
|
-
it('detects syntax error in #const', () => {
|
|
1019
|
-
let file = program.setFile('source/main.brs', `
|
|
1020
|
-
sub main()
|
|
1021
|
-
#if %
|
|
1022
|
-
print "true"
|
|
1023
|
-
#end if
|
|
1024
|
-
end sub
|
|
1025
|
-
`);
|
|
1026
|
-
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
1027
|
-
DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%'),
|
|
1028
|
-
DiagnosticMessages_1.DiagnosticMessages.invalidHashIfValue()
|
|
1029
|
-
]);
|
|
1030
|
-
});
|
|
1031
|
-
it('detects #const name using reserved word', () => {
|
|
1032
|
-
let file = program.setFile('source/main.brs', `
|
|
1033
|
-
sub main()
|
|
1034
|
-
#const function = true
|
|
1035
|
-
end sub
|
|
1036
|
-
`);
|
|
1037
|
-
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
1038
|
-
DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord(),
|
|
1039
|
-
DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('#const')
|
|
1040
|
-
]);
|
|
1041
|
-
});
|
|
1042
|
-
it('detects syntax error in #const', () => {
|
|
1043
|
-
let file = program.setFile('source/main.brs', `
|
|
1044
|
-
sub main()
|
|
1045
|
-
#const someConst = 123
|
|
1046
|
-
end sub
|
|
1047
|
-
`);
|
|
1048
|
-
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
1049
|
-
DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()
|
|
1050
|
-
]);
|
|
1051
|
-
});
|
|
1052
|
-
});
|
|
1053
|
-
it('supports stop statement', () => {
|
|
1054
|
-
let file = program.setFile('source/main.brs', `
|
|
1055
|
-
sub main()
|
|
1056
|
-
stop
|
|
1057
|
-
end sub
|
|
1058
|
-
`);
|
|
1059
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1060
|
-
});
|
|
1061
|
-
it('supports single-line if statements', () => {
|
|
1062
|
-
let file = program.setFile('source/main.brs', `
|
|
1063
|
-
sub main()
|
|
1064
|
-
if 1 < 2: return true: end if
|
|
1065
|
-
if 1 < 2: return true
|
|
1066
|
-
end if
|
|
1067
|
-
if false : print "true" : end if
|
|
1068
|
-
if true: print "8 worked": else if true: print "not run": else: print "not run": end if
|
|
1069
|
-
if true then : test = sub() : print "yes" : end sub : end if
|
|
1070
|
-
end sub
|
|
1071
|
-
`);
|
|
1072
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1073
|
-
});
|
|
1074
|
-
it('supports line_num as global variable', () => {
|
|
1075
|
-
file.parse(`
|
|
1076
|
-
sub Main()
|
|
1077
|
-
print LINE_NUM
|
|
1078
|
-
end sub
|
|
1079
|
-
`);
|
|
1080
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1081
|
-
});
|
|
1082
|
-
it('supports many keywords as object property names', () => {
|
|
1083
|
-
file.parse(`
|
|
1084
|
-
sub Main()
|
|
1085
|
-
person = {}
|
|
1086
|
-
person.and = true
|
|
1087
|
-
person.box = true
|
|
1088
|
-
person.createobject = true
|
|
1089
|
-
person.dim = true
|
|
1090
|
-
person.double = true
|
|
1091
|
-
person.each = true
|
|
1092
|
-
person.else = true
|
|
1093
|
-
person.elseif = true
|
|
1094
|
-
person.end = true
|
|
1095
|
-
person.endfor = true
|
|
1096
|
-
person.endfunction = true
|
|
1097
|
-
person.endif = true
|
|
1098
|
-
person.endsub = true
|
|
1099
|
-
person.endwhile = true
|
|
1100
|
-
person.eval = true
|
|
1101
|
-
person.exit = true
|
|
1102
|
-
person.exitfor = true
|
|
1103
|
-
person.exitwhile = true
|
|
1104
|
-
person.false = true
|
|
1105
|
-
person.float = true
|
|
1106
|
-
person.for = true
|
|
1107
|
-
person.foreach = true
|
|
1108
|
-
person.function = true
|
|
1109
|
-
person.getglobalaa = true
|
|
1110
|
-
person.getlastruncompileerror = true
|
|
1111
|
-
person.getlastrunruntimeerror = true
|
|
1112
|
-
person.goto = true
|
|
1113
|
-
person.if = true
|
|
1114
|
-
person.integer = true
|
|
1115
|
-
person.invalid = true
|
|
1116
|
-
person.let = true
|
|
1117
|
-
person.line_num = true
|
|
1118
|
-
person.longinteger = true
|
|
1119
|
-
person.next = true
|
|
1120
|
-
person.not = true
|
|
1121
|
-
person.objfun = true
|
|
1122
|
-
person.or = true
|
|
1123
|
-
person.pos = true
|
|
1124
|
-
person.print = true
|
|
1125
|
-
person.rem = true
|
|
1126
|
-
person.return = true
|
|
1127
|
-
person.run = true
|
|
1128
|
-
person.step = true
|
|
1129
|
-
person.stop = true
|
|
1130
|
-
person.string = true
|
|
1131
|
-
person.sub = true
|
|
1132
|
-
person.tab = true
|
|
1133
|
-
person.then = true
|
|
1134
|
-
person.to = true
|
|
1135
|
-
person.true = true
|
|
1136
|
-
person.type = true
|
|
1137
|
-
person.while = true
|
|
1138
|
-
person.public = true
|
|
1139
|
-
person.protected = true
|
|
1140
|
-
person.private = true
|
|
1141
|
-
person.class = true
|
|
1142
|
-
person.override = true
|
|
1143
|
-
person.new = true
|
|
1144
|
-
end sub
|
|
1145
|
-
`);
|
|
1146
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1147
|
-
});
|
|
1148
|
-
it('does not error on numeric literal type designators', () => {
|
|
1149
|
-
file.parse(`
|
|
1150
|
-
sub main()
|
|
1151
|
-
print &he2
|
|
1152
|
-
print 1.2E+2
|
|
1153
|
-
print 2!
|
|
1154
|
-
print 12D-12
|
|
1155
|
-
print 2.3#
|
|
1156
|
-
print &hFEDCBA9876543210&
|
|
1157
|
-
print 9876543210&
|
|
1158
|
-
end sub
|
|
1159
|
-
`);
|
|
1160
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1161
|
-
});
|
|
1162
|
-
it('does not error when encountering sub with return type', () => {
|
|
1163
|
-
file.parse(`
|
|
1164
|
-
sub main() as integer
|
|
1165
|
-
return
|
|
1166
|
-
end sub
|
|
1167
|
-
`);
|
|
1168
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1169
|
-
});
|
|
1170
|
-
it('does not lose function scopes when mismatched end sub', () => {
|
|
1171
|
-
file.parse(`
|
|
1172
|
-
sub main()
|
|
1173
|
-
sayHi()
|
|
1174
|
-
end function
|
|
1175
|
-
|
|
1176
|
-
sub sayHi()
|
|
1177
|
-
print "hello world"
|
|
1178
|
-
end sub
|
|
1179
|
-
`);
|
|
1180
|
-
(0, chai_config_spec_1.expect)(file.functionScopes).to.be.lengthOf(2);
|
|
1181
|
-
});
|
|
1182
|
-
it('does not lose sub scope when mismatched end function', () => {
|
|
1183
|
-
file.parse(`
|
|
1184
|
-
function main()
|
|
1185
|
-
sayHi()
|
|
1186
|
-
end sub
|
|
1187
|
-
|
|
1188
|
-
sub sayHi()
|
|
1189
|
-
print "hello world"
|
|
1190
|
-
end sub
|
|
1191
|
-
`);
|
|
1192
|
-
(0, chai_config_spec_1.expect)(file.functionScopes).to.be.lengthOf(2);
|
|
1193
|
-
});
|
|
1194
|
-
it('does not error with boolean in RHS of set statement', () => {
|
|
1195
|
-
file.parse(`
|
|
1196
|
-
sub main()
|
|
1197
|
-
foo = {
|
|
1198
|
-
bar: false
|
|
1199
|
-
}
|
|
1200
|
-
foo.bar = true and false or 3 > 4
|
|
1201
|
-
end sub
|
|
1202
|
-
`);
|
|
1203
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1204
|
-
});
|
|
1205
|
-
it('does not error with boolean in RHS of set statement', () => {
|
|
1206
|
-
file.parse(`
|
|
1207
|
-
sub main()
|
|
1208
|
-
m = {
|
|
1209
|
-
isTrue: false
|
|
1210
|
-
}
|
|
1211
|
-
m.isTrue = true = true
|
|
1212
|
-
m.isTrue = m.isTrue = true
|
|
1213
|
-
m.isTrue = m.isTrue = m.isTrue
|
|
1214
|
-
end sub
|
|
1215
|
-
`);
|
|
1216
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1217
|
-
});
|
|
1218
|
-
it('supports variable names ending with type designators', () => {
|
|
1219
|
-
file.parse(`
|
|
1220
|
-
sub main()
|
|
1221
|
-
name$ = "bob"
|
|
1222
|
-
age% = 1
|
|
1223
|
-
height! = 5.5
|
|
1224
|
-
salary# = 9.87654321
|
|
1225
|
-
someHex& = 13
|
|
1226
|
-
end sub
|
|
1227
|
-
`);
|
|
1228
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1229
|
-
});
|
|
1230
|
-
it('supports multiple spaces between two-word keywords', () => {
|
|
1231
|
-
file.parse(`
|
|
1232
|
-
sub main()
|
|
1233
|
-
if true then
|
|
1234
|
-
print "true"
|
|
1235
|
-
else if true then
|
|
1236
|
-
print "also true"
|
|
1237
|
-
end if
|
|
1238
|
-
end sub
|
|
1239
|
-
`);
|
|
1240
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1241
|
-
});
|
|
1242
|
-
it('does not error with `stop` as object key', () => {
|
|
1243
|
-
file.parse(`
|
|
1244
|
-
function GetObject()
|
|
1245
|
-
obj = {
|
|
1246
|
-
stop: function() as void
|
|
1247
|
-
|
|
1248
|
-
end function
|
|
1249
|
-
}
|
|
1250
|
-
return obj
|
|
1251
|
-
end function
|
|
1252
|
-
`);
|
|
1253
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1254
|
-
});
|
|
1255
|
-
it('does not error with `run` as object key', () => {
|
|
1256
|
-
file.parse(`
|
|
1257
|
-
function GetObject()
|
|
1258
|
-
obj = {
|
|
1259
|
-
run: function() as void
|
|
1260
|
-
|
|
1261
|
-
end function
|
|
1262
|
-
}
|
|
1263
|
-
return obj
|
|
1264
|
-
end function
|
|
1265
|
-
`);
|
|
1266
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1267
|
-
});
|
|
1268
|
-
it('supports assignment operators', () => {
|
|
1269
|
-
file.parse(`
|
|
1270
|
-
function Main()
|
|
1271
|
-
x = 1
|
|
1272
|
-
x += 1
|
|
1273
|
-
x += 2
|
|
1274
|
-
x -= 1
|
|
1275
|
-
x /= 2
|
|
1276
|
-
x = 9
|
|
1277
|
-
x \\= 2
|
|
1278
|
-
x *= 3.0
|
|
1279
|
-
x -= 1
|
|
1280
|
-
print x
|
|
1281
|
-
end function
|
|
1282
|
-
`);
|
|
1283
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1284
|
-
});
|
|
1285
|
-
it('supports `then` as object property', () => {
|
|
1286
|
-
file.parse(`
|
|
1287
|
-
function Main()
|
|
1288
|
-
promise = {
|
|
1289
|
-
then: sub()
|
|
1290
|
-
end sub
|
|
1291
|
-
}
|
|
1292
|
-
promise.then()
|
|
1293
|
-
end function
|
|
1294
|
-
`);
|
|
1295
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1296
|
-
});
|
|
1297
|
-
it('supports function as parameter type', () => {
|
|
1298
|
-
file.parse(`
|
|
1299
|
-
sub Main()
|
|
1300
|
-
doWork = function(callback as function)
|
|
1301
|
-
end function
|
|
1302
|
-
end sub
|
|
1303
|
-
`);
|
|
1304
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1305
|
-
});
|
|
1306
|
-
it('supports increment operator', () => {
|
|
1307
|
-
file.parse(`
|
|
1308
|
-
function Main()
|
|
1309
|
-
x = 3
|
|
1310
|
-
x++
|
|
1311
|
-
end function
|
|
1312
|
-
`);
|
|
1313
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1314
|
-
});
|
|
1315
|
-
it('supports decrement operator', () => {
|
|
1316
|
-
file.parse(`
|
|
1317
|
-
function Main()
|
|
1318
|
-
x = 3
|
|
1319
|
-
x--
|
|
1320
|
-
end function
|
|
1321
|
-
`);
|
|
1322
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1323
|
-
});
|
|
1324
|
-
it('supports writing numbers with decimal but no trailing digit', () => {
|
|
1325
|
-
file.parse(`
|
|
1326
|
-
function Main()
|
|
1327
|
-
x = 3.
|
|
1328
|
-
print x
|
|
1329
|
-
end function
|
|
1330
|
-
`);
|
|
1331
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1332
|
-
});
|
|
1333
|
-
it('supports assignment operators against object properties', () => {
|
|
1334
|
-
file.parse(`
|
|
1335
|
-
function Main()
|
|
1336
|
-
m.age = 1
|
|
1337
|
-
|
|
1338
|
-
m.age += 1
|
|
1339
|
-
m.age -= 1
|
|
1340
|
-
m.age *= 1
|
|
1341
|
-
m.age /= 1
|
|
1342
|
-
m.age \\= 1
|
|
1343
|
-
|
|
1344
|
-
m["age"] += 1
|
|
1345
|
-
m["age"] -= 1
|
|
1346
|
-
m["age"] *= 1
|
|
1347
|
-
m["age"] /= 1
|
|
1348
|
-
m["age"] \\= 1
|
|
1349
|
-
|
|
1350
|
-
print m.age
|
|
1351
|
-
end function
|
|
1352
|
-
`);
|
|
1353
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1354
|
-
});
|
|
1355
|
-
//skipped until `brs` supports this
|
|
1356
|
-
it('supports bitshift assignment operators', () => {
|
|
1357
|
-
file.parse(`
|
|
1358
|
-
function Main()
|
|
1359
|
-
x = 1
|
|
1360
|
-
x <<= 8
|
|
1361
|
-
x >>= 4
|
|
1362
|
-
print x
|
|
1363
|
-
end function
|
|
1364
|
-
`);
|
|
1365
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1366
|
-
});
|
|
1367
|
-
//skipped until `brs` supports this
|
|
1368
|
-
it('supports bitshift assignment operators on objects', () => {
|
|
1369
|
-
file.parse(`
|
|
1370
|
-
function Main()
|
|
1371
|
-
m.x = 1
|
|
1372
|
-
m.x <<= 1
|
|
1373
|
-
m.x >>= 1
|
|
1374
|
-
print m.x
|
|
1375
|
-
end function
|
|
1376
|
-
`);
|
|
1377
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1378
|
-
});
|
|
1379
|
-
it('supports leading and trailing periods for numeric literals', () => {
|
|
1380
|
-
file.parse(`
|
|
1381
|
-
function Main()
|
|
1382
|
-
one = 1.
|
|
1383
|
-
print one
|
|
1384
|
-
pointOne = .1
|
|
1385
|
-
print pointOne
|
|
1386
|
-
end function
|
|
1387
|
-
`);
|
|
1388
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1389
|
-
});
|
|
1390
|
-
it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
|
|
1391
|
-
file.parse(`
|
|
1392
|
-
function Main()
|
|
1393
|
-
m.x = 1
|
|
1394
|
-
'm['x'] << 1
|
|
1395
|
-
'm['x'] >> 1
|
|
1396
|
-
print m.x
|
|
1397
|
-
end function
|
|
1398
|
-
`);
|
|
1399
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1400
|
-
});
|
|
1401
|
-
it('supports weird period AA accessor', () => {
|
|
1402
|
-
file.parse(`
|
|
1403
|
-
function Main()
|
|
1404
|
-
m._uuid = "123"
|
|
1405
|
-
print m.["_uuid"]
|
|
1406
|
-
end function
|
|
1407
|
-
`);
|
|
1408
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1409
|
-
});
|
|
1410
|
-
it('adds error for library statements NOT at top of file', () => {
|
|
1411
|
-
program.setFile('source/file.brs', ``);
|
|
1412
|
-
program.setFile('source/main.bs', `
|
|
1413
|
-
sub main()
|
|
1414
|
-
end sub
|
|
1415
|
-
import "file.brs"
|
|
1416
|
-
`);
|
|
1417
|
-
program.validate();
|
|
1418
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1419
|
-
DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
|
|
1420
|
-
]);
|
|
1421
|
-
});
|
|
1422
|
-
it('supports library imports', () => {
|
|
1423
|
-
program.setFile('source/main.brs', `
|
|
1424
|
-
Library "v30/bslCore.brs"
|
|
1425
|
-
`);
|
|
1426
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
1427
|
-
});
|
|
1428
|
-
it('adds error for library statements NOT at top of file', () => {
|
|
1429
|
-
program.setFile('source/main.brs', `
|
|
1430
|
-
sub main()
|
|
1431
|
-
end sub
|
|
1432
|
-
Library "v30/bslCore.brs"
|
|
1433
|
-
`);
|
|
1434
|
-
program.validate();
|
|
1435
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1436
|
-
DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
|
|
1437
|
-
]);
|
|
1438
|
-
});
|
|
1439
|
-
it('adds error for library statements inside of function body', () => {
|
|
1440
|
-
program.setFile('source/main.brs', `
|
|
1441
|
-
sub main()
|
|
1442
|
-
Library "v30/bslCore.brs"
|
|
1443
|
-
end sub
|
|
1444
|
-
`);
|
|
1445
|
-
program.validate();
|
|
1446
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1447
|
-
DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
|
|
1448
|
-
]);
|
|
1449
|
-
});
|
|
1450
|
-
it('supports colons as separators in associative array properties', () => {
|
|
1451
|
-
file.parse(`
|
|
1452
|
-
sub Main()
|
|
1453
|
-
obj = {x:0 : y: 1}
|
|
1454
|
-
end sub
|
|
1455
|
-
`);
|
|
1456
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1457
|
-
});
|
|
1458
|
-
it('succeeds when finding variables with "sub" in them', () => {
|
|
1459
|
-
let file = program.setFile('source/main.brs', `
|
|
1460
|
-
function DoSomething()
|
|
1461
|
-
return value.subType()
|
|
1462
|
-
end function
|
|
1463
|
-
`);
|
|
1464
|
-
(0, chai_config_spec_1.expect)(file.callables[0]).to.deep.include({
|
|
1465
|
-
file: file,
|
|
1466
|
-
nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36)
|
|
1467
|
-
});
|
|
1468
|
-
});
|
|
1469
|
-
it('succeeds when finding variables with the word "function" in them', () => {
|
|
1470
|
-
file.parse(`
|
|
1471
|
-
function Test()
|
|
1472
|
-
typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
|
|
1473
|
-
end function
|
|
1474
|
-
`);
|
|
1475
|
-
});
|
|
1476
|
-
it('finds line and column numbers for functions', () => {
|
|
1477
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1478
|
-
file.parse(`
|
|
1479
|
-
function DoA()
|
|
1480
|
-
print "A"
|
|
1481
|
-
end function
|
|
1482
|
-
|
|
1483
|
-
function DoB()
|
|
1484
|
-
print "B"
|
|
1485
|
-
end function
|
|
1486
|
-
`);
|
|
1487
|
-
(0, chai_config_spec_1.expect)(file.callables[0].name).to.equal('DoA');
|
|
1488
|
-
(0, chai_config_spec_1.expect)(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
|
|
1489
|
-
(0, chai_config_spec_1.expect)(file.callables[1].name).to.equal('DoB');
|
|
1490
|
-
(0, chai_config_spec_1.expect)(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 26, 5, 29));
|
|
1491
|
-
});
|
|
1492
|
-
it('throws an error if the file has already been parsed', () => {
|
|
1493
|
-
let file = new BrsFile_1.BrsFile('abspath', 'relpath', program);
|
|
1494
|
-
file.parse(`'a comment`);
|
|
1495
|
-
try {
|
|
1496
|
-
file.parse(`'a new comment`);
|
|
1497
|
-
chai_config_spec_1.assert.fail(null, null, 'Should have thrown an exception, but did not');
|
|
1498
|
-
}
|
|
1499
|
-
catch (e) {
|
|
1500
|
-
//test passes
|
|
1501
|
-
}
|
|
1502
|
-
});
|
|
1503
|
-
it('finds and registers duplicate callables', () => {
|
|
1504
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1505
|
-
file.parse(`
|
|
1506
|
-
function DoA()
|
|
1507
|
-
print "A"
|
|
1508
|
-
end function
|
|
1509
|
-
|
|
1510
|
-
function DoA()
|
|
1511
|
-
print "A"
|
|
1512
|
-
end function
|
|
1513
|
-
`);
|
|
1514
|
-
(0, chai_config_spec_1.expect)(file.callables.length).to.equal(2);
|
|
1515
|
-
(0, chai_config_spec_1.expect)(file.callables[0].name).to.equal('DoA');
|
|
1516
|
-
(0, chai_config_spec_1.expect)(file.callables[0].nameRange.start.line).to.equal(1);
|
|
1517
|
-
(0, chai_config_spec_1.expect)(file.callables[1].name).to.equal('DoA');
|
|
1518
|
-
(0, chai_config_spec_1.expect)(file.callables[1].nameRange.start.line).to.equal(5);
|
|
1519
|
-
});
|
|
1520
|
-
it('finds function call line and column numbers', () => {
|
|
1521
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1522
|
-
file.parse(`
|
|
1523
|
-
function DoA()
|
|
1524
|
-
DoB("a")
|
|
1525
|
-
end function
|
|
1526
|
-
function DoB(a as string)
|
|
1527
|
-
DoC()
|
|
1528
|
-
end function
|
|
1529
|
-
`);
|
|
1530
|
-
(0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(2);
|
|
1531
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 28));
|
|
1532
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
|
|
1533
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 25));
|
|
1534
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
|
|
1535
|
-
});
|
|
1536
|
-
it('finds function calls that are unfinished', () => {
|
|
1537
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1538
|
-
file.parse(`
|
|
1539
|
-
function DoA()
|
|
1540
|
-
DoB("a"
|
|
1541
|
-
end function
|
|
1542
|
-
function DoB(a as string)
|
|
1543
|
-
DoC(
|
|
1544
|
-
end function
|
|
1545
|
-
`);
|
|
1546
|
-
(0, testHelpers_spec_1.expectDiagnostics)(file.parser.diagnostics, [
|
|
1547
|
-
DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
|
|
1548
|
-
DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(),
|
|
1549
|
-
DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('\n')
|
|
1550
|
-
]);
|
|
1551
|
-
(0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(2);
|
|
1552
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 27));
|
|
1553
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
|
|
1554
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 24));
|
|
1555
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
|
|
1556
|
-
});
|
|
1557
|
-
it('sanitizes brs errors', () => {
|
|
1558
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1559
|
-
file.parse(`
|
|
1560
|
-
function DoSomething
|
|
1561
|
-
end function
|
|
1562
|
-
`);
|
|
1563
|
-
(0, testHelpers_spec_1.expectHasDiagnostics)(file);
|
|
1564
|
-
(0, chai_config_spec_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
|
|
1565
|
-
(0, chai_config_spec_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
|
|
1566
|
-
});
|
|
1567
|
-
it('supports using the `next` keyword in a for loop', () => {
|
|
1568
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1569
|
-
file.parse(`
|
|
1570
|
-
sub countit()
|
|
1571
|
-
for each num in [1,2,3]
|
|
1572
|
-
print num
|
|
1573
|
-
next
|
|
1574
|
-
end sub
|
|
1575
|
-
`);
|
|
1576
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1577
|
-
});
|
|
1578
|
-
//test is not working yet, but will be enabled when brs supports this syntax
|
|
1579
|
-
it('supports assigning functions to objects', () => {
|
|
1580
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1581
|
-
file.parse(`
|
|
1582
|
-
function main()
|
|
1583
|
-
o = CreateObject("roAssociativeArray")
|
|
1584
|
-
o.sayHello = sub()
|
|
1585
|
-
print "hello"
|
|
1586
|
-
end sub
|
|
1587
|
-
end function
|
|
1588
|
-
`);
|
|
1589
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1590
|
-
});
|
|
1591
|
-
});
|
|
1592
|
-
describe('findCallables', () => {
|
|
1593
|
-
it('finds range', () => {
|
|
1594
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1595
|
-
file.parse(`
|
|
1596
|
-
sub Sum()
|
|
1597
|
-
print "hello world"
|
|
1598
|
-
end sub
|
|
1599
|
-
`);
|
|
1600
|
-
let callable = file.callables[0];
|
|
1601
|
-
(0, chai_config_spec_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
|
|
1602
|
-
});
|
|
1603
|
-
it('finds correct body range even with inner function', () => {
|
|
1604
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1605
|
-
file.parse(`
|
|
1606
|
-
sub Sum()
|
|
1607
|
-
sayHi = sub()
|
|
1608
|
-
print "Hi"
|
|
1609
|
-
end sub
|
|
1610
|
-
sayHi()
|
|
1611
|
-
end sub
|
|
1612
|
-
`);
|
|
1613
|
-
let callable = file.callables[0];
|
|
1614
|
-
(0, chai_config_spec_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 6, 23));
|
|
1615
|
-
});
|
|
1616
|
-
it('finds callable parameters', () => {
|
|
1617
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1618
|
-
file.parse(`
|
|
1619
|
-
function Sum(a, b, c)
|
|
1620
|
-
|
|
1621
|
-
end function
|
|
1622
|
-
`);
|
|
1623
|
-
let callable = file.callables[0];
|
|
1624
|
-
(0, chai_config_spec_1.expect)(callable.params[0]).to.deep.include({
|
|
1625
|
-
name: 'a',
|
|
1626
|
-
isOptional: false,
|
|
1627
|
-
isRestArgument: false
|
|
1628
|
-
});
|
|
1629
|
-
(0, chai_config_spec_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
|
|
1630
|
-
(0, chai_config_spec_1.expect)(callable.params[1]).to.deep.include({
|
|
1631
|
-
name: 'b',
|
|
1632
|
-
isOptional: false,
|
|
1633
|
-
isRestArgument: false
|
|
1634
|
-
});
|
|
1635
|
-
(0, chai_config_spec_1.expect)(callable.params[1].type).instanceof(DynamicType_1.DynamicType);
|
|
1636
|
-
(0, chai_config_spec_1.expect)(callable.params[2]).to.deep.include({
|
|
1637
|
-
name: 'c',
|
|
1638
|
-
isOptional: false,
|
|
1639
|
-
isRestArgument: false
|
|
1640
|
-
});
|
|
1641
|
-
(0, chai_config_spec_1.expect)(callable.params[2].type).instanceof(DynamicType_1.DynamicType);
|
|
1642
|
-
});
|
|
1643
|
-
it('finds optional parameters', () => {
|
|
1644
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1645
|
-
file.parse(`
|
|
1646
|
-
function Sum(a=2)
|
|
1647
|
-
|
|
1648
|
-
end function
|
|
1649
|
-
`);
|
|
1650
|
-
let callable = file.callables[0];
|
|
1651
|
-
(0, chai_config_spec_1.expect)(callable.params[0]).to.deep.include({
|
|
1652
|
-
name: 'a',
|
|
1653
|
-
isOptional: true,
|
|
1654
|
-
isRestArgument: false
|
|
1655
|
-
});
|
|
1656
|
-
(0, chai_config_spec_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
|
|
1657
|
-
});
|
|
1658
|
-
it('finds parameter types', () => {
|
|
1659
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1660
|
-
file.parse(`
|
|
1661
|
-
function Sum(a, b as integer, c as string)
|
|
1662
|
-
|
|
1663
|
-
end function
|
|
1664
|
-
`);
|
|
1665
|
-
let callable = file.callables[0];
|
|
1666
|
-
(0, chai_config_spec_1.expect)(callable.params[0]).to.deep.include({
|
|
1667
|
-
name: 'a',
|
|
1668
|
-
isOptional: false,
|
|
1669
|
-
isRestArgument: false
|
|
1670
|
-
});
|
|
1671
|
-
(0, chai_config_spec_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
|
|
1672
|
-
(0, chai_config_spec_1.expect)(callable.params[1]).to.deep.include({
|
|
1673
|
-
name: 'b',
|
|
1674
|
-
isOptional: false,
|
|
1675
|
-
isRestArgument: false
|
|
1676
|
-
});
|
|
1677
|
-
(0, chai_config_spec_1.expect)(callable.params[1].type).instanceof(IntegerType_1.IntegerType);
|
|
1678
|
-
(0, chai_config_spec_1.expect)(callable.params[2]).to.deep.include({
|
|
1679
|
-
name: 'c',
|
|
1680
|
-
isOptional: false,
|
|
1681
|
-
isRestArgument: false
|
|
1682
|
-
});
|
|
1683
|
-
(0, chai_config_spec_1.expect)(callable.params[2].type).instanceof(StringType_1.StringType);
|
|
1684
|
-
});
|
|
1685
|
-
});
|
|
1686
|
-
describe('findCallableInvocations', () => {
|
|
1687
|
-
it('finds arguments with literal values', () => {
|
|
1688
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1689
|
-
file.parse(`
|
|
1690
|
-
function Sum()
|
|
1691
|
-
DoSomething("name", 12, true)
|
|
1692
|
-
end function
|
|
1693
|
-
`);
|
|
1694
|
-
(0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(1);
|
|
1695
|
-
const argsMap = file.functionCalls[0].args.map(arg => {
|
|
1696
|
-
// disregard arg.expression, etc.
|
|
1697
|
-
return { type: arg.type, range: arg.range, text: arg.text };
|
|
1698
|
-
});
|
|
1699
|
-
(0, chai_config_spec_1.expect)(argsMap).to.eql([{
|
|
1700
|
-
type: new StringType_1.StringType(),
|
|
1701
|
-
range: util_1.default.createRange(2, 32, 2, 38),
|
|
1702
|
-
text: '"name"'
|
|
1703
|
-
}, {
|
|
1704
|
-
type: new IntegerType_1.IntegerType(),
|
|
1705
|
-
range: util_1.default.createRange(2, 40, 2, 42),
|
|
1706
|
-
text: '12'
|
|
1707
|
-
}, {
|
|
1708
|
-
type: new BooleanType_1.BooleanType(),
|
|
1709
|
-
range: util_1.default.createRange(2, 44, 2, 48),
|
|
1710
|
-
text: 'true'
|
|
1711
|
-
}]);
|
|
1712
|
-
});
|
|
1713
|
-
it('finds function calls nested inside statements', () => {
|
|
1714
|
-
program.setFile(`source/main.brs`, `
|
|
1715
|
-
sub main()
|
|
1716
|
-
if true then
|
|
1717
|
-
DoesNotExist(1, 2)
|
|
1718
|
-
end if
|
|
1719
|
-
end sub
|
|
1720
|
-
`);
|
|
1721
|
-
program.validate();
|
|
1722
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1723
|
-
DiagnosticMessages_1.DiagnosticMessages.cannotFindFunction('DoesNotExist')
|
|
1724
|
-
]);
|
|
1725
|
-
});
|
|
1726
|
-
it('finds arguments with variable values', () => {
|
|
1727
|
-
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
1728
|
-
file.parse(`
|
|
1729
|
-
function Sum()
|
|
1730
|
-
count = 1
|
|
1731
|
-
name = "John"
|
|
1732
|
-
isAlive = true
|
|
1733
|
-
DoSomething(count, name, isAlive)
|
|
1734
|
-
end function
|
|
1735
|
-
`);
|
|
1736
|
-
(0, chai_config_spec_1.expect)(file.functionCalls.length).to.equal(1);
|
|
1737
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[0].args[0]).deep.include({
|
|
1738
|
-
type: new DynamicType_1.DynamicType(),
|
|
1739
|
-
text: 'count'
|
|
1740
|
-
});
|
|
1741
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[0].args[1]).deep.include({
|
|
1742
|
-
type: new DynamicType_1.DynamicType(),
|
|
1743
|
-
text: 'name'
|
|
1744
|
-
});
|
|
1745
|
-
(0, chai_config_spec_1.expect)(file.functionCalls[0].args[2]).deep.include({
|
|
1746
|
-
type: new DynamicType_1.DynamicType(),
|
|
1747
|
-
text: 'isAlive'
|
|
1748
|
-
});
|
|
1749
|
-
});
|
|
1750
|
-
});
|
|
1751
|
-
describe('findCallables', () => {
|
|
1752
|
-
//this test is to help with code coverage
|
|
1753
|
-
it('skips top-level statements', () => {
|
|
1754
|
-
let file = new BrsFile_1.BrsFile('absolute', 'relative', program);
|
|
1755
|
-
file.parse('name = "Bob"');
|
|
1756
|
-
(0, chai_config_spec_1.expect)(file.callables.length).to.equal(0);
|
|
1757
|
-
});
|
|
1758
|
-
it('finds return type', () => {
|
|
1759
|
-
let file = program.setFile('source/main.brs', `
|
|
1760
|
-
function DoSomething() as string
|
|
1761
|
-
end function
|
|
1762
|
-
`);
|
|
1763
|
-
(0, chai_config_spec_1.expect)(file.callables[0]).to.deep.include({
|
|
1764
|
-
file: file,
|
|
1765
|
-
nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36),
|
|
1766
|
-
name: 'DoSomething',
|
|
1767
|
-
params: []
|
|
1768
|
-
});
|
|
1769
|
-
(0, chai_config_spec_1.expect)(file.callables[0].type.returnType).instanceof(StringType_1.StringType);
|
|
1770
|
-
});
|
|
1771
|
-
});
|
|
1772
|
-
describe('createFunctionScopes', () => {
|
|
1773
|
-
it('creates range properly', () => {
|
|
1774
|
-
file.parse(`
|
|
1775
|
-
sub Main()
|
|
1776
|
-
name = 'bob"
|
|
1777
|
-
end sub
|
|
1778
|
-
`);
|
|
1779
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
|
|
1780
|
-
});
|
|
1781
|
-
it('creates scopes for parent and child functions', () => {
|
|
1782
|
-
file.parse(`
|
|
1783
|
-
sub Main()
|
|
1784
|
-
sayHi = sub()
|
|
1785
|
-
print "hi"
|
|
1786
|
-
end sub
|
|
1787
|
-
|
|
1788
|
-
scheduleJob(sub()
|
|
1789
|
-
print "job completed"
|
|
1790
|
-
end sub)
|
|
1791
|
-
end sub
|
|
1792
|
-
`);
|
|
1793
|
-
(0, chai_config_spec_1.expect)(file.functionScopes).to.length(3);
|
|
1794
|
-
});
|
|
1795
|
-
it('outer function does not capture inner statements', () => {
|
|
1796
|
-
file.parse(`
|
|
1797
|
-
sub Main()
|
|
1798
|
-
name = "john"
|
|
1799
|
-
sayHi = sub()
|
|
1800
|
-
age = 12
|
|
1801
|
-
end sub
|
|
1802
|
-
end sub
|
|
1803
|
-
`);
|
|
1804
|
-
let outerScope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(2, 25));
|
|
1805
|
-
(0, chai_config_spec_1.expect)(outerScope.variableDeclarations).to.be.lengthOf(2);
|
|
1806
|
-
let innerScope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(4, 10));
|
|
1807
|
-
(0, chai_config_spec_1.expect)(innerScope.variableDeclarations).to.be.lengthOf(1);
|
|
1808
|
-
});
|
|
1809
|
-
it('finds variables declared in function scopes', () => {
|
|
1810
|
-
file.parse(`
|
|
1811
|
-
sub Main()
|
|
1812
|
-
sayHi = sub()
|
|
1813
|
-
age = 12
|
|
1814
|
-
end sub
|
|
1815
|
-
|
|
1816
|
-
scheduleJob(sub()
|
|
1817
|
-
name = "bob"
|
|
1818
|
-
end sub)
|
|
1819
|
-
end sub
|
|
1820
|
-
`);
|
|
1821
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(1);
|
|
1822
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0]).to.deep.include({
|
|
1823
|
-
lineIndex: 2,
|
|
1824
|
-
name: 'sayHi'
|
|
1825
|
-
});
|
|
1826
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0].type).instanceof(FunctionType_1.FunctionType);
|
|
1827
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[1].variableDeclarations).to.be.length(1);
|
|
1828
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[1].variableDeclarations[0]).to.deep.include({
|
|
1829
|
-
lineIndex: 3,
|
|
1830
|
-
name: 'age'
|
|
1831
|
-
});
|
|
1832
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[1].variableDeclarations[0].type).instanceof(IntegerType_1.IntegerType);
|
|
1833
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[2].variableDeclarations).to.be.length(1);
|
|
1834
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[2].variableDeclarations[0]).to.deep.include({
|
|
1835
|
-
lineIndex: 7,
|
|
1836
|
-
name: 'name'
|
|
1837
|
-
});
|
|
1838
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[2].variableDeclarations[0].type).instanceof(StringType_1.StringType);
|
|
1839
|
-
});
|
|
1840
|
-
it('finds variable declarations inside of if statements', () => {
|
|
1841
|
-
file.parse(`
|
|
1842
|
-
sub Main()
|
|
1843
|
-
if true then
|
|
1844
|
-
theLength = 1
|
|
1845
|
-
end if
|
|
1846
|
-
end sub
|
|
1847
|
-
`);
|
|
1848
|
-
let scope = file.getFunctionScopeAtPosition(vscode_languageserver_1.Position.create(3, 0));
|
|
1849
|
-
(0, chai_config_spec_1.expect)(scope.variableDeclarations[0]).to.exist;
|
|
1850
|
-
(0, chai_config_spec_1.expect)(scope.variableDeclarations[0].name).to.equal('theLength');
|
|
1851
|
-
});
|
|
1852
|
-
it('finds value from global return', () => {
|
|
1853
|
-
let file = program.setFile('source/main.brs', `
|
|
1854
|
-
sub Main()
|
|
1855
|
-
myName = GetName()
|
|
1856
|
-
end sub
|
|
1857
|
-
|
|
1858
|
-
function GetName() as string
|
|
1859
|
-
return "bob"
|
|
1860
|
-
end function
|
|
1861
|
-
`);
|
|
1862
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(1);
|
|
1863
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0]).to.deep.include({
|
|
1864
|
-
lineIndex: 2,
|
|
1865
|
-
name: 'myName'
|
|
1866
|
-
});
|
|
1867
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[0].type).instanceof(StringType_1.StringType);
|
|
1868
|
-
});
|
|
1869
|
-
it('finds variable type from other variable', () => {
|
|
1870
|
-
file.parse(`
|
|
1871
|
-
sub Main()
|
|
1872
|
-
name = "bob"
|
|
1873
|
-
nameCopy = name
|
|
1874
|
-
end sub
|
|
1875
|
-
`);
|
|
1876
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations).to.be.length(2);
|
|
1877
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[1]).to.deep.include({
|
|
1878
|
-
lineIndex: 3,
|
|
1879
|
-
name: 'nameCopy'
|
|
1880
|
-
});
|
|
1881
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].variableDeclarations[1].type).instanceof(StringType_1.StringType);
|
|
1882
|
-
});
|
|
1883
|
-
it('sets proper range for functions', () => {
|
|
1884
|
-
file.parse(`
|
|
1885
|
-
sub Main()
|
|
1886
|
-
getName = function()
|
|
1887
|
-
return "bob"
|
|
1888
|
-
end function
|
|
1889
|
-
end sub
|
|
1890
|
-
`);
|
|
1891
|
-
(0, chai_config_spec_1.expect)(file.functionScopes).to.be.length(2);
|
|
1892
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 5, 23));
|
|
1893
|
-
(0, chai_config_spec_1.expect)(file.functionScopes[1].range).to.eql(vscode_languageserver_1.Range.create(2, 30, 4, 32));
|
|
1894
|
-
});
|
|
1895
|
-
});
|
|
1896
|
-
it('handles mixed case `then` partions of conditionals', () => {
|
|
1897
|
-
let mainFile = program.setFile('source/main.brs', `
|
|
1898
|
-
sub Main()
|
|
1899
|
-
if true then
|
|
1900
|
-
print "works"
|
|
1901
|
-
end if
|
|
1902
|
-
end sub
|
|
1903
|
-
`);
|
|
1904
|
-
(0, chai_config_spec_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
|
|
1905
|
-
mainFile = program.setFile('source/main.brs', `
|
|
1906
|
-
sub Main()
|
|
1907
|
-
if true Then
|
|
1908
|
-
print "works"
|
|
1909
|
-
end if
|
|
1910
|
-
end sub
|
|
1911
|
-
`);
|
|
1912
|
-
(0, chai_config_spec_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
|
|
1913
|
-
mainFile = program.setFile('source/main.brs', `
|
|
1914
|
-
sub Main()
|
|
1915
|
-
if true THEN
|
|
1916
|
-
print "works"
|
|
1917
|
-
end if
|
|
1918
|
-
end sub
|
|
1919
|
-
`);
|
|
1920
|
-
(0, chai_config_spec_1.expect)(mainFile.getDiagnostics()).to.be.lengthOf(0);
|
|
1921
|
-
});
|
|
1922
|
-
describe('getHover', () => {
|
|
1923
|
-
it('works for param types', () => {
|
|
1924
|
-
let file = program.setFile('source/main.brs', `
|
|
1925
|
-
sub DoSomething(name as string)
|
|
1926
|
-
name = 1
|
|
1927
|
-
sayMyName = function(name as string)
|
|
1928
|
-
end function
|
|
1929
|
-
end sub
|
|
1930
|
-
`);
|
|
1931
|
-
//hover over the `name = 1` line
|
|
1932
|
-
let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 24))[0];
|
|
1933
|
-
(0, chai_config_spec_1.expect)(hover).to.exist;
|
|
1934
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 24));
|
|
1935
|
-
//hover over the `name` parameter declaration
|
|
1936
|
-
hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 34))[0];
|
|
1937
|
-
(0, chai_config_spec_1.expect)(hover).to.exist;
|
|
1938
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 32, 1, 36));
|
|
1939
|
-
});
|
|
1940
|
-
//ignore this for now...it's not a huge deal
|
|
1941
|
-
it('does not match on keywords or data types', () => {
|
|
1942
|
-
let file = program.setFile('source/main.brs', `
|
|
1943
|
-
sub Main(name as string)
|
|
1944
|
-
end sub
|
|
1945
|
-
sub as()
|
|
1946
|
-
end sub
|
|
1947
|
-
`);
|
|
1948
|
-
//hover over the `as`
|
|
1949
|
-
(0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 31))).to.be.empty;
|
|
1950
|
-
//hover over the `string`
|
|
1951
|
-
(0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 36))).to.be.empty;
|
|
1952
|
-
});
|
|
1953
|
-
it('finds declared function', () => {
|
|
1954
|
-
let file = program.setFile('source/main.brs', `
|
|
1955
|
-
function Main(count = 1)
|
|
1956
|
-
firstName = "bob"
|
|
1957
|
-
age = 21
|
|
1958
|
-
shoeSize = 10
|
|
1959
|
-
end function
|
|
1960
|
-
`);
|
|
1961
|
-
let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(1, 28))[0];
|
|
1962
|
-
(0, chai_config_spec_1.expect)(hover).to.exist;
|
|
1963
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
|
|
1964
|
-
(0, chai_config_spec_1.expect)(hover.contents).to.equal([
|
|
1965
|
-
'```brightscript',
|
|
1966
|
-
'function Main(count? as dynamic) as dynamic',
|
|
1967
|
-
'```'
|
|
1968
|
-
].join('\n'));
|
|
1969
|
-
});
|
|
1970
|
-
it('finds declared namespace function', () => {
|
|
1971
|
-
let file = program.setFile('source/main.brs', `
|
|
1972
|
-
namespace mySpace
|
|
1973
|
-
function Main(count = 1)
|
|
1974
|
-
firstName = "bob"
|
|
1975
|
-
age = 21
|
|
1976
|
-
shoeSize = 10
|
|
1977
|
-
end function
|
|
1978
|
-
end namespace
|
|
1979
|
-
`);
|
|
1980
|
-
let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 28))[0];
|
|
1981
|
-
(0, chai_config_spec_1.expect)(hover).to.exist;
|
|
1982
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 25, 2, 29));
|
|
1983
|
-
(0, chai_config_spec_1.expect)(hover.contents).to.equal([
|
|
1984
|
-
'```brightscript',
|
|
1985
|
-
'function Main(count? as dynamic) as dynamic',
|
|
1986
|
-
'```'
|
|
1987
|
-
].join('\n'));
|
|
1988
|
-
});
|
|
1989
|
-
it('finds variable function hover in same scope', () => {
|
|
1990
|
-
let file = program.setFile('source/main.brs', `
|
|
1991
|
-
sub Main()
|
|
1992
|
-
sayMyName = sub(name as string)
|
|
1993
|
-
end sub
|
|
1994
|
-
|
|
1995
|
-
sayMyName()
|
|
1996
|
-
end sub
|
|
1997
|
-
`);
|
|
1998
|
-
let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 24))[0];
|
|
1999
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
|
|
2000
|
-
(0, chai_config_spec_1.expect)(hover.contents).to.equal([
|
|
2001
|
-
'```brightscript',
|
|
2002
|
-
'sub sayMyName(name as string) as void',
|
|
2003
|
-
'```'
|
|
2004
|
-
].join('\n'));
|
|
2005
|
-
});
|
|
2006
|
-
it('does not crash when hovering on built-in functions', () => {
|
|
2007
|
-
let file = program.setFile('source/main.brs', `
|
|
2008
|
-
function doUcase(text)
|
|
2009
|
-
return ucase(text)
|
|
2010
|
-
end function
|
|
2011
|
-
`);
|
|
2012
|
-
(0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 30))[0].contents).to.equal([
|
|
2013
|
-
'```brightscript',
|
|
2014
|
-
'function UCase(s as string) as string',
|
|
2015
|
-
'```'
|
|
2016
|
-
].join('\n'));
|
|
2017
|
-
});
|
|
2018
|
-
it('does not crash when hovering on object method call', () => {
|
|
2019
|
-
let file = program.setFile('source/main.brs', `
|
|
2020
|
-
function getInstr(url, text)
|
|
2021
|
-
return url.instr(text)
|
|
2022
|
-
end function
|
|
2023
|
-
`);
|
|
2024
|
-
(0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 35))[0].contents).to.equal([
|
|
2025
|
-
'```brightscript',
|
|
2026
|
-
//TODO this really shouldn't be returning the global function, but it does...so make sure it doesn't crash right now.
|
|
2027
|
-
'function Instr(startOrText as dynamic, textOrSubstring as string, substring? as string) as integer',
|
|
2028
|
-
'```'
|
|
2029
|
-
].join('\n'));
|
|
2030
|
-
});
|
|
2031
|
-
it('finds function hover in file scope', () => {
|
|
2032
|
-
let file = program.setFile('source/main.brs', `
|
|
2033
|
-
sub Main()
|
|
2034
|
-
sayMyName()
|
|
2035
|
-
end sub
|
|
2036
|
-
|
|
2037
|
-
sub sayMyName()
|
|
2038
|
-
|
|
2039
|
-
end sub
|
|
2040
|
-
`);
|
|
2041
|
-
let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 25))[0];
|
|
2042
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
|
|
2043
|
-
(0, chai_config_spec_1.expect)(hover.contents).to.equal([
|
|
2044
|
-
'```brightscript',
|
|
2045
|
-
'sub sayMyName() as void',
|
|
2046
|
-
'```'
|
|
2047
|
-
].join('\n'));
|
|
2048
|
-
});
|
|
2049
|
-
it('finds namespace function hover in file scope', () => {
|
|
2050
|
-
let file = program.setFile('source/main.brs', `
|
|
2051
|
-
namespace mySpace
|
|
2052
|
-
sub Main()
|
|
2053
|
-
sayMyName()
|
|
2054
|
-
end sub
|
|
2055
|
-
|
|
2056
|
-
sub sayMyName()
|
|
2057
|
-
|
|
2058
|
-
end sub
|
|
2059
|
-
end namespace
|
|
2060
|
-
`);
|
|
2061
|
-
let hover = program.getHover(file.srcPath, vscode_languageserver_1.Position.create(3, 25))[0];
|
|
2062
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(3, 20, 3, 29));
|
|
2063
|
-
(0, chai_config_spec_1.expect)(hover.contents).to.equal([
|
|
2064
|
-
'```brightscript',
|
|
2065
|
-
'sub sayMyName() as void',
|
|
2066
|
-
'```'
|
|
2067
|
-
].join('\n'));
|
|
2068
|
-
});
|
|
2069
|
-
it('finds function hover in scope', () => {
|
|
2070
|
-
let rootDir = process.cwd();
|
|
2071
|
-
program = new Program_1.Program({
|
|
2072
|
-
rootDir: rootDir
|
|
2073
|
-
});
|
|
2074
|
-
let mainFile = program.setFile('source/main.brs', `
|
|
2075
|
-
sub Main()
|
|
2076
|
-
sayMyName()
|
|
2077
|
-
end sub
|
|
2078
|
-
`);
|
|
2079
|
-
program.setFile('source/lib.brs', `
|
|
2080
|
-
sub sayMyName(name as string)
|
|
2081
|
-
|
|
2082
|
-
end sub
|
|
2083
|
-
`);
|
|
2084
|
-
let hover = program.getHover(mainFile.srcPath, vscode_languageserver_1.Position.create(2, 25))[0];
|
|
2085
|
-
(0, chai_config_spec_1.expect)(hover).to.exist;
|
|
2086
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
|
|
2087
|
-
(0, chai_config_spec_1.expect)(hover.contents).to.equal([
|
|
2088
|
-
'```brightscript',
|
|
2089
|
-
'sub sayMyName(name as string) as void',
|
|
2090
|
-
'```'
|
|
2091
|
-
].join('\n'));
|
|
2092
|
-
});
|
|
2093
|
-
it('finds namespace function hover in scope', () => {
|
|
2094
|
-
let rootDir = process.cwd();
|
|
2095
|
-
program = new Program_1.Program({
|
|
2096
|
-
rootDir: rootDir
|
|
2097
|
-
});
|
|
2098
|
-
let mainFile = program.setFile('source/main.brs', `
|
|
2099
|
-
sub Main()
|
|
2100
|
-
mySpace.sayMyName()
|
|
2101
|
-
end sub
|
|
2102
|
-
`);
|
|
2103
|
-
program.setFile('source/lib.brs', `
|
|
2104
|
-
namespace mySpace
|
|
2105
|
-
sub sayMyName(name as string)
|
|
2106
|
-
end sub
|
|
2107
|
-
end namespace
|
|
2108
|
-
`);
|
|
2109
|
-
let hover = program.getHover(mainFile.srcPath, vscode_languageserver_1.Position.create(2, 34))[0];
|
|
2110
|
-
(0, chai_config_spec_1.expect)(hover).to.exist;
|
|
2111
|
-
(0, chai_config_spec_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 28, 2, 37));
|
|
2112
|
-
(0, chai_config_spec_1.expect)(hover.contents).to.equal([
|
|
2113
|
-
'```brightscript',
|
|
2114
|
-
'sub sayMyName(name as string) as void',
|
|
2115
|
-
'```'
|
|
2116
|
-
].join('\n'));
|
|
2117
|
-
});
|
|
2118
|
-
it('includes markdown comments in hover.', () => {
|
|
2119
|
-
let rootDir = process.cwd();
|
|
2120
|
-
program = new Program_1.Program({
|
|
2121
|
-
rootDir: rootDir
|
|
2122
|
-
});
|
|
2123
|
-
const file = program.setFile('source/lib.brs', `
|
|
2124
|
-
'
|
|
2125
|
-
' The main function
|
|
2126
|
-
'
|
|
2127
|
-
sub main()
|
|
2128
|
-
writeToLog("hello")
|
|
2129
|
-
end sub
|
|
2130
|
-
|
|
2131
|
-
'
|
|
2132
|
-
' Prints a message to the log.
|
|
2133
|
-
' Works with *markdown* **content**
|
|
2134
|
-
'
|
|
2135
|
-
sub writeToLog(message as string)
|
|
2136
|
-
print message
|
|
2137
|
-
end sub
|
|
2138
|
-
`);
|
|
2139
|
-
//hover over log("hello")
|
|
2140
|
-
(0, chai_config_spec_1.expect)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 22))[0].contents).to.equal([
|
|
2141
|
-
'```brightscript',
|
|
2142
|
-
'sub writeToLog(message as string) as void',
|
|
2143
|
-
'```',
|
|
2144
|
-
'***',
|
|
2145
|
-
'',
|
|
2146
|
-
' Prints a message to the log.',
|
|
2147
|
-
' Works with *markdown* **content**',
|
|
2148
|
-
''
|
|
2149
|
-
].join('\n'));
|
|
2150
|
-
//hover over sub ma|in()
|
|
2151
|
-
(0, chai_config_spec_1.expect)((0, testHelpers_spec_1.trim)(program.getHover(file.srcPath, vscode_languageserver_1.Position.create(4, 22))[0].contents.toString())).to.equal((0, testHelpers_spec_1.trim) `
|
|
2152
|
-
\`\`\`brightscript
|
|
2153
|
-
sub main() as void
|
|
2154
|
-
\`\`\`
|
|
2155
|
-
***
|
|
2156
|
-
|
|
2157
|
-
The main function
|
|
2158
|
-
`);
|
|
2159
|
-
});
|
|
2160
|
-
it('handles mixed case `then` partions of conditionals', () => {
|
|
2161
|
-
let mainFile = program.setFile('source/main.brs', `
|
|
2162
|
-
sub Main()
|
|
2163
|
-
if true then
|
|
2164
|
-
print "works"
|
|
2165
|
-
end if
|
|
2166
|
-
end sub
|
|
2167
|
-
`);
|
|
2168
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
|
|
2169
|
-
mainFile = program.setFile('source/main.brs', `
|
|
2170
|
-
sub Main()
|
|
2171
|
-
if true Then
|
|
2172
|
-
print "works"
|
|
2173
|
-
end if
|
|
2174
|
-
end sub
|
|
2175
|
-
`);
|
|
2176
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
|
|
2177
|
-
mainFile = program.setFile('source/main.brs', `
|
|
2178
|
-
sub Main()
|
|
2179
|
-
if true THEN
|
|
2180
|
-
print "works"
|
|
2181
|
-
end if
|
|
2182
|
-
end sub
|
|
2183
|
-
`);
|
|
2184
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
|
|
2185
|
-
});
|
|
2186
|
-
});
|
|
2187
|
-
it('does not throw when encountering incomplete import statement', () => {
|
|
2188
|
-
program.setFile('source/main.brs', `
|
|
2189
|
-
import
|
|
2190
|
-
sub main()
|
|
2191
|
-
end sub
|
|
2192
|
-
`);
|
|
2193
|
-
program.validate();
|
|
2194
|
-
//this test will throw an exception if something went wrong
|
|
2195
|
-
});
|
|
2196
|
-
describe('transpile', () => {
|
|
2197
|
-
it('namespaced functions default param values in d.bs files are transpiled correctly', () => {
|
|
2198
|
-
testGetTypedef(`
|
|
2199
|
-
namespace promises
|
|
2200
|
-
function onThen(promise as dynamic, callback = promises.internal.defaultThenCallback as function, context = "__INVALID__" as object) as dynamic
|
|
2201
|
-
return true
|
|
2202
|
-
end function
|
|
2203
|
-
end namespace
|
|
2204
|
-
namespace promises.internal
|
|
2205
|
-
function defaultThenCallback(value = invalid as dynamic, _ = invalid as dynamic) as dynamic
|
|
2206
|
-
end function
|
|
2207
|
-
end namespace
|
|
2208
|
-
`, `
|
|
2209
|
-
namespace promises
|
|
2210
|
-
function onThen(promise as dynamic, callback = promises.internal.defaultThenCallback as function, context = "__INVALID__" as object) as dynamic
|
|
2211
|
-
end function
|
|
2212
|
-
end namespace
|
|
2213
|
-
namespace promises.internal
|
|
2214
|
-
function defaultThenCallback(value = invalid as dynamic, _ = invalid as dynamic) as dynamic
|
|
2215
|
-
end function
|
|
2216
|
-
end namespace
|
|
2217
|
-
`);
|
|
2218
|
-
});
|
|
2219
|
-
it('namespaced functions default param values in d.bs files are transpiled correctly', () => {
|
|
2220
|
-
testGetTypedef(`
|
|
2221
|
-
namespace alpha
|
|
2222
|
-
function beta()
|
|
2223
|
-
end function
|
|
2224
|
-
function charlie(fn = alpha.beta, fn2 = beta)
|
|
2225
|
-
end function
|
|
2226
|
-
end namespace
|
|
2227
|
-
function delta(fn = alpha.beta)
|
|
2228
|
-
end function
|
|
2229
|
-
`);
|
|
2230
|
-
});
|
|
2231
|
-
describe('null tokens', () => {
|
|
2232
|
-
it('succeeds when token locations are omitted', () => {
|
|
2233
|
-
doTest(`
|
|
2234
|
-
library "something" 'comment before func
|
|
2235
|
-
sub main(arg0, arg1 as string, arg2 = invalid)
|
|
2236
|
-
'comment
|
|
2237
|
-
aa = {
|
|
2238
|
-
'comment
|
|
2239
|
-
one: 1
|
|
2240
|
-
"two": 2
|
|
2241
|
-
}
|
|
2242
|
-
arr = [
|
|
2243
|
-
'comment
|
|
2244
|
-
1
|
|
2245
|
-
'comment
|
|
2246
|
-
2
|
|
2247
|
-
]
|
|
2248
|
-
val = +3
|
|
2249
|
-
print "hello"
|
|
2250
|
-
'comment after print
|
|
2251
|
-
num = 1
|
|
2252
|
-
num++
|
|
2253
|
-
num += 2
|
|
2254
|
-
num = +num
|
|
2255
|
-
test(num)
|
|
2256
|
-
for i = 0 to 10 step 1
|
|
2257
|
-
exit for
|
|
2258
|
-
end for
|
|
2259
|
-
while true
|
|
2260
|
-
exit while
|
|
2261
|
-
end while
|
|
2262
|
-
if true then
|
|
2263
|
-
print 1
|
|
2264
|
-
else if true
|
|
2265
|
-
print 1
|
|
2266
|
-
else
|
|
2267
|
-
print 1
|
|
2268
|
-
end if
|
|
2269
|
-
dim thing[1, 2]
|
|
2270
|
-
label1:
|
|
2271
|
-
goto label1
|
|
2272
|
-
end
|
|
2273
|
-
stop
|
|
2274
|
-
stuff = [
|
|
2275
|
-
1
|
|
2276
|
-
2
|
|
2277
|
-
3
|
|
2278
|
-
]
|
|
2279
|
-
for each item in stuff
|
|
2280
|
-
print item
|
|
2281
|
-
end for
|
|
2282
|
-
m.thing = 1
|
|
2283
|
-
m.thing += 1
|
|
2284
|
-
m[1] = 1
|
|
2285
|
-
m[1] += 1
|
|
2286
|
-
m[1, 2] = 2
|
|
2287
|
-
try
|
|
2288
|
-
print m.b.c
|
|
2289
|
-
catch e
|
|
2290
|
-
print e
|
|
2291
|
-
end try
|
|
2292
|
-
throw "crash"
|
|
2293
|
-
for i = 0 to 10
|
|
2294
|
-
continue
|
|
2295
|
-
end for
|
|
2296
|
-
print m@name
|
|
2297
|
-
print (1 + 2)
|
|
2298
|
-
end sub
|
|
2299
|
-
|
|
2300
|
-
function test(p1)
|
|
2301
|
-
return p1
|
|
2302
|
-
end function
|
|
2303
|
-
`);
|
|
2304
|
-
});
|
|
2305
|
-
it('works for bs content', () => {
|
|
2306
|
-
program.setFile('source/lib.bs', ``);
|
|
2307
|
-
doTest(`
|
|
2308
|
-
import "pkg:/source/lib.bs"
|
|
2309
|
-
@annotation()
|
|
2310
|
-
sub test()
|
|
2311
|
-
two = 2
|
|
2312
|
-
print \`1\${two}\${3}\n\`
|
|
2313
|
-
print (1 as integer)
|
|
2314
|
-
print SOURCE_LINE_NUM
|
|
2315
|
-
print FUNCTION_NAME
|
|
2316
|
-
print SOURCE_FUNCTION_NAME
|
|
2317
|
-
print PKG_LOCATION
|
|
2318
|
-
print PKG_PATH
|
|
2319
|
-
print LINE_NUM
|
|
2320
|
-
print new Person()
|
|
2321
|
-
m@.someCallfunc()
|
|
2322
|
-
m@.someCallfunc(1, 2)
|
|
2323
|
-
print tag\`stuff\${LINE_NUM}\${LINE_NUM}\`
|
|
2324
|
-
print 1 = 1 ? 1 : 2
|
|
2325
|
-
print 1 = 1 ? m.one : m.two
|
|
2326
|
-
print 1 ?? 2
|
|
2327
|
-
print m.one ?? m.two
|
|
2328
|
-
print /123/gi
|
|
2329
|
-
end sub
|
|
2330
|
-
function tag(param1, param2)
|
|
2331
|
-
end function
|
|
2332
|
-
const a = 1
|
|
2333
|
-
namespace alpha
|
|
2334
|
-
function beta()
|
|
2335
|
-
throw "An error has occurred"
|
|
2336
|
-
end function
|
|
2337
|
-
function charlie()
|
|
2338
|
-
end function
|
|
2339
|
-
end namespace
|
|
2340
|
-
sub test()
|
|
2341
|
-
' alpha.charlie()
|
|
2342
|
-
end sub
|
|
2343
|
-
|
|
2344
|
-
enum Direction
|
|
2345
|
-
up = "up"
|
|
2346
|
-
end enum
|
|
2347
|
-
|
|
2348
|
-
class Person
|
|
2349
|
-
name as string
|
|
2350
|
-
sub new()
|
|
2351
|
-
print m.name
|
|
2352
|
-
end sub
|
|
2353
|
-
|
|
2354
|
-
sub test()
|
|
2355
|
-
end sub
|
|
2356
|
-
end class
|
|
2357
|
-
|
|
2358
|
-
interface Beta
|
|
2359
|
-
name as string
|
|
2360
|
-
end interface
|
|
2361
|
-
`, `
|
|
2362
|
-
'import "pkg:/source/lib.bs"
|
|
2363
|
-
|
|
2364
|
-
sub test()
|
|
2365
|
-
two = 2
|
|
2366
|
-
print ("1" + bslib_toString(two) + bslib_toString(3) + chr(10))
|
|
2367
|
-
print 1
|
|
2368
|
-
print -1
|
|
2369
|
-
print "test"
|
|
2370
|
-
print "test"
|
|
2371
|
-
print "pkg:/source/main.brs:" + str(LINE_NUM)
|
|
2372
|
-
print "pkg:/source/main.brs"
|
|
2373
|
-
print LINE_NUM
|
|
2374
|
-
print Person()
|
|
2375
|
-
m.callfunc("someCallfunc", invalid)
|
|
2376
|
-
m.callfunc("someCallfunc", 1, 2)
|
|
2377
|
-
print tag(["stuff", "", ""], [LINE_NUM, LINE_NUM])
|
|
2378
|
-
print bslib_ternary(1 = 1, 1, 2)
|
|
2379
|
-
print (function(__bsCondition, m)
|
|
2380
|
-
if __bsCondition then
|
|
2381
|
-
return m.one
|
|
2382
|
-
else
|
|
2383
|
-
return m.two
|
|
2384
|
-
end if
|
|
2385
|
-
end function)(1 = 1, m)
|
|
2386
|
-
print bslib_coalesce(1, 2)
|
|
2387
|
-
print (function(m)
|
|
2388
|
-
__bsConsequent = m.one
|
|
2389
|
-
if __bsConsequent <> invalid then
|
|
2390
|
-
return __bsConsequent
|
|
2391
|
-
else
|
|
2392
|
-
return m.two
|
|
2393
|
-
end if
|
|
2394
|
-
end function)(m)
|
|
2395
|
-
print CreateObject("roRegex", "123", "gi")
|
|
2396
|
-
end sub
|
|
2397
|
-
|
|
2398
|
-
function tag(param1, param2)
|
|
2399
|
-
end function
|
|
2400
|
-
|
|
2401
|
-
function alpha_beta()
|
|
2402
|
-
throw "An error has occurred"
|
|
2403
|
-
end function
|
|
2404
|
-
|
|
2405
|
-
function alpha_charlie()
|
|
2406
|
-
end function
|
|
2407
|
-
|
|
2408
|
-
sub test()
|
|
2409
|
-
' alpha.charlie()
|
|
2410
|
-
end sub
|
|
2411
|
-
|
|
2412
|
-
sub __Person_method_new()
|
|
2413
|
-
m.name = invalid
|
|
2414
|
-
print m.name
|
|
2415
|
-
end sub
|
|
2416
|
-
sub __Person_method_test()
|
|
2417
|
-
end sub
|
|
2418
|
-
function __Person_builder()
|
|
2419
|
-
instance = {}
|
|
2420
|
-
instance.new = __Person_method_new
|
|
2421
|
-
instance.test = __Person_method_test
|
|
2422
|
-
return instance
|
|
2423
|
-
end function
|
|
2424
|
-
function Person()
|
|
2425
|
-
instance = __Person_builder()
|
|
2426
|
-
instance.new()
|
|
2427
|
-
return instance
|
|
2428
|
-
end function
|
|
2429
|
-
`);
|
|
2430
|
-
});
|
|
2431
|
-
it('handles source literals properly', () => {
|
|
2432
|
-
const pathUrl = fileUrl(testHelpers_spec_2.rootDir);
|
|
2433
|
-
let text = `"${pathUrl.substring(0, 4)}" + "${pathUrl.substring(4)}`;
|
|
2434
|
-
doTest(`
|
|
2435
|
-
sub test()
|
|
2436
|
-
print SOURCE_FILE_PATH
|
|
2437
|
-
print SOURCE_LOCATION
|
|
2438
|
-
end sub
|
|
2439
|
-
`, `
|
|
2440
|
-
sub test()
|
|
2441
|
-
print ${text}/source/main.bs"
|
|
2442
|
-
print ${text}/source/main.bs:-1"
|
|
2443
|
-
end sub
|
|
2444
|
-
`);
|
|
2445
|
-
});
|
|
2446
|
-
function doTest(source, expected = source) {
|
|
2447
|
-
const file = program.setFile('source/main.bs', '');
|
|
2448
|
-
//override the parser with our locationless parser
|
|
2449
|
-
file['_parser'] = Parser_1.Parser.parse(source, { mode: Parser_1.ParseMode.BrighterScript, trackLocations: false });
|
|
2450
|
-
program.getScopesForFile(file).forEach(x => x['cache'].clear());
|
|
2451
|
-
program.validate();
|
|
2452
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2453
|
-
const result = file.transpile();
|
|
2454
|
-
(0, chai_config_spec_1.expect)((0, testHelpers_spec_1.trimMap)((0, undent_1.default)(result.code))).to.eql((0, undent_1.default)(expected));
|
|
2455
|
-
}
|
|
2456
|
-
});
|
|
2457
|
-
it('transpilies libpkg:/ paths when encountered', () => {
|
|
2458
|
-
program.setFile('source/lib.bs', `
|
|
2459
|
-
import "libpkg:/source/numbers.bs"
|
|
2460
|
-
`);
|
|
2461
|
-
program.setFile('source/numbers.bs', `
|
|
2462
|
-
sub test()
|
|
2463
|
-
end sub
|
|
2464
|
-
`);
|
|
2465
|
-
testTranspile(`
|
|
2466
|
-
<component name="TestButton" extends="Group">
|
|
2467
|
-
<script type="text/brightscript" uri="libpkg:/source/lib.bs"/>
|
|
2468
|
-
</component>
|
|
2469
|
-
`, `
|
|
2470
|
-
<component name="TestButton" extends="Group">
|
|
2471
|
-
<script type="text/brightscript" uri="libpkg:/source/lib.brs" />
|
|
2472
|
-
<script type="text/brightscript" uri="pkg:/source/numbers.brs" />
|
|
2473
|
-
<script type="text/brightscript" uri="pkg:/source/bslib.brs" />
|
|
2474
|
-
</component>
|
|
2475
|
-
`, undefined, 'components/TestButton.xml');
|
|
2476
|
-
});
|
|
2477
|
-
it('excludes trailing commas in array literals', () => {
|
|
2478
|
-
testTranspile(`
|
|
2479
|
-
sub main()
|
|
2480
|
-
arr = [
|
|
2481
|
-
1,
|
|
2482
|
-
2,
|
|
2483
|
-
3
|
|
2484
|
-
]
|
|
2485
|
-
obj = {
|
|
2486
|
-
one: 1,
|
|
2487
|
-
two: 2,
|
|
2488
|
-
three: 3
|
|
2489
|
-
}
|
|
2490
|
-
end sub
|
|
2491
|
-
`, `
|
|
2492
|
-
sub main()
|
|
2493
|
-
arr = [
|
|
2494
|
-
1
|
|
2495
|
-
2
|
|
2496
|
-
3
|
|
2497
|
-
]
|
|
2498
|
-
obj = {
|
|
2499
|
-
one: 1
|
|
2500
|
-
two: 2
|
|
2501
|
-
three: 3
|
|
2502
|
-
}
|
|
2503
|
-
end sub
|
|
2504
|
-
`);
|
|
2505
|
-
});
|
|
2506
|
-
it('transpiles if statement keywords as provided', () => {
|
|
2507
|
-
const code = `
|
|
2508
|
-
sub main()
|
|
2509
|
-
If True Then
|
|
2510
|
-
Print True
|
|
2511
|
-
Else If True Then
|
|
2512
|
-
print True
|
|
2513
|
-
Else If False Then
|
|
2514
|
-
Print False
|
|
2515
|
-
Else
|
|
2516
|
-
Print False
|
|
2517
|
-
End If
|
|
2518
|
-
end sub
|
|
2519
|
-
`;
|
|
2520
|
-
testTranspile(code);
|
|
2521
|
-
testTranspile(code.toLowerCase());
|
|
2522
|
-
testTranspile(code.toUpperCase());
|
|
2523
|
-
});
|
|
2524
|
-
it('does not transpile `then` tokens', () => {
|
|
2525
|
-
testTranspile(`
|
|
2526
|
-
sub main()
|
|
2527
|
-
if true
|
|
2528
|
-
print true
|
|
2529
|
-
else if true
|
|
2530
|
-
print false
|
|
2531
|
-
end if
|
|
2532
|
-
end sub
|
|
2533
|
-
`);
|
|
2534
|
-
});
|
|
2535
|
-
it('honors spacing between multi-word tokens', () => {
|
|
2536
|
-
testTranspile(`
|
|
2537
|
-
sub main()
|
|
2538
|
-
if true
|
|
2539
|
-
print true
|
|
2540
|
-
elseif true
|
|
2541
|
-
print false
|
|
2542
|
-
endif
|
|
2543
|
-
end sub
|
|
2544
|
-
`);
|
|
2545
|
-
});
|
|
2546
|
-
it('handles when only some of the statements have `then`', () => {
|
|
2547
|
-
testTranspile(`
|
|
2548
|
-
function main()
|
|
2549
|
-
if true
|
|
2550
|
-
else if true then
|
|
2551
|
-
else if true
|
|
2552
|
-
else if true then
|
|
2553
|
-
if true then
|
|
2554
|
-
return true
|
|
2555
|
-
end if
|
|
2556
|
-
end if
|
|
2557
|
-
end function
|
|
2558
|
-
`);
|
|
2559
|
-
});
|
|
2560
|
-
it('retains casing of parameter types', () => {
|
|
2561
|
-
function test(type) {
|
|
2562
|
-
testTranspile(`
|
|
2563
|
-
sub one(a as ${type}, b as ${type.toUpperCase()}, c as ${type.toLowerCase()})
|
|
2564
|
-
end sub
|
|
2565
|
-
`);
|
|
2566
|
-
}
|
|
2567
|
-
test('Boolean');
|
|
2568
|
-
test('Double');
|
|
2569
|
-
test('Dynamic');
|
|
2570
|
-
test('Float');
|
|
2571
|
-
test('Integer');
|
|
2572
|
-
test('LongInteger');
|
|
2573
|
-
test('Object');
|
|
2574
|
-
test('String');
|
|
2575
|
-
});
|
|
2576
|
-
it('retains casing of return types', () => {
|
|
2577
|
-
function test(type) {
|
|
2578
|
-
testTranspile(`
|
|
2579
|
-
sub one() as ${type}
|
|
2580
|
-
end sub
|
|
2581
|
-
|
|
2582
|
-
sub two() as ${type.toLowerCase()}
|
|
2583
|
-
end sub
|
|
2584
|
-
|
|
2585
|
-
sub three() as ${type.toUpperCase()}
|
|
2586
|
-
end sub
|
|
2587
|
-
`);
|
|
2588
|
-
}
|
|
2589
|
-
test('Boolean');
|
|
2590
|
-
test('Double');
|
|
2591
|
-
test('Dynamic');
|
|
2592
|
-
test('Float');
|
|
2593
|
-
test('Integer');
|
|
2594
|
-
test('LongInteger');
|
|
2595
|
-
test('Object');
|
|
2596
|
-
test('String');
|
|
2597
|
-
test('Void');
|
|
2598
|
-
});
|
|
2599
|
-
it('retains casing of literal types', () => {
|
|
2600
|
-
function test(type) {
|
|
2601
|
-
testTranspile(`
|
|
2602
|
-
sub main()
|
|
2603
|
-
thing = ${type}
|
|
2604
|
-
thing = ${type.toLowerCase()}
|
|
2605
|
-
thing = ${type.toUpperCase()}
|
|
2606
|
-
end sub
|
|
2607
|
-
`);
|
|
2608
|
-
}
|
|
2609
|
-
test('Invalid');
|
|
2610
|
-
test('True');
|
|
2611
|
-
test('False');
|
|
2612
|
-
});
|
|
2613
|
-
describe('throwStatement', () => {
|
|
2614
|
-
it('transpiles properly', () => {
|
|
2615
|
-
testTranspile(`
|
|
2616
|
-
sub main()
|
|
2617
|
-
try
|
|
2618
|
-
throw "some message"
|
|
2619
|
-
catch e
|
|
2620
|
-
end try
|
|
2621
|
-
end sub
|
|
2622
|
-
`);
|
|
2623
|
-
});
|
|
2624
|
-
});
|
|
2625
|
-
describe('try/catch', () => {
|
|
2626
|
-
it('transpiles properly', () => {
|
|
2627
|
-
testTranspile(`
|
|
2628
|
-
sub main()
|
|
2629
|
-
try
|
|
2630
|
-
print m.b.c
|
|
2631
|
-
catch e
|
|
2632
|
-
print e
|
|
2633
|
-
end try
|
|
2634
|
-
end sub
|
|
2635
|
-
`);
|
|
2636
|
-
});
|
|
2637
|
-
});
|
|
2638
|
-
describe('namespaces', () => {
|
|
2639
|
-
it('properly transpiles namespace functions for assignments', () => {
|
|
2640
|
-
testTranspile(`
|
|
2641
|
-
namespace NameA.NameB
|
|
2642
|
-
sub Speak()
|
|
2643
|
-
end sub
|
|
2644
|
-
end namespace
|
|
2645
|
-
sub main()
|
|
2646
|
-
sayHello = NameA.NameB.Speak
|
|
2647
|
-
sayHello()
|
|
2648
|
-
someOtherObject = m.other.object
|
|
2649
|
-
end sub
|
|
2650
|
-
`, `
|
|
2651
|
-
sub NameA_NameB_Speak()
|
|
2652
|
-
end sub
|
|
2653
|
-
|
|
2654
|
-
sub main()
|
|
2655
|
-
sayHello = NameA_NameB_Speak
|
|
2656
|
-
sayHello()
|
|
2657
|
-
someOtherObject = m.other.object
|
|
2658
|
-
end sub
|
|
2659
|
-
`);
|
|
2660
|
-
});
|
|
2661
|
-
it('transpiles namespace calls from within an array', () => {
|
|
2662
|
-
testTranspile(`
|
|
2663
|
-
namespace Vertibrates.Birds
|
|
2664
|
-
function GetAllBirds()
|
|
2665
|
-
return [
|
|
2666
|
-
GetDuck(),
|
|
2667
|
-
GetGoose()
|
|
2668
|
-
]
|
|
2669
|
-
end function
|
|
2670
|
-
|
|
2671
|
-
function GetDuck()
|
|
2672
|
-
end function
|
|
2673
|
-
|
|
2674
|
-
function GetGoose()
|
|
2675
|
-
end function
|
|
2676
|
-
end namespace
|
|
2677
|
-
`, `
|
|
2678
|
-
function Vertibrates_Birds_GetAllBirds()
|
|
2679
|
-
return [
|
|
2680
|
-
Vertibrates_Birds_GetDuck()
|
|
2681
|
-
Vertibrates_Birds_GetGoose()
|
|
2682
|
-
]
|
|
2683
|
-
end function
|
|
2684
|
-
|
|
2685
|
-
function Vertibrates_Birds_GetDuck()
|
|
2686
|
-
end function
|
|
2687
|
-
|
|
2688
|
-
function Vertibrates_Birds_GetGoose()
|
|
2689
|
-
end function
|
|
2690
|
-
`, undefined, 'components/NobodyImportsMe.bs', false);
|
|
2691
|
-
});
|
|
2692
|
-
it('properly transpiles inferred namespace function for assignment', () => {
|
|
2693
|
-
testTranspile(`
|
|
2694
|
-
namespace NameA.NameB
|
|
2695
|
-
sub Speak()
|
|
2696
|
-
end sub
|
|
2697
|
-
sub main()
|
|
2698
|
-
sayHello = Speak
|
|
2699
|
-
sayHello()
|
|
2700
|
-
end sub
|
|
2701
|
-
end namespace
|
|
2702
|
-
`, `
|
|
2703
|
-
sub NameA_NameB_Speak()
|
|
2704
|
-
end sub
|
|
2705
|
-
|
|
2706
|
-
sub NameA_NameB_main()
|
|
2707
|
-
sayHello = NameA_NameB_Speak
|
|
2708
|
-
sayHello()
|
|
2709
|
-
end sub
|
|
2710
|
-
`);
|
|
2711
|
-
});
|
|
2712
|
-
});
|
|
2713
|
-
it('includes all text to end of line for a non-terminated string', () => {
|
|
2714
|
-
testTranspile('sub main()\n name = "john \nend sub', 'sub main()\n name = "john "\nend sub', null, 'source/main.bs', false);
|
|
2715
|
-
});
|
|
2716
|
-
it('escapes quotes in string literals', () => {
|
|
2717
|
-
testTranspile(`
|
|
2718
|
-
sub main()
|
|
2719
|
-
expected += chr(10) + " version=""2.0"""
|
|
2720
|
-
end sub
|
|
2721
|
-
`);
|
|
2722
|
-
});
|
|
2723
|
-
it('keeps function parameter types in proper order', () => {
|
|
2724
|
-
testTranspile(`
|
|
2725
|
-
function CreateTestStatistic(name as string, result = "Success" as string, time = 0 as integer, errorCode = 0 as integer, errorMessage = "" as string) as object
|
|
2726
|
-
end function
|
|
2727
|
-
`);
|
|
2728
|
-
});
|
|
2729
|
-
it('discard parameter types when removeParameterTypes is true', () => {
|
|
2730
|
-
program.options.removeParameterTypes = true;
|
|
2731
|
-
testTranspile(`
|
|
2732
|
-
sub one(a as integer, b = "" as string, c = invalid as dynamic)
|
|
2733
|
-
end sub
|
|
2734
|
-
`, `
|
|
2735
|
-
sub one(a, b = "", c = invalid)
|
|
2736
|
-
end sub
|
|
2737
|
-
`);
|
|
2738
|
-
});
|
|
2739
|
-
it('discard return type when removeParameterTypes is true', () => {
|
|
2740
|
-
program.options.removeParameterTypes = true;
|
|
2741
|
-
testTranspile(`
|
|
2742
|
-
function one() as string
|
|
2743
|
-
return ""
|
|
2744
|
-
end function
|
|
2745
|
-
`, `
|
|
2746
|
-
function one()
|
|
2747
|
-
return ""
|
|
2748
|
-
end function
|
|
2749
|
-
`);
|
|
2750
|
-
});
|
|
2751
|
-
it('does not remove `as void` when removeParameterTypes is true', () => {
|
|
2752
|
-
program.options.removeParameterTypes = true;
|
|
2753
|
-
testTranspile(`
|
|
2754
|
-
function one() as void
|
|
2755
|
-
return
|
|
2756
|
-
end function
|
|
2757
|
-
`, `
|
|
2758
|
-
function one() as void
|
|
2759
|
-
return
|
|
2760
|
-
end function
|
|
2761
|
-
`);
|
|
2762
|
-
});
|
|
2763
|
-
it('does not remove `as <type>` for sub when removeParameterTypes is true', () => {
|
|
2764
|
-
program.options.removeParameterTypes = true;
|
|
2765
|
-
testTranspile(`
|
|
2766
|
-
sub one() as string
|
|
2767
|
-
return "hello"
|
|
2768
|
-
end sub
|
|
2769
|
-
`, `
|
|
2770
|
-
sub one() as string
|
|
2771
|
-
return "hello"
|
|
2772
|
-
end sub
|
|
2773
|
-
`);
|
|
2774
|
-
});
|
|
2775
|
-
it('does not remove `as boolean` from onKeyEvent when removeParameterTypes is true', () => {
|
|
2776
|
-
program.options.removeParameterTypes = true;
|
|
2777
|
-
testTranspile(`
|
|
2778
|
-
function onKeyEvent(p1) as boolean
|
|
2779
|
-
return true
|
|
2780
|
-
end function
|
|
2781
|
-
|
|
2782
|
-
function somethingElse() as string
|
|
2783
|
-
return "hello"
|
|
2784
|
-
end function
|
|
2785
|
-
`, `
|
|
2786
|
-
function onKeyEvent(p1) as boolean
|
|
2787
|
-
return true
|
|
2788
|
-
end function
|
|
2789
|
-
|
|
2790
|
-
function somethingElse()
|
|
2791
|
-
return "hello"
|
|
2792
|
-
end function
|
|
2793
|
-
`);
|
|
2794
|
-
});
|
|
2795
|
-
it('transpiles local var assignment operators', () => {
|
|
2796
|
-
testTranspile(`
|
|
2797
|
-
sub main()
|
|
2798
|
-
count = 0
|
|
2799
|
-
count += 1
|
|
2800
|
-
count -= 1
|
|
2801
|
-
count *= 1
|
|
2802
|
-
count /= 1
|
|
2803
|
-
count \\= 1
|
|
2804
|
-
count <<= 1
|
|
2805
|
-
count >>= 1
|
|
2806
|
-
end sub
|
|
2807
|
-
`);
|
|
2808
|
-
});
|
|
2809
|
-
it('transpiles AA property assignment operators', () => {
|
|
2810
|
-
testTranspile(`
|
|
2811
|
-
sub main()
|
|
2812
|
-
person = {
|
|
2813
|
-
count: 0
|
|
2814
|
-
}
|
|
2815
|
-
person.count += 1
|
|
2816
|
-
end sub
|
|
2817
|
-
`);
|
|
2818
|
-
});
|
|
2819
|
-
it('transpiles AA indexed assignment operators', () => {
|
|
2820
|
-
testTranspile(`
|
|
2821
|
-
sub main()
|
|
2822
|
-
person = {
|
|
2823
|
-
count: 0
|
|
2824
|
-
}
|
|
2825
|
-
person["count"] += 1
|
|
2826
|
-
end sub
|
|
2827
|
-
`);
|
|
2828
|
-
});
|
|
2829
|
-
it('relative-referenced namespaced functions get prefixed', () => {
|
|
2830
|
-
testTranspile(`
|
|
2831
|
-
namespace Vertibrates.Birds
|
|
2832
|
-
function GetAllBirds()
|
|
2833
|
-
return [
|
|
2834
|
-
GetDuck(),
|
|
2835
|
-
GetGoose()
|
|
2836
|
-
]
|
|
2837
|
-
end function
|
|
2838
|
-
|
|
2839
|
-
function GetDuck()
|
|
2840
|
-
end function
|
|
2841
|
-
|
|
2842
|
-
function GetGoose()
|
|
2843
|
-
end function
|
|
2844
|
-
end namespace
|
|
2845
|
-
`, `
|
|
2846
|
-
function Vertibrates_Birds_GetAllBirds()
|
|
2847
|
-
return [
|
|
2848
|
-
Vertibrates_Birds_GetDuck()
|
|
2849
|
-
Vertibrates_Birds_GetGoose()
|
|
2850
|
-
]
|
|
2851
|
-
end function
|
|
2852
|
-
|
|
2853
|
-
function Vertibrates_Birds_GetDuck()
|
|
2854
|
-
end function
|
|
2855
|
-
|
|
2856
|
-
function Vertibrates_Birds_GetGoose()
|
|
2857
|
-
end function
|
|
2858
|
-
`, 'trim', 'source/main.bs');
|
|
2859
|
-
});
|
|
2860
|
-
it('transpiles namespaced functions', () => {
|
|
2861
|
-
testTranspile(`
|
|
2862
|
-
namespace NameA
|
|
2863
|
-
sub alert()
|
|
2864
|
-
end sub
|
|
2865
|
-
end namespace
|
|
2866
|
-
namespace NameA.NameB
|
|
2867
|
-
sub alert()
|
|
2868
|
-
end sub
|
|
2869
|
-
end namespace
|
|
2870
|
-
`, `
|
|
2871
|
-
sub NameA_alert()
|
|
2872
|
-
end sub
|
|
2873
|
-
sub NameA_NameB_alert()
|
|
2874
|
-
end sub
|
|
2875
|
-
`, 'trim', 'source/main.bs');
|
|
2876
|
-
});
|
|
2877
|
-
it('transpiles dim', () => {
|
|
2878
|
-
function doTest(code) {
|
|
2879
|
-
testTranspile(`
|
|
2880
|
-
sub main()
|
|
2881
|
-
requestList = []
|
|
2882
|
-
${code}
|
|
2883
|
-
end sub
|
|
2884
|
-
`, `
|
|
2885
|
-
sub main()
|
|
2886
|
-
requestList = []
|
|
2887
|
-
${code}
|
|
2888
|
-
end sub
|
|
2889
|
-
`);
|
|
2890
|
-
}
|
|
2891
|
-
doTest(`Dim c[5]`);
|
|
2892
|
-
doTest(`Dim c[5, 4]`);
|
|
2893
|
-
doTest(`Dim c[5, 4, 6]`);
|
|
2894
|
-
doTest(`Dim requestData[requestList.count()]`);
|
|
2895
|
-
doTest(`Dim requestData[1, requestList.count()]`);
|
|
2896
|
-
doTest(`Dim requestData[1, requestList.count(), 2]`);
|
|
2897
|
-
doTest(`Dim requestData[requestList[2]]`);
|
|
2898
|
-
doTest(`Dim requestData[1, requestList[2]]`);
|
|
2899
|
-
doTest(`Dim requestData[1, requestList[2], 2]`);
|
|
2900
|
-
doTest(`Dim requestData[requestList["2"]]`);
|
|
2901
|
-
doTest(`Dim requestData[1, requestList["2"]]`);
|
|
2902
|
-
doTest(`Dim requestData[1, requestList["2"], 2]`);
|
|
2903
|
-
doTest(`Dim requestData[1, StrToI("1"), 2]`);
|
|
2904
|
-
testTranspile(`
|
|
2905
|
-
function getValue(param1)
|
|
2906
|
-
end function
|
|
2907
|
-
|
|
2908
|
-
sub main()
|
|
2909
|
-
requestList = []
|
|
2910
|
-
Dim requestData[1, getValue({
|
|
2911
|
-
key: "value"
|
|
2912
|
-
}), 2]
|
|
2913
|
-
end sub
|
|
2914
|
-
`);
|
|
2915
|
-
});
|
|
2916
|
-
it('handles multi-index multi-dimensional arrays', () => {
|
|
2917
|
-
testTranspile(`
|
|
2918
|
-
sub main()
|
|
2919
|
-
myMultiArray = [[[[[[[[["hello"]]]]]]]]]
|
|
2920
|
-
myMultiArray[0][0][0][0][0][0][0][0][0] = "goodbye"
|
|
2921
|
-
print myMultiArray[0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
2922
|
-
end sub
|
|
2923
|
-
`, `
|
|
2924
|
-
sub main()
|
|
2925
|
-
myMultiArray = [
|
|
2926
|
-
[
|
|
2927
|
-
[
|
|
2928
|
-
[
|
|
2929
|
-
[
|
|
2930
|
-
[
|
|
2931
|
-
[
|
|
2932
|
-
[
|
|
2933
|
-
[
|
|
2934
|
-
"hello"
|
|
2935
|
-
]
|
|
2936
|
-
]
|
|
2937
|
-
]
|
|
2938
|
-
]
|
|
2939
|
-
]
|
|
2940
|
-
]
|
|
2941
|
-
]
|
|
2942
|
-
]
|
|
2943
|
-
]
|
|
2944
|
-
myMultiArray[0][0][0][0][0][0][0][0][0] = "goodbye"
|
|
2945
|
-
print myMultiArray[0, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
2946
|
-
end sub
|
|
2947
|
-
`);
|
|
2948
|
-
});
|
|
2949
|
-
it('transpiles calls to fully-qualified namespaced functions', () => {
|
|
2950
|
-
testTranspile(`
|
|
2951
|
-
namespace NameA
|
|
2952
|
-
sub alert()
|
|
2953
|
-
end sub
|
|
2954
|
-
end namespace
|
|
2955
|
-
namespace NameA.NameB
|
|
2956
|
-
sub alert()
|
|
2957
|
-
end sub
|
|
2958
|
-
end namespace
|
|
2959
|
-
sub main()
|
|
2960
|
-
NameA.alert()
|
|
2961
|
-
NameA.NameB.alert()
|
|
2962
|
-
end sub
|
|
2963
|
-
`, `
|
|
2964
|
-
sub NameA_alert()
|
|
2965
|
-
end sub
|
|
2966
|
-
sub NameA_NameB_alert()
|
|
2967
|
-
end sub
|
|
2968
|
-
|
|
2969
|
-
sub main()
|
|
2970
|
-
NameA_alert()
|
|
2971
|
-
NameA_NameB_alert()
|
|
2972
|
-
end sub
|
|
2973
|
-
`, 'trim', 'source/main.bs');
|
|
2974
|
-
});
|
|
2975
|
-
it('keeps end-of-line comments with their line', () => {
|
|
2976
|
-
testTranspile(`
|
|
2977
|
-
function DoSomething() 'comment 1
|
|
2978
|
-
name = "bob" 'comment 2
|
|
2979
|
-
end function 'comment 3
|
|
2980
|
-
`);
|
|
2981
|
-
});
|
|
2982
|
-
it('works for functions', () => {
|
|
2983
|
-
testTranspile(`
|
|
2984
|
-
function DoSomething()
|
|
2985
|
-
'lots of empty white space
|
|
2986
|
-
'that will be removed during transpile
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
end function
|
|
2991
|
-
`, `
|
|
2992
|
-
function DoSomething()
|
|
2993
|
-
'lots of empty white space
|
|
2994
|
-
'that will be removed during transpile
|
|
2995
|
-
end function
|
|
2996
|
-
`);
|
|
2997
|
-
});
|
|
2998
|
-
it('keeps empty AAs and arrays on same line', () => {
|
|
2999
|
-
testTranspile(`
|
|
3000
|
-
sub a()
|
|
3001
|
-
person = {}
|
|
3002
|
-
stuff = []
|
|
3003
|
-
end sub
|
|
3004
|
-
`, null, 'trim');
|
|
3005
|
-
});
|
|
3006
|
-
it('does not add leading or trailing newlines', () => {
|
|
3007
|
-
testTranspile(`function abc()\nend function`, undefined, 'none');
|
|
3008
|
-
});
|
|
3009
|
-
it('generates proper sourcemap comment', () => {
|
|
3010
|
-
program.options.sourceMap = true;
|
|
3011
|
-
const file = program.setFile('source/main.bs', `
|
|
3012
|
-
sub main()
|
|
3013
|
-
end sub
|
|
3014
|
-
`);
|
|
3015
|
-
(0, chai_config_spec_1.expect)(file.transpile().code).to.eql((0, undent_1.default) `
|
|
3016
|
-
sub main()
|
|
3017
|
-
end sub
|
|
3018
|
-
'//# sourceMappingURL=./main.brs.map
|
|
3019
|
-
`);
|
|
3020
|
-
});
|
|
3021
|
-
it('includes sourcemap.name property', () => {
|
|
3022
|
-
program.options.sourceMap = true;
|
|
3023
|
-
const file = program.setFile('source/main.bs', `
|
|
3024
|
-
sub main()
|
|
3025
|
-
end sub
|
|
3026
|
-
`);
|
|
3027
|
-
(0, chai_config_spec_1.expect)(file.transpile().map.toJSON().file).to.eql('main.brs');
|
|
3028
|
-
});
|
|
3029
|
-
it('sourcemap sources array contains absolute path by default', () => {
|
|
3030
|
-
program.options.sourceMap = true;
|
|
3031
|
-
const file = program.setFile('source/main.bs', `
|
|
3032
|
-
sub main()
|
|
3033
|
-
end sub
|
|
3034
|
-
`);
|
|
3035
|
-
const map = file.transpile().map.toJSON();
|
|
3036
|
-
(0, chai_config_spec_1.expect)(map.sources).to.have.lengthOf(1);
|
|
3037
|
-
(0, chai_config_spec_1.expect)(path.isAbsolute(map.sources[0])).to.be.true;
|
|
3038
|
-
(0, chai_config_spec_1.expect)((0, util_1.standardizePath) `${map.sources[0]}`).to.eql((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.bs`);
|
|
3039
|
-
});
|
|
3040
|
-
it('handles sourcemap edge case', async () => {
|
|
3041
|
-
let source = 'sub main()\n' +
|
|
3042
|
-
'\n' +
|
|
3043
|
-
' print 1\n' +
|
|
3044
|
-
'\n' +
|
|
3045
|
-
'end sub';
|
|
3046
|
-
program.options.sourceMap = true;
|
|
3047
|
-
let result = testTranspile(source, `sub main()\n print 1\nend sub`, 'none', 'source/main.bs');
|
|
3048
|
-
//load the source map
|
|
3049
|
-
let location = await source_map_1.SourceMapConsumer.with(result.map.toJSON(), null, (consumer) => {
|
|
3050
|
-
return consumer.generatedPositionFor({
|
|
3051
|
-
line: 3,
|
|
3052
|
-
column: 0,
|
|
3053
|
-
source: (0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.bs`,
|
|
3054
|
-
bias: source_map_1.SourceMapConsumer.LEAST_UPPER_BOUND
|
|
3055
|
-
});
|
|
3056
|
-
});
|
|
3057
|
-
(0, chai_config_spec_1.expect)(location.line).to.eql(2);
|
|
3058
|
-
(0, chai_config_spec_1.expect)(location.column).eql(4);
|
|
3059
|
-
});
|
|
3060
|
-
it('computes correct locations for sourcemap', async () => {
|
|
3061
|
-
let source = `function abc(name)\n firstName = name\nend function`;
|
|
3062
|
-
let tokens = Lexer_1.Lexer.scan(source).tokens
|
|
3063
|
-
//remove newlines and EOF
|
|
3064
|
-
.filter(x => x.kind !== TokenKind_1.TokenKind.Eof && x.kind !== TokenKind_1.TokenKind.Newline);
|
|
3065
|
-
program.options.sourceMap = true;
|
|
3066
|
-
let result = testTranspile(source, source, 'none');
|
|
3067
|
-
//load the source map
|
|
3068
|
-
await source_map_1.SourceMapConsumer.with(result.map.toString(), null, (consumer) => {
|
|
3069
|
-
let tokenResult = tokens.map(token => ({
|
|
3070
|
-
kind: token.kind,
|
|
3071
|
-
start: token.range.start
|
|
3072
|
-
}));
|
|
3073
|
-
let sourcemapResult = tokens.map(token => {
|
|
3074
|
-
let originalPosition = consumer.originalPositionFor({
|
|
3075
|
-
//convert token 0-based line to source-map 1-based line for the lookup
|
|
3076
|
-
line: token.range.start.line + 1,
|
|
3077
|
-
column: token.range.start.character
|
|
3078
|
-
});
|
|
3079
|
-
return {
|
|
3080
|
-
kind: token.kind,
|
|
3081
|
-
start: vscode_languageserver_1.Position.create(
|
|
3082
|
-
//convert source-map 1-based line to token 0-based line
|
|
3083
|
-
originalPosition.line - 1, originalPosition.column)
|
|
3084
|
-
};
|
|
3085
|
-
});
|
|
3086
|
-
(0, chai_config_spec_1.expect)(sourcemapResult).to.eql(tokenResult);
|
|
3087
|
-
});
|
|
3088
|
-
});
|
|
3089
|
-
it('handles empty if block', () => {
|
|
3090
|
-
testTranspile(`
|
|
3091
|
-
sub main()
|
|
3092
|
-
if true then
|
|
3093
|
-
end if
|
|
3094
|
-
if true then
|
|
3095
|
-
else
|
|
3096
|
-
print "else"
|
|
3097
|
-
end if
|
|
3098
|
-
if true then
|
|
3099
|
-
else if true then
|
|
3100
|
-
print "else"
|
|
3101
|
-
end if
|
|
3102
|
-
if true then
|
|
3103
|
-
else if true then
|
|
3104
|
-
print "elseif"
|
|
3105
|
-
else
|
|
3106
|
-
print "else"
|
|
3107
|
-
end if
|
|
3108
|
-
end sub
|
|
3109
|
-
`);
|
|
3110
|
-
});
|
|
3111
|
-
it('handles empty elseif block', () => {
|
|
3112
|
-
testTranspile(`
|
|
3113
|
-
sub main()
|
|
3114
|
-
if true then
|
|
3115
|
-
print "if"
|
|
3116
|
-
else if true then
|
|
3117
|
-
end if
|
|
3118
|
-
if true then
|
|
3119
|
-
print "if"
|
|
3120
|
-
else if true then
|
|
3121
|
-
else if true then
|
|
3122
|
-
end if
|
|
3123
|
-
end sub
|
|
3124
|
-
`);
|
|
3125
|
-
});
|
|
3126
|
-
it('handles empty else block', () => {
|
|
3127
|
-
testTranspile(`
|
|
3128
|
-
sub main()
|
|
3129
|
-
if true then
|
|
3130
|
-
print "if"
|
|
3131
|
-
else
|
|
3132
|
-
end if
|
|
3133
|
-
if true then
|
|
3134
|
-
print "if"
|
|
3135
|
-
else if true then
|
|
3136
|
-
print "elseif"
|
|
3137
|
-
else
|
|
3138
|
-
end if
|
|
3139
|
-
end sub
|
|
3140
|
-
`);
|
|
3141
|
-
});
|
|
3142
|
-
it('handles else block with a leading comment', () => {
|
|
3143
|
-
testTranspile(`
|
|
3144
|
-
sub main()
|
|
3145
|
-
if true then
|
|
3146
|
-
print "if"
|
|
3147
|
-
else
|
|
3148
|
-
' leading comment
|
|
3149
|
-
print "else"
|
|
3150
|
-
end if
|
|
3151
|
-
end sub
|
|
3152
|
-
`);
|
|
3153
|
-
});
|
|
3154
|
-
it('works for function parameters', () => {
|
|
3155
|
-
testTranspile(`
|
|
3156
|
-
function DoSomething(name, age as integer, text as string)
|
|
3157
|
-
end function
|
|
3158
|
-
`, `
|
|
3159
|
-
function DoSomething(name, age as integer, text as string)
|
|
3160
|
-
end function
|
|
3161
|
-
`);
|
|
3162
|
-
});
|
|
3163
|
-
it('adds newlines between top-level statements', () => {
|
|
3164
|
-
testTranspile(`
|
|
3165
|
-
function a()
|
|
3166
|
-
end function
|
|
3167
|
-
|
|
3168
|
-
function b()
|
|
3169
|
-
end function
|
|
3170
|
-
`);
|
|
3171
|
-
});
|
|
3172
|
-
it('properly indents nested AA literals', () => {
|
|
3173
|
-
testTranspile(`
|
|
3174
|
-
sub doSomething()
|
|
3175
|
-
grandparent = {
|
|
3176
|
-
parent: {
|
|
3177
|
-
child: {
|
|
3178
|
-
grandchild: {
|
|
3179
|
-
name: "baby"
|
|
3180
|
-
}
|
|
3181
|
-
}
|
|
3182
|
-
}
|
|
3183
|
-
}
|
|
3184
|
-
end sub
|
|
3185
|
-
`);
|
|
3186
|
-
});
|
|
3187
|
-
it('does not add comma after final object property even when comments are present', () => {
|
|
3188
|
-
testTranspile(`
|
|
3189
|
-
sub doSomething()
|
|
3190
|
-
person = {
|
|
3191
|
-
age: 12 'comment
|
|
3192
|
-
name: "child"
|
|
3193
|
-
}
|
|
3194
|
-
person = {
|
|
3195
|
-
age: 12 'comment
|
|
3196
|
-
name: "child" 'comment
|
|
3197
|
-
}
|
|
3198
|
-
person = {
|
|
3199
|
-
age: 12 'comment
|
|
3200
|
-
name: "child"
|
|
3201
|
-
'comment
|
|
3202
|
-
}
|
|
3203
|
-
person = {
|
|
3204
|
-
age: 12 'comment
|
|
3205
|
-
name: "child" 'comment
|
|
3206
|
-
'comment
|
|
3207
|
-
}
|
|
3208
|
-
end sub
|
|
3209
|
-
`);
|
|
3210
|
-
});
|
|
3211
|
-
it('works for a complex function with comments all over the place', () => {
|
|
3212
|
-
testTranspile(`
|
|
3213
|
-
'import some library
|
|
3214
|
-
library "v30/bslCore.brs" 'comment
|
|
3215
|
-
|
|
3216
|
-
'a function that does something
|
|
3217
|
-
function doSomething(age as integer, name = "bob") 'comment
|
|
3218
|
-
person = { 'comment
|
|
3219
|
-
name: "parent" 'comment
|
|
3220
|
-
"age": 12
|
|
3221
|
-
'comment as whole line
|
|
3222
|
-
child: { 'comment
|
|
3223
|
-
name: "child" 'comment
|
|
3224
|
-
}
|
|
3225
|
-
}
|
|
3226
|
-
person.name = "john" 'comment
|
|
3227
|
-
person.child.name = "baby" 'comment
|
|
3228
|
-
person["name"] = person.child["name"] 'comment
|
|
3229
|
-
age = 12 + 2 'comment
|
|
3230
|
-
name = "tim" 'comment
|
|
3231
|
-
age = 12 'comment
|
|
3232
|
-
while true 'comment
|
|
3233
|
-
age = age + 1 'comment
|
|
3234
|
-
exit while 'comment
|
|
3235
|
-
end while 'comment
|
|
3236
|
-
while age < 12 or age < 15 'comment
|
|
3237
|
-
age++ 'comment
|
|
3238
|
-
exit while 'comment
|
|
3239
|
-
end while 'comment
|
|
3240
|
-
if true or 1 = 1 or name = "tim" then 'comment
|
|
3241
|
-
print false 'comment
|
|
3242
|
-
else if false or "cat" = "dog" or true then 'comment
|
|
3243
|
-
print "true" 'comment
|
|
3244
|
-
else 'comment
|
|
3245
|
-
print "else" 'comment
|
|
3246
|
-
end if 'comment
|
|
3247
|
-
someBool = (true or false) or ((true) or (false)) 'comment
|
|
3248
|
-
mylabel: 'comment
|
|
3249
|
-
goto mylabel 'comment
|
|
3250
|
-
age++ 'comment
|
|
3251
|
-
age-- 'comment
|
|
3252
|
-
end 'comment
|
|
3253
|
-
stop 'comment
|
|
3254
|
-
indexes = [ 'comment
|
|
3255
|
-
'comment on its own line
|
|
3256
|
-
1 'comment
|
|
3257
|
-
2 'comment
|
|
3258
|
-
3 'comment
|
|
3259
|
-
] 'comment
|
|
3260
|
-
firstIndex = indexes[0] 'comment
|
|
3261
|
-
for each idx in indexes 'comment
|
|
3262
|
-
indexes[idx] = idx + 1 'comment
|
|
3263
|
-
end for 'comment
|
|
3264
|
-
if not true then 'comment
|
|
3265
|
-
print "false" 'comment
|
|
3266
|
-
end if 'comment 'comment
|
|
3267
|
-
for i = 0 to 10 step 1 'comment
|
|
3268
|
-
name = "bob" 'comment
|
|
3269
|
-
age = 12 'comment
|
|
3270
|
-
exit for 'comment
|
|
3271
|
-
end for 'comment
|
|
3272
|
-
callback = function(name, age as integer, cb as Function) as integer 'comment
|
|
3273
|
-
returnValue = 12 'comment
|
|
3274
|
-
return returnValue 'comment
|
|
3275
|
-
end function 'comment
|
|
3276
|
-
print "a"; "b"; 3 'comment
|
|
3277
|
-
a(1, 2, 3) 'comment
|
|
3278
|
-
person.functionCall(1, 2, 3) 'comment
|
|
3279
|
-
if true then 'comment
|
|
3280
|
-
level = 1 'comment
|
|
3281
|
-
if false then 'comment
|
|
3282
|
-
level = 2 'comment
|
|
3283
|
-
if true or false then 'comment
|
|
3284
|
-
level = 3 'comment
|
|
3285
|
-
if false and true then 'comment
|
|
3286
|
-
level = 4 'comment
|
|
3287
|
-
end if 'comment
|
|
3288
|
-
end if 'comment
|
|
3289
|
-
end if 'comment
|
|
3290
|
-
end if 'comment
|
|
3291
|
-
end function
|
|
3292
|
-
|
|
3293
|
-
function a(p1, p2, p3) 'comment
|
|
3294
|
-
end function 'comment
|
|
3295
|
-
`);
|
|
3296
|
-
});
|
|
3297
|
-
it('simple mapped files include a reference to the source map', () => {
|
|
3298
|
-
let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
|
|
3299
|
-
sub logInfo()
|
|
3300
|
-
end sub
|
|
3301
|
-
`);
|
|
3302
|
-
file.needsTranspiled = false;
|
|
3303
|
-
const { code } = file.transpile();
|
|
3304
|
-
(0, chai_config_spec_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
|
|
3305
|
-
});
|
|
3306
|
-
it('AST generated files include a reference to the source map', () => {
|
|
3307
|
-
let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
|
|
3308
|
-
sub logInfo()
|
|
3309
|
-
end sub
|
|
3310
|
-
`);
|
|
3311
|
-
file.needsTranspiled = true;
|
|
3312
|
-
const { code } = file.transpile();
|
|
3313
|
-
(0, chai_config_spec_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
|
|
3314
|
-
});
|
|
3315
|
-
it('replaces custom types in parameter types and return types', () => {
|
|
3316
|
-
program.setFile('source/SomeKlass.bs', `
|
|
3317
|
-
class SomeKlass
|
|
3318
|
-
end class
|
|
3319
|
-
`);
|
|
3320
|
-
testTranspile(`
|
|
3321
|
-
function foo() as SomeKlass
|
|
3322
|
-
return new SomeKlass()
|
|
3323
|
-
end function
|
|
3324
|
-
|
|
3325
|
-
sub bar(obj as SomeKlass)
|
|
3326
|
-
end sub
|
|
3327
|
-
`, `
|
|
3328
|
-
function foo() as object
|
|
3329
|
-
return SomeKlass()
|
|
3330
|
-
end function
|
|
3331
|
-
|
|
3332
|
-
sub bar(obj as object)
|
|
3333
|
-
end sub
|
|
3334
|
-
`);
|
|
3335
|
-
});
|
|
3336
|
-
});
|
|
3337
|
-
describe('callfunc operator', () => {
|
|
3338
|
-
describe('transpile', () => {
|
|
3339
|
-
it('does not produce diagnostics', () => {
|
|
3340
|
-
program.setFile('source/main.bs', `
|
|
3341
|
-
sub test()
|
|
3342
|
-
someNode = createObject("roSGNode", "Rectangle")
|
|
3343
|
-
someNode@.someFunction(test.value)
|
|
3344
|
-
end sub
|
|
3345
|
-
`);
|
|
3346
|
-
program.validate();
|
|
3347
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3348
|
-
});
|
|
3349
|
-
it('sets invalid on empty callfunc', () => {
|
|
3350
|
-
testTranspile(`
|
|
3351
|
-
sub main()
|
|
3352
|
-
node = invalid
|
|
3353
|
-
node@.doSomething()
|
|
3354
|
-
m.top.node@.doSomething()
|
|
3355
|
-
m.top.node@.doSomething(1)
|
|
3356
|
-
end sub
|
|
3357
|
-
`, `
|
|
3358
|
-
sub main()
|
|
3359
|
-
node = invalid
|
|
3360
|
-
node.callfunc("doSomething", invalid)
|
|
3361
|
-
m.top.node.callfunc("doSomething", invalid)
|
|
3362
|
-
m.top.node.callfunc("doSomething", 1)
|
|
3363
|
-
end sub
|
|
3364
|
-
`);
|
|
3365
|
-
});
|
|
3366
|
-
it('includes original arguments', () => {
|
|
3367
|
-
testTranspile(`
|
|
3368
|
-
sub main()
|
|
3369
|
-
node = invalid
|
|
3370
|
-
node@.doSomething(1, true, m.top.someVal)
|
|
3371
|
-
end sub
|
|
3372
|
-
`, `
|
|
3373
|
-
sub main()
|
|
3374
|
-
node = invalid
|
|
3375
|
-
node.callfunc("doSomething", 1, true, m.top.someVal)
|
|
3376
|
-
end sub
|
|
3377
|
-
`);
|
|
3378
|
-
});
|
|
3379
|
-
});
|
|
3380
|
-
});
|
|
3381
|
-
describe('transform callback', () => {
|
|
3382
|
-
function parseFileWithCallback(ext, onParsed) {
|
|
3383
|
-
const rootDir = process.cwd();
|
|
3384
|
-
const program = new Program_1.Program({
|
|
3385
|
-
rootDir: rootDir
|
|
3386
|
-
});
|
|
3387
|
-
program.plugins.add({
|
|
3388
|
-
name: 'transform callback',
|
|
3389
|
-
afterFileParse: onParsed
|
|
3390
|
-
});
|
|
3391
|
-
file = program.setFile(`source/file${ext}`, `
|
|
3392
|
-
sub Sum()
|
|
3393
|
-
print "hello world"
|
|
3394
|
-
end sub
|
|
3395
|
-
`);
|
|
3396
|
-
(0, chai_config_spec_1.expect)(file.extension).to.equal(ext);
|
|
3397
|
-
return file;
|
|
3398
|
-
}
|
|
3399
|
-
it('called for BRS file', () => {
|
|
3400
|
-
const onParsed = sinon.spy();
|
|
3401
|
-
parseFileWithCallback('.brs', onParsed);
|
|
3402
|
-
(0, chai_config_spec_1.expect)(onParsed.callCount).to.equal(1);
|
|
3403
|
-
});
|
|
3404
|
-
it('called for BR file', () => {
|
|
3405
|
-
const onParsed = sinon.spy();
|
|
3406
|
-
parseFileWithCallback('.bs', onParsed);
|
|
3407
|
-
(0, chai_config_spec_1.expect)(onParsed.callCount).to.equal(1);
|
|
3408
|
-
});
|
|
3409
|
-
});
|
|
3410
|
-
describe('typedefKey', () => {
|
|
3411
|
-
it('works for .brs files', () => {
|
|
3412
|
-
(0, chai_config_spec_1.expect)((0, util_1.standardizePath)((program.setFile('source/main.brs', '')).typedefKey)).to.equal((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir.toLowerCase()}/source/main.d.bs`);
|
|
3413
|
-
});
|
|
3414
|
-
it('returns undefined for files that should not have a typedef', () => {
|
|
3415
|
-
(0, chai_config_spec_1.expect)((program.setFile('source/main.bs', '')).typedefKey).to.be.undefined;
|
|
3416
|
-
(0, chai_config_spec_1.expect)((program.setFile('source/main.d.bs', '')).typedefKey).to.be.undefined;
|
|
3417
|
-
const xmlFile = program.setFile('components/comp.xml', '');
|
|
3418
|
-
(0, chai_config_spec_1.expect)(xmlFile.typedefKey).to.be.undefined;
|
|
3419
|
-
});
|
|
3420
|
-
});
|
|
3421
|
-
describe('type definitions', () => {
|
|
3422
|
-
it('only exposes defined functions even if source has more', () => {
|
|
3423
|
-
//parse the .brs file first so it doesn't know about the typedef
|
|
3424
|
-
program.setFile('source/main.brs', `
|
|
3425
|
-
sub main()
|
|
3426
|
-
end sub
|
|
3427
|
-
sub speak()
|
|
3428
|
-
end sub
|
|
3429
|
-
`);
|
|
3430
|
-
program.setFile('source/main.d.bs', `
|
|
3431
|
-
sub main()
|
|
3432
|
-
end sub
|
|
3433
|
-
`);
|
|
3434
|
-
const sourceScope = program.getScopeByName('source');
|
|
3435
|
-
const functionNames = sourceScope.getAllCallables().map(x => x.callable.name);
|
|
3436
|
-
(0, chai_config_spec_1.expect)(functionNames).to.include('main');
|
|
3437
|
-
(0, chai_config_spec_1.expect)(functionNames).not.to.include('speak');
|
|
3438
|
-
});
|
|
3439
|
-
it('reacts to typedef file changes', () => {
|
|
3440
|
-
let file = program.setFile('source/main.brs', `
|
|
3441
|
-
sub main()
|
|
3442
|
-
end sub
|
|
3443
|
-
sub speak()
|
|
3444
|
-
end sub
|
|
3445
|
-
`);
|
|
3446
|
-
(0, chai_config_spec_1.expect)(file.hasTypedef).to.be.false;
|
|
3447
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).not.to.exist;
|
|
3448
|
-
program.setFile('source/main.d.bs', `
|
|
3449
|
-
sub main()
|
|
3450
|
-
end sub
|
|
3451
|
-
`);
|
|
3452
|
-
(0, chai_config_spec_1.expect)(file.hasTypedef).to.be.true;
|
|
3453
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).to.exist;
|
|
3454
|
-
//add replace file, does it still find the typedef
|
|
3455
|
-
file = program.setFile('source/main.brs', `
|
|
3456
|
-
sub main()
|
|
3457
|
-
end sub
|
|
3458
|
-
sub speak()
|
|
3459
|
-
end sub
|
|
3460
|
-
`);
|
|
3461
|
-
(0, chai_config_spec_1.expect)(file.hasTypedef).to.be.true;
|
|
3462
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).to.exist;
|
|
3463
|
-
program.removeFile((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main.d.bs`);
|
|
3464
|
-
(0, chai_config_spec_1.expect)(file.hasTypedef).to.be.false;
|
|
3465
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).not.to.exist;
|
|
3466
|
-
});
|
|
3467
|
-
});
|
|
3468
|
-
describe('typedef', () => {
|
|
3469
|
-
it('includes enum and interface types', () => {
|
|
3470
|
-
testGetTypedef(`
|
|
3471
|
-
interface Foo
|
|
3472
|
-
field as string
|
|
3473
|
-
end interface
|
|
3474
|
-
|
|
3475
|
-
enum Bar
|
|
3476
|
-
value
|
|
3477
|
-
end enum
|
|
3478
|
-
|
|
3479
|
-
function baz(parameter as Foo) as Bar
|
|
3480
|
-
return Bar.value
|
|
3481
|
-
end function
|
|
3482
|
-
`, `
|
|
3483
|
-
interface Foo
|
|
3484
|
-
field as string
|
|
3485
|
-
end interface
|
|
3486
|
-
|
|
3487
|
-
enum Bar
|
|
3488
|
-
value
|
|
3489
|
-
end enum
|
|
3490
|
-
function baz(parameter as Foo) as Bar
|
|
3491
|
-
end function
|
|
3492
|
-
`);
|
|
3493
|
-
});
|
|
3494
|
-
it('sets typedef path properly', () => {
|
|
3495
|
-
(0, chai_config_spec_1.expect)((program.setFile('source/main1.brs', '')).typedefKey).to.equal((0, util_1.standardizePath) `${testHelpers_spec_2.rootDir}/source/main1.d.bs`.toLowerCase());
|
|
3496
|
-
(0, chai_config_spec_1.expect)((program.setFile('source/main2.d.bs', '')).typedefKey).to.equal(undefined);
|
|
3497
|
-
(0, chai_config_spec_1.expect)((program.setFile('source/main3.bs', '')).typedefKey).to.equal(undefined);
|
|
3498
|
-
//works for dest with `.brs` extension
|
|
3499
|
-
(0, chai_config_spec_1.expect)((program.setFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefKey).to.equal(undefined);
|
|
3500
|
-
});
|
|
3501
|
-
it('does not link when missing from program', () => {
|
|
3502
|
-
const file = program.setFile('source/main.brs', ``);
|
|
3503
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).not.to.exist;
|
|
3504
|
-
});
|
|
3505
|
-
it('links typedef when added BEFORE .brs file', () => {
|
|
3506
|
-
const typedef = program.setFile('source/main.d.bs', ``);
|
|
3507
|
-
const file = program.setFile('source/main.brs', ``);
|
|
3508
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).to.equal(typedef);
|
|
3509
|
-
});
|
|
3510
|
-
it('links typedef when added AFTER .brs file', () => {
|
|
3511
|
-
const file = program.setFile('source/main.brs', ``);
|
|
3512
|
-
const typedef = program.setFile('source/main.d.bs', ``);
|
|
3513
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).to.eql(typedef);
|
|
3514
|
-
});
|
|
3515
|
-
it('removes typedef link when typedef is removed', () => {
|
|
3516
|
-
const typedef = program.setFile('source/main.d.bs', ``);
|
|
3517
|
-
const file = program.setFile('source/main.brs', ``);
|
|
3518
|
-
program.removeFile(typedef.srcPath);
|
|
3519
|
-
(0, chai_config_spec_1.expect)(file.typedefFile).to.be.undefined;
|
|
3520
|
-
});
|
|
3521
|
-
});
|
|
3522
|
-
describe('getTypedef', () => {
|
|
3523
|
-
function testTypedef(original, expected) {
|
|
3524
|
-
let file = program.setFile('source/main.brs', original);
|
|
3525
|
-
program.validate();
|
|
3526
|
-
(0, chai_config_spec_1.expect)(file.getTypedef().trimEnd()).to.eql(expected);
|
|
3527
|
-
}
|
|
3528
|
-
it('includes namespace on extend class names', () => {
|
|
3529
|
-
testTypedef(`
|
|
3530
|
-
namespace AnimalKingdom
|
|
3531
|
-
class Bird
|
|
3532
|
-
end class
|
|
3533
|
-
class Duck extends Bird
|
|
3534
|
-
end class
|
|
3535
|
-
end namespace
|
|
3536
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3537
|
-
namespace AnimalKingdom
|
|
3538
|
-
class Bird
|
|
3539
|
-
sub new()
|
|
3540
|
-
end sub
|
|
3541
|
-
end class
|
|
3542
|
-
class Duck extends AnimalKingdom.Bird
|
|
3543
|
-
sub new()
|
|
3544
|
-
end sub
|
|
3545
|
-
end class
|
|
3546
|
-
end namespace
|
|
3547
|
-
`);
|
|
3548
|
-
});
|
|
3549
|
-
it('strips function body', () => {
|
|
3550
|
-
testTypedef(`
|
|
3551
|
-
sub main(param1 as string)
|
|
3552
|
-
print "main"
|
|
3553
|
-
end sub
|
|
3554
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3555
|
-
sub main(param1 as string)
|
|
3556
|
-
end sub
|
|
3557
|
-
`);
|
|
3558
|
-
});
|
|
3559
|
-
it('includes annotations', () => {
|
|
3560
|
-
testTypedef(`
|
|
3561
|
-
namespace test
|
|
3562
|
-
@an
|
|
3563
|
-
@anFunc("value")
|
|
3564
|
-
function getDuck()
|
|
3565
|
-
end function
|
|
3566
|
-
class Duck
|
|
3567
|
-
@anMember
|
|
3568
|
-
@anMember("field")
|
|
3569
|
-
private thing
|
|
3570
|
-
|
|
3571
|
-
@anMember
|
|
3572
|
-
@anMember("func")
|
|
3573
|
-
private function foo()
|
|
3574
|
-
end function
|
|
3575
|
-
end class
|
|
3576
|
-
end namespace
|
|
3577
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3578
|
-
namespace test
|
|
3579
|
-
@an
|
|
3580
|
-
@anFunc("value")
|
|
3581
|
-
function getDuck()
|
|
3582
|
-
end function
|
|
3583
|
-
class Duck
|
|
3584
|
-
sub new()
|
|
3585
|
-
end sub
|
|
3586
|
-
@anMember
|
|
3587
|
-
@anMember("field")
|
|
3588
|
-
private thing as dynamic
|
|
3589
|
-
@anMember
|
|
3590
|
-
@anMember("func")
|
|
3591
|
-
private function foo()
|
|
3592
|
-
end function
|
|
3593
|
-
end class
|
|
3594
|
-
end namespace
|
|
3595
|
-
`);
|
|
3596
|
-
});
|
|
3597
|
-
it('includes import statements', () => {
|
|
3598
|
-
testTypedef(`
|
|
3599
|
-
import "pkg:/source/lib.brs"
|
|
3600
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3601
|
-
import "pkg:/source/lib.brs"
|
|
3602
|
-
`);
|
|
3603
|
-
});
|
|
3604
|
-
it('includes namespace statements', () => {
|
|
3605
|
-
testTypedef(`
|
|
3606
|
-
namespace Name
|
|
3607
|
-
sub logInfo()
|
|
3608
|
-
end sub
|
|
3609
|
-
end namespace
|
|
3610
|
-
namespace NameA.NameB
|
|
3611
|
-
sub logInfo()
|
|
3612
|
-
end sub
|
|
3613
|
-
end namespace
|
|
3614
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3615
|
-
namespace Name
|
|
3616
|
-
sub logInfo()
|
|
3617
|
-
end sub
|
|
3618
|
-
end namespace
|
|
3619
|
-
namespace NameA.NameB
|
|
3620
|
-
sub logInfo()
|
|
3621
|
-
end sub
|
|
3622
|
-
end namespace
|
|
3623
|
-
`);
|
|
3624
|
-
});
|
|
3625
|
-
it('includes classes', () => {
|
|
3626
|
-
testTypedef(`
|
|
3627
|
-
class Person
|
|
3628
|
-
public name as string
|
|
3629
|
-
public age = 12
|
|
3630
|
-
public sub getAge() as integer
|
|
3631
|
-
return m.age
|
|
3632
|
-
end sub
|
|
3633
|
-
end class
|
|
3634
|
-
namespace NameA.NameB
|
|
3635
|
-
class Person
|
|
3636
|
-
public name as string
|
|
3637
|
-
public age = 12
|
|
3638
|
-
public sub getAge() as integer
|
|
3639
|
-
return m.age
|
|
3640
|
-
end sub
|
|
3641
|
-
end class
|
|
3642
|
-
end namespace
|
|
3643
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3644
|
-
class Person
|
|
3645
|
-
sub new()
|
|
3646
|
-
end sub
|
|
3647
|
-
public name as string
|
|
3648
|
-
public age as integer
|
|
3649
|
-
public sub getAge() as integer
|
|
3650
|
-
end sub
|
|
3651
|
-
end class
|
|
3652
|
-
namespace NameA.NameB
|
|
3653
|
-
class Person
|
|
3654
|
-
sub new()
|
|
3655
|
-
end sub
|
|
3656
|
-
public name as string
|
|
3657
|
-
public age as integer
|
|
3658
|
-
public sub getAge() as integer
|
|
3659
|
-
end sub
|
|
3660
|
-
end class
|
|
3661
|
-
end namespace
|
|
3662
|
-
`);
|
|
3663
|
-
});
|
|
3664
|
-
it('creates constructor properly', () => {
|
|
3665
|
-
testTypedef(`
|
|
3666
|
-
class Parent
|
|
3667
|
-
end class
|
|
3668
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3669
|
-
class Parent
|
|
3670
|
-
sub new()
|
|
3671
|
-
end sub
|
|
3672
|
-
end class
|
|
3673
|
-
`);
|
|
3674
|
-
});
|
|
3675
|
-
it('sets properties to dynamic when initialized to invalid', () => {
|
|
3676
|
-
testTypedef(`
|
|
3677
|
-
class Human
|
|
3678
|
-
public firstName = invalid
|
|
3679
|
-
public lastName as string = invalid
|
|
3680
|
-
end class
|
|
3681
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3682
|
-
class Human
|
|
3683
|
-
sub new()
|
|
3684
|
-
end sub
|
|
3685
|
-
public firstName as dynamic
|
|
3686
|
-
public lastName as string
|
|
3687
|
-
end class
|
|
3688
|
-
`);
|
|
3689
|
-
});
|
|
3690
|
-
it('includes class inheritance', () => {
|
|
3691
|
-
testTypedef(`
|
|
3692
|
-
class Human
|
|
3693
|
-
sub new(name as string)
|
|
3694
|
-
m.name = name
|
|
3695
|
-
end sub
|
|
3696
|
-
end class
|
|
3697
|
-
class Person extends Human
|
|
3698
|
-
sub new(name as string)
|
|
3699
|
-
super(name)
|
|
3700
|
-
end sub
|
|
3701
|
-
end class
|
|
3702
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3703
|
-
class Human
|
|
3704
|
-
sub new(name as string)
|
|
3705
|
-
end sub
|
|
3706
|
-
end class
|
|
3707
|
-
class Person extends Human
|
|
3708
|
-
sub new(name as string)
|
|
3709
|
-
end sub
|
|
3710
|
-
end class
|
|
3711
|
-
`);
|
|
3712
|
-
});
|
|
3713
|
-
it('includes access modifier keyword', () => {
|
|
3714
|
-
testTypedef(`
|
|
3715
|
-
class Human
|
|
3716
|
-
public firstName as string
|
|
3717
|
-
protected middleName as string
|
|
3718
|
-
private lastName as string
|
|
3719
|
-
public function getFirstName()
|
|
3720
|
-
return m.firstName
|
|
3721
|
-
end function
|
|
3722
|
-
protected function getMiddleName()
|
|
3723
|
-
return m.middleName
|
|
3724
|
-
end function
|
|
3725
|
-
private function getLastName()
|
|
3726
|
-
return m.lastName
|
|
3727
|
-
end function
|
|
3728
|
-
end class
|
|
3729
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3730
|
-
class Human
|
|
3731
|
-
sub new()
|
|
3732
|
-
end sub
|
|
3733
|
-
public firstName as string
|
|
3734
|
-
protected middleName as string
|
|
3735
|
-
private lastName as string
|
|
3736
|
-
public function getFirstName()
|
|
3737
|
-
end function
|
|
3738
|
-
protected function getMiddleName()
|
|
3739
|
-
end function
|
|
3740
|
-
private function getLastName()
|
|
3741
|
-
end function
|
|
3742
|
-
end class
|
|
3743
|
-
`);
|
|
3744
|
-
});
|
|
3745
|
-
it('includes overrides keyword if present in source', () => {
|
|
3746
|
-
testTypedef(`
|
|
3747
|
-
class Animal
|
|
3748
|
-
public sub speak()
|
|
3749
|
-
print "Hello Animal"
|
|
3750
|
-
end sub
|
|
3751
|
-
end class
|
|
3752
|
-
class Dog extends Animal
|
|
3753
|
-
public override sub speak()
|
|
3754
|
-
print "Hello Dog"
|
|
3755
|
-
end sub
|
|
3756
|
-
end class
|
|
3757
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3758
|
-
class Animal
|
|
3759
|
-
sub new()
|
|
3760
|
-
end sub
|
|
3761
|
-
public sub speak()
|
|
3762
|
-
end sub
|
|
3763
|
-
end class
|
|
3764
|
-
class Dog extends Animal
|
|
3765
|
-
sub new()
|
|
3766
|
-
end sub
|
|
3767
|
-
public override sub speak()
|
|
3768
|
-
end sub
|
|
3769
|
-
end class
|
|
3770
|
-
`);
|
|
3771
|
-
});
|
|
3772
|
-
it('includes class inheritance cross-namespace', () => {
|
|
3773
|
-
testTypedef(`
|
|
3774
|
-
namespace NameA
|
|
3775
|
-
class Human
|
|
3776
|
-
sub new(name as string)
|
|
3777
|
-
m.name = name
|
|
3778
|
-
end sub
|
|
3779
|
-
end class
|
|
3780
|
-
end namespace
|
|
3781
|
-
namespace NameB
|
|
3782
|
-
class Person extends NameA.Human
|
|
3783
|
-
sub new(name as string)
|
|
3784
|
-
super(name)
|
|
3785
|
-
end sub
|
|
3786
|
-
end class
|
|
3787
|
-
end namespace
|
|
3788
|
-
`, (0, testHelpers_spec_1.trim) `
|
|
3789
|
-
namespace NameA
|
|
3790
|
-
class Human
|
|
3791
|
-
sub new(name as string)
|
|
3792
|
-
end sub
|
|
3793
|
-
end class
|
|
3794
|
-
end namespace
|
|
3795
|
-
namespace NameB
|
|
3796
|
-
class Person extends NameA.Human
|
|
3797
|
-
sub new(name as string)
|
|
3798
|
-
end sub
|
|
3799
|
-
end class
|
|
3800
|
-
end namespace
|
|
3801
|
-
`);
|
|
3802
|
-
});
|
|
3803
|
-
});
|
|
3804
|
-
describe('parser getter', () => {
|
|
3805
|
-
it('recreates the parser when missing', () => {
|
|
3806
|
-
const file = program.setFile('source/main.brs', `
|
|
3807
|
-
sub main()
|
|
3808
|
-
end sub
|
|
3809
|
-
`);
|
|
3810
|
-
const parser = file['_parser'];
|
|
3811
|
-
//clear the private _parser instance
|
|
3812
|
-
file['_parser'] = undefined;
|
|
3813
|
-
//force the file to get a new instance of parser
|
|
3814
|
-
const newParser = file.parser;
|
|
3815
|
-
(0, chai_config_spec_1.expect)(newParser).to.exist.and.to.not.equal(parser);
|
|
3816
|
-
//reference shouldn't change in subsequent accesses
|
|
3817
|
-
(0, chai_config_spec_1.expect)(file.parser).to.equal(newParser);
|
|
3818
|
-
});
|
|
3819
|
-
it('call parse when previously skipped', () => {
|
|
3820
|
-
program.setFile('source/main.d.bs', `'typedef
|
|
3821
|
-
sub main()
|
|
3822
|
-
end sub
|
|
3823
|
-
`);
|
|
3824
|
-
const file = program.setFile('source/main.brs', `'source
|
|
3825
|
-
sub main()
|
|
3826
|
-
end sub
|
|
3827
|
-
`);
|
|
3828
|
-
//no functions should be found since the parser was skipped
|
|
3829
|
-
(0, chai_config_spec_1.expect)(file['_parser']).to.not.exist;
|
|
3830
|
-
const stub = sinon.stub(file, 'parse').callThrough();
|
|
3831
|
-
//`file.parser` is a getter, so that should force the parse to occur
|
|
3832
|
-
(0, chai_config_spec_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(1);
|
|
3833
|
-
(0, chai_config_spec_1.expect)(stub.called).to.be.true;
|
|
3834
|
-
//parse should have been called
|
|
3835
|
-
});
|
|
3836
|
-
});
|
|
3837
|
-
describe('Plugins', () => {
|
|
3838
|
-
let pluginFileName;
|
|
3839
|
-
let idx = 1;
|
|
3840
|
-
beforeEach(() => {
|
|
3841
|
-
pluginFileName = `plugin-${idx++}.js`;
|
|
3842
|
-
fsExtra.outputFileSync((0, util_1.standardizePath) `${testHelpers_spec_2.tempDir}/plugins/${pluginFileName}`, `
|
|
3843
|
-
function plugin() {
|
|
3844
|
-
return {
|
|
3845
|
-
name: 'lower-file-name',
|
|
3846
|
-
afterFileParse: (evt) => {
|
|
3847
|
-
evt._customProp = true;
|
|
3848
|
-
}
|
|
3849
|
-
};
|
|
3850
|
-
}
|
|
3851
|
-
exports.default = plugin;
|
|
3852
|
-
`);
|
|
3853
|
-
});
|
|
3854
|
-
it('can load an absolute plugin which receives callbacks', () => {
|
|
3855
|
-
program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(testHelpers_spec_2.tempDir, [
|
|
3856
|
-
(0, util_1.standardizePath) `${testHelpers_spec_2.tempDir}/plugins/${pluginFileName}`
|
|
3857
|
-
]), { logger: (0, logging_1.createLogger)() });
|
|
3858
|
-
const file = program.setFile('source/MAIN.brs', '');
|
|
3859
|
-
(0, chai_config_spec_1.expect)(file._customProp).to.exist;
|
|
3860
|
-
});
|
|
3861
|
-
it('can load a relative plugin which receives callbacks', () => {
|
|
3862
|
-
program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(testHelpers_spec_2.tempDir, [
|
|
3863
|
-
`./plugins/${pluginFileName}`
|
|
3864
|
-
]), { logger: (0, logging_1.createLogger)() });
|
|
3865
|
-
const file = program.setFile('source/MAIN.brs', '');
|
|
3866
|
-
(0, chai_config_spec_1.expect)(file._customProp).to.exist;
|
|
3867
|
-
});
|
|
3868
|
-
});
|
|
3869
|
-
describe('getDefinition', () => {
|
|
3870
|
-
it('returns const locations', () => {
|
|
3871
|
-
const file = program.setFile('source/main.bs', `
|
|
3872
|
-
sub main()
|
|
3873
|
-
print alpha.beta.charlie
|
|
3874
|
-
end sub
|
|
3875
|
-
namespace alpha.beta
|
|
3876
|
-
const CHARLIE = true
|
|
3877
|
-
end namespace
|
|
3878
|
-
`);
|
|
3879
|
-
program.validate();
|
|
3880
|
-
//print alpha.beta.char|lie
|
|
3881
|
-
(0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 41))).to.eql([{
|
|
3882
|
-
uri: vscode_uri_1.URI.file(file.srcPath).toString(),
|
|
3883
|
-
range: util_1.default.createRange(5, 26, 5, 33)
|
|
3884
|
-
}]);
|
|
3885
|
-
});
|
|
3886
|
-
it('returns enum locations', () => {
|
|
3887
|
-
const file = program.setFile('source/main.bs', `
|
|
3888
|
-
sub main()
|
|
3889
|
-
print alpha.beta.people.charlie
|
|
3890
|
-
end sub
|
|
3891
|
-
namespace alpha.beta
|
|
3892
|
-
enum people
|
|
3893
|
-
charlie = "charles"
|
|
3894
|
-
end enum
|
|
3895
|
-
end namespace
|
|
3896
|
-
`);
|
|
3897
|
-
program.validate();
|
|
3898
|
-
//print alpha.beta.char|lie
|
|
3899
|
-
(0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 40))).to.eql([{
|
|
3900
|
-
uri: vscode_uri_1.URI.file(file.srcPath).toString(),
|
|
3901
|
-
range: util_1.default.createRange(5, 25, 5, 31)
|
|
3902
|
-
}]);
|
|
3903
|
-
});
|
|
3904
|
-
it('does not crash on nulls', () => {
|
|
3905
|
-
const file = program.setFile('source/main.bs', `
|
|
3906
|
-
sub main()
|
|
3907
|
-
print alpha.beta
|
|
3908
|
-
end sub
|
|
3909
|
-
`);
|
|
3910
|
-
program.validate();
|
|
3911
|
-
sinon.stub(util_1.default, 'getAllDottedGetParts').returns(null);
|
|
3912
|
-
// print alpha.be|ta
|
|
3913
|
-
(0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 34))).to.eql([]);
|
|
3914
|
-
});
|
|
3915
|
-
it('returns enum member locations', () => {
|
|
3916
|
-
const file = program.setFile('source/main.bs', `
|
|
3917
|
-
sub main()
|
|
3918
|
-
print alpha.beta.people.charlie
|
|
3919
|
-
end sub
|
|
3920
|
-
namespace alpha.beta
|
|
3921
|
-
enum people
|
|
3922
|
-
charlie = "charles"
|
|
3923
|
-
end enum
|
|
3924
|
-
end namespace
|
|
3925
|
-
`);
|
|
3926
|
-
program.validate();
|
|
3927
|
-
//print alpha.beta.char|lie
|
|
3928
|
-
(0, chai_config_spec_1.expect)(program.getDefinition(file.srcPath, vscode_languageserver_1.Position.create(2, 48))).to.eql([{
|
|
3929
|
-
uri: vscode_uri_1.URI.file(file.srcPath).toString(),
|
|
3930
|
-
range: util_1.default.createRange(6, 24, 6, 31)
|
|
3931
|
-
}]);
|
|
3932
|
-
});
|
|
3933
|
-
});
|
|
3934
|
-
it('catches mismatched `end` keywords for functions', () => {
|
|
3935
|
-
program.setFile('source/main.brs', `
|
|
3936
|
-
function speak()
|
|
3937
|
-
end sub
|
|
3938
|
-
sub walk()
|
|
3939
|
-
end function
|
|
3940
|
-
`);
|
|
3941
|
-
program.validate();
|
|
3942
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword('function', 'sub')), { range: util_1.default.createRange(2, 12, 2, 19) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword('sub', 'function')), { range: util_1.default.createRange(4, 12, 4, 24) })]);
|
|
3943
|
-
});
|
|
3944
|
-
describe('backporting v1 syntax changes', () => {
|
|
3945
|
-
it('transpiles typed arrays to dynamic', () => {
|
|
3946
|
-
testTranspile(`
|
|
3947
|
-
sub main(param1 as string[], param2 as SomeType[])
|
|
3948
|
-
end sub
|
|
3949
|
-
`, `
|
|
3950
|
-
sub main(param1 as dynamic, param2 as dynamic)
|
|
3951
|
-
end sub
|
|
3952
|
-
`);
|
|
3953
|
-
});
|
|
3954
|
-
it('transpiles typed arrays in return types to dynamic', () => {
|
|
3955
|
-
testTranspile(`
|
|
3956
|
-
function main() as integer[]
|
|
3957
|
-
return []
|
|
3958
|
-
end function
|
|
3959
|
-
`, `
|
|
3960
|
-
function main() as dynamic
|
|
3961
|
-
return []
|
|
3962
|
-
end function
|
|
3963
|
-
`);
|
|
3964
|
-
});
|
|
3965
|
-
it('transpiles typed arrays in return types to dynamic', () => {
|
|
3966
|
-
testTranspile(`
|
|
3967
|
-
function main() as integer[]
|
|
3968
|
-
return []
|
|
3969
|
-
end function
|
|
3970
|
-
`, `
|
|
3971
|
-
function main() as dynamic
|
|
3972
|
-
return []
|
|
3973
|
-
end function
|
|
3974
|
-
`);
|
|
3975
|
-
});
|
|
3976
|
-
it('transpiles multi-dimension typed arrays to dynamic', () => {
|
|
3977
|
-
testTranspile(`
|
|
3978
|
-
sub main(param1 as float[][][])
|
|
3979
|
-
end sub
|
|
3980
|
-
`, `
|
|
3981
|
-
sub main(param1 as dynamic)
|
|
3982
|
-
end sub
|
|
3983
|
-
`);
|
|
3984
|
-
});
|
|
3985
|
-
it('removes typecasts in transpiled code', () => {
|
|
3986
|
-
testTranspile(`
|
|
3987
|
-
sub main(myNode, myString)
|
|
3988
|
-
print (myNode as roSGNode).id
|
|
3989
|
-
print (myNode as roSGNode).getParent().id
|
|
3990
|
-
myNode2 = myNode as roSgNode
|
|
3991
|
-
print (myString as string).len()
|
|
3992
|
-
print (myString as string).right(3)
|
|
3993
|
-
myString2 = myString as string
|
|
3994
|
-
end sub
|
|
3995
|
-
`, `
|
|
3996
|
-
sub main(myNode, myString)
|
|
3997
|
-
print myNode.id
|
|
3998
|
-
print myNode.getParent().id
|
|
3999
|
-
myNode2 = myNode
|
|
4000
|
-
print myString.len()
|
|
4001
|
-
print myString.right(3)
|
|
4002
|
-
myString2 = myString
|
|
4003
|
-
end sub
|
|
4004
|
-
`);
|
|
4005
|
-
});
|
|
4006
|
-
it('allows and removes multiple typecasts in transpiled code', () => {
|
|
4007
|
-
testTranspile(`
|
|
4008
|
-
sub main(myNode)
|
|
4009
|
-
print ((myNode as roSGNode as roSGNodeLabel).text as string as ifStringOps).len()
|
|
4010
|
-
end sub
|
|
4011
|
-
`, `
|
|
4012
|
-
sub main(myNode)
|
|
4013
|
-
print myNode.text.len()
|
|
4014
|
-
end sub
|
|
4015
|
-
`);
|
|
4016
|
-
});
|
|
4017
|
-
it('allows built in objects as type names', () => {
|
|
4018
|
-
testTranspile(`
|
|
4019
|
-
sub main(x as roSGNode, y as roSGNodeEvent, z as ifArray)
|
|
4020
|
-
end sub
|
|
4021
|
-
`, `
|
|
4022
|
-
sub main(x as object, y as object, z as object)
|
|
4023
|
-
end sub
|
|
4024
|
-
`);
|
|
4025
|
-
});
|
|
4026
|
-
it('allows component names as types names', () => {
|
|
4027
|
-
testTranspile(`
|
|
4028
|
-
sub main(x as roSGNodeGroup, y as roSGNodeRowList, z as roSGNodeCustomComponent)
|
|
4029
|
-
end sub
|
|
4030
|
-
`, `
|
|
4031
|
-
sub main(x as object, y as object, z as object)
|
|
4032
|
-
end sub
|
|
4033
|
-
`);
|
|
4034
|
-
});
|
|
4035
|
-
it('allows union types for primitives', () => {
|
|
4036
|
-
testTranspile(`
|
|
4037
|
-
sub main(x as string or float, y as object or float or string)
|
|
4038
|
-
end sub
|
|
4039
|
-
`, `
|
|
4040
|
-
sub main(x as dynamic, y as dynamic)
|
|
4041
|
-
end sub
|
|
4042
|
-
`);
|
|
4043
|
-
});
|
|
4044
|
-
it('allows union types for classes, interfaces', () => {
|
|
4045
|
-
testTranspile(`
|
|
4046
|
-
interface IFaceA
|
|
4047
|
-
name as string
|
|
4048
|
-
data as integer
|
|
4049
|
-
end interface
|
|
4050
|
-
|
|
4051
|
-
interface IFaceB
|
|
4052
|
-
name as string
|
|
4053
|
-
value as float
|
|
4054
|
-
end interface
|
|
4055
|
-
|
|
4056
|
-
sub main(x as IFaceA or IFaceB)
|
|
4057
|
-
end sub
|
|
4058
|
-
`, `
|
|
4059
|
-
sub main(x as dynamic)
|
|
4060
|
-
end sub
|
|
4061
|
-
`);
|
|
4062
|
-
});
|
|
4063
|
-
it('allows union types for classes, interfaces', () => {
|
|
4064
|
-
testTranspile(`
|
|
4065
|
-
namespace alpha.beta
|
|
4066
|
-
interface IFaceA
|
|
4067
|
-
name as string
|
|
4068
|
-
data as integer
|
|
4069
|
-
end interface
|
|
4070
|
-
|
|
4071
|
-
interface IFaceB
|
|
4072
|
-
name as string
|
|
4073
|
-
value as float
|
|
4074
|
-
end interface
|
|
4075
|
-
end namespace
|
|
4076
|
-
|
|
4077
|
-
sub main(x as alpha.beta.IFaceA or alpha.beta.IFaceB)
|
|
4078
|
-
end sub
|
|
4079
|
-
`, `
|
|
4080
|
-
sub main(x as dynamic)
|
|
4081
|
-
end sub
|
|
4082
|
-
`);
|
|
4083
|
-
});
|
|
4084
|
-
it('allows union types of arrays', () => {
|
|
4085
|
-
testTranspile(`
|
|
4086
|
-
namespace alpha.beta
|
|
4087
|
-
interface IFaceA
|
|
4088
|
-
name as string
|
|
4089
|
-
data as integer
|
|
4090
|
-
end interface
|
|
4091
|
-
|
|
4092
|
-
interface IFaceB
|
|
4093
|
-
name as string
|
|
4094
|
-
value as float
|
|
4095
|
-
end interface
|
|
4096
|
-
end namespace
|
|
4097
|
-
|
|
4098
|
-
sub main(x as alpha.beta.IFaceA[][] or alpha.beta.IFaceB[] or ifStringOps)
|
|
4099
|
-
end sub
|
|
4100
|
-
`, `
|
|
4101
|
-
sub main(x as dynamic)
|
|
4102
|
-
end sub
|
|
4103
|
-
`);
|
|
4104
|
-
});
|
|
4105
|
-
it('allows intersection types for primitives', () => {
|
|
4106
|
-
testTranspile(`
|
|
4107
|
-
sub main(x as string and float, y as object and float or string)
|
|
4108
|
-
end sub
|
|
4109
|
-
`, `
|
|
4110
|
-
sub main(x as dynamic, y as dynamic)
|
|
4111
|
-
end sub
|
|
4112
|
-
`);
|
|
4113
|
-
});
|
|
4114
|
-
it('allows intersection types for classes, interfaces', () => {
|
|
4115
|
-
testTranspile(`
|
|
4116
|
-
interface IFaceA
|
|
4117
|
-
name as string
|
|
4118
|
-
data as integer
|
|
4119
|
-
end interface
|
|
4120
|
-
|
|
4121
|
-
interface IFaceB
|
|
4122
|
-
name as string
|
|
4123
|
-
value as float
|
|
4124
|
-
end interface
|
|
4125
|
-
|
|
4126
|
-
sub main(x as IFaceA and IFaceB)
|
|
4127
|
-
end sub
|
|
4128
|
-
`, `
|
|
4129
|
-
sub main(x as dynamic)
|
|
4130
|
-
end sub
|
|
4131
|
-
`);
|
|
4132
|
-
});
|
|
4133
|
-
it('allows intersection types for classes, interfaces', () => {
|
|
4134
|
-
testTranspile(`
|
|
4135
|
-
namespace alpha.beta
|
|
4136
|
-
interface IFaceA
|
|
4137
|
-
name as string
|
|
4138
|
-
data as integer
|
|
4139
|
-
end interface
|
|
4140
|
-
|
|
4141
|
-
interface IFaceB
|
|
4142
|
-
name as string
|
|
4143
|
-
value as float
|
|
4144
|
-
end interface
|
|
4145
|
-
end namespace
|
|
4146
|
-
|
|
4147
|
-
sub main(x as alpha.beta.IFaceA and alpha.beta.IFaceB)
|
|
4148
|
-
end sub
|
|
4149
|
-
`, `
|
|
4150
|
-
sub main(x as dynamic)
|
|
4151
|
-
end sub
|
|
4152
|
-
`);
|
|
4153
|
-
});
|
|
4154
|
-
it('allows intersection types of arrays', () => {
|
|
4155
|
-
testTranspile(`
|
|
4156
|
-
namespace alpha.beta
|
|
4157
|
-
interface IFaceA
|
|
4158
|
-
name as string
|
|
4159
|
-
data as integer
|
|
4160
|
-
end interface
|
|
4161
|
-
|
|
4162
|
-
interface IFaceB
|
|
4163
|
-
name as string
|
|
4164
|
-
value as float
|
|
4165
|
-
end interface
|
|
4166
|
-
end namespace
|
|
4167
|
-
|
|
4168
|
-
sub main(x as alpha.beta.IFaceA[][] and alpha.beta.IFaceB[] and ifStringOps)
|
|
4169
|
-
end sub
|
|
4170
|
-
`, `
|
|
4171
|
-
sub main(x as dynamic)
|
|
4172
|
-
end sub
|
|
4173
|
-
`);
|
|
4174
|
-
});
|
|
4175
|
-
it('allows grouped expression in types types', () => {
|
|
4176
|
-
testTranspile(`
|
|
4177
|
-
namespace alpha.beta
|
|
4178
|
-
interface IFaceA
|
|
4179
|
-
name as string
|
|
4180
|
-
data as integer
|
|
4181
|
-
end interface
|
|
4182
|
-
|
|
4183
|
-
interface IFaceB
|
|
4184
|
-
name as string
|
|
4185
|
-
value as float
|
|
4186
|
-
end interface
|
|
4187
|
-
end namespace
|
|
4188
|
-
|
|
4189
|
-
sub main(x as (alpha.beta.IFace and alpha.beta.IFaceB)[] or ifStringOps)
|
|
4190
|
-
end sub
|
|
4191
|
-
`, `
|
|
4192
|
-
sub main(x as dynamic)
|
|
4193
|
-
end sub
|
|
4194
|
-
`);
|
|
4195
|
-
});
|
|
4196
|
-
it('allows built-in types for return values', () => {
|
|
4197
|
-
testTranspile(`
|
|
4198
|
-
function makeLabel(text as string) as roSGNodeLabel
|
|
4199
|
-
label = createObject("roSGNode", "Label")
|
|
4200
|
-
label.text = text
|
|
4201
|
-
end function
|
|
4202
|
-
`, `
|
|
4203
|
-
function makeLabel(text as string) as object
|
|
4204
|
-
label = createObject("roSGNode", "Label")
|
|
4205
|
-
label.text = text
|
|
4206
|
-
end function
|
|
4207
|
-
`);
|
|
4208
|
-
});
|
|
4209
|
-
it('allows built-in types for interface members', () => {
|
|
4210
|
-
program.setFile('source/main.bs', `
|
|
4211
|
-
interface MyBase
|
|
4212
|
-
regex as roRegex
|
|
4213
|
-
node as roSGNodeLabel
|
|
4214
|
-
sub outputMatches(textInput as string)
|
|
4215
|
-
function getLabelParent() as roSGNode
|
|
4216
|
-
end interface
|
|
4217
|
-
`);
|
|
4218
|
-
program.validate();
|
|
4219
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4220
|
-
});
|
|
4221
|
-
it('allows extends on interfaces', () => {
|
|
4222
|
-
testTranspile(`
|
|
4223
|
-
interface MyBase
|
|
4224
|
-
url as string
|
|
4225
|
-
end interface
|
|
4226
|
-
|
|
4227
|
-
interface MyExtends extends MyBase
|
|
4228
|
-
method as string
|
|
4229
|
-
end interface
|
|
4230
|
-
`, `
|
|
4231
|
-
`);
|
|
4232
|
-
});
|
|
4233
|
-
it('allows extends on classes', () => {
|
|
4234
|
-
program.setFile('source/main.bs', `
|
|
4235
|
-
class MyBase
|
|
4236
|
-
url as string
|
|
4237
|
-
end class
|
|
4238
|
-
|
|
4239
|
-
class MyExtends extends MyBase
|
|
4240
|
-
method as string
|
|
4241
|
-
end class
|
|
4242
|
-
`);
|
|
4243
|
-
program.validate();
|
|
4244
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4245
|
-
});
|
|
4246
|
-
it('allows built-in types for class members', () => {
|
|
4247
|
-
program.setFile('source/main.bs', `
|
|
4248
|
-
class MyBase
|
|
4249
|
-
regex as roRegex
|
|
4250
|
-
node as roSGNodeLabel
|
|
4251
|
-
|
|
4252
|
-
sub outputMatches(textInput as string)
|
|
4253
|
-
matches = m.regex.match(textInput)
|
|
4254
|
-
if matches.count() > 1
|
|
4255
|
-
m.node.text = matches[1]
|
|
4256
|
-
else
|
|
4257
|
-
m.node.text = "no match"
|
|
4258
|
-
end if
|
|
4259
|
-
end sub
|
|
4260
|
-
|
|
4261
|
-
function getLabelParent() as roSGNode
|
|
4262
|
-
return m.node.getParent()
|
|
4263
|
-
end function
|
|
4264
|
-
end class
|
|
4265
|
-
`);
|
|
4266
|
-
program.validate();
|
|
4267
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4268
|
-
});
|
|
4269
|
-
it('allows types on lhs of assignments', () => {
|
|
4270
|
-
testTranspile(`
|
|
4271
|
-
sub foo(node as roSGNode)
|
|
4272
|
-
nodeParent as roSGNode = node.getParent()
|
|
4273
|
-
text as string = nodeParent.id
|
|
4274
|
-
print text
|
|
4275
|
-
end sub
|
|
4276
|
-
`, `
|
|
4277
|
-
sub foo(node as object)
|
|
4278
|
-
nodeParent = node.getParent()
|
|
4279
|
-
text = nodeParent.id
|
|
4280
|
-
print text
|
|
4281
|
-
end sub
|
|
4282
|
-
`);
|
|
4283
|
-
});
|
|
4284
|
-
it('allows typecast statements', () => {
|
|
4285
|
-
testTranspile(`
|
|
4286
|
-
typecast m as whatever
|
|
4287
|
-
|
|
4288
|
-
sub foo(node as object)
|
|
4289
|
-
print node[m.keyProp]
|
|
4290
|
-
end sub
|
|
4291
|
-
`, `
|
|
4292
|
-
sub foo(node as object)
|
|
4293
|
-
print node[m.keyProp]
|
|
4294
|
-
end sub
|
|
4295
|
-
`);
|
|
4296
|
-
});
|
|
4297
|
-
describe('inline interfaces', () => {
|
|
4298
|
-
it('transpiles to "dynamic"', () => {
|
|
4299
|
-
testTranspile(`
|
|
4300
|
-
function foo(input as {name as string}) as {id as string}
|
|
4301
|
-
output as {id as string} = {id: input.name}
|
|
4302
|
-
return output
|
|
4303
|
-
end function
|
|
4304
|
-
`, `
|
|
4305
|
-
function foo(input as dynamic) as dynamic
|
|
4306
|
-
output = {
|
|
4307
|
-
id: input.name
|
|
4308
|
-
}
|
|
4309
|
-
return output
|
|
4310
|
-
end function
|
|
4311
|
-
`);
|
|
4312
|
-
});
|
|
4313
|
-
});
|
|
4314
|
-
describe('type statements interfaces', () => {
|
|
4315
|
-
it('transpiles statement to nothing', () => {
|
|
4316
|
-
testTranspile(`
|
|
4317
|
-
type number = integer or float
|
|
4318
|
-
|
|
4319
|
-
sub foo()
|
|
4320
|
-
print "hello"
|
|
4321
|
-
end sub
|
|
4322
|
-
`, `
|
|
4323
|
-
sub foo()
|
|
4324
|
-
print "hello"
|
|
4325
|
-
end sub
|
|
4326
|
-
`);
|
|
4327
|
-
});
|
|
4328
|
-
it('transpiles type statement to object', () => {
|
|
4329
|
-
testTranspile(`
|
|
4330
|
-
type number = integer or float
|
|
4331
|
-
|
|
4332
|
-
sub foo(node as number)
|
|
4333
|
-
print node[m.keyProp]
|
|
4334
|
-
end sub
|
|
4335
|
-
`, `
|
|
4336
|
-
sub foo(node as object)
|
|
4337
|
-
print node[m.keyProp]
|
|
4338
|
-
end sub
|
|
4339
|
-
`);
|
|
4340
|
-
});
|
|
4341
|
-
});
|
|
4342
|
-
describe('for each loop with types', () => {
|
|
4343
|
-
it('transpiles to untyped for each', () => {
|
|
4344
|
-
testTranspile(`
|
|
4345
|
-
sub foo(items as string[])
|
|
4346
|
-
for each item as string in items
|
|
4347
|
-
print item
|
|
4348
|
-
end for
|
|
4349
|
-
end sub
|
|
4350
|
-
`, `
|
|
4351
|
-
sub foo(items as dynamic)
|
|
4352
|
-
for each item in items
|
|
4353
|
-
print item
|
|
4354
|
-
end for
|
|
4355
|
-
end sub
|
|
4356
|
-
`);
|
|
4357
|
-
});
|
|
4358
|
-
});
|
|
4359
|
-
describe('typed functions in type expressions', () => {
|
|
4360
|
-
it('transpiles to function', () => {
|
|
4361
|
-
testTranspile(`
|
|
4362
|
-
function test(func as function(name as string, num as integer) as integer) as integer
|
|
4363
|
-
return func("hello", 123)
|
|
4364
|
-
end function
|
|
4365
|
-
`, `
|
|
4366
|
-
function test(func as Function) as integer
|
|
4367
|
-
return func("hello", 123)
|
|
4368
|
-
end function
|
|
4369
|
-
`);
|
|
4370
|
-
});
|
|
4371
|
-
});
|
|
4372
|
-
});
|
|
4373
|
-
it('allows up to 63 function params', () => {
|
|
4374
|
-
program.setFile('source/main.bs', `
|
|
4375
|
-
function test(p1 = 1, p2 = 2, p3 = 3, p4 = 4, p5 = 5, p6 = 6, p7 = 7, p8 = 8, p9 = 9, p10 = 10, p11 = 11, p12 = 12, p13 = 13, p14 = 14, p15 = 15, p16 = 16, p17 = 17, p18 = 18, p19 = 19, p20 = 20, p21 = 21, p22 = 22, p23 = 23, p24 = 24, p25 = 25, p26 = 26, p27 = 27, p28 = 28, p29 = 29, p30 = 30, p31 = 31, p32 = 32, p33 = 33, p34 = 34, p35 = 35, p36 = 36, p37 = 37, p38 = 38, p39 = 39, p40 = 40, p41 = 41, p42 = 42, p43 = 43, p44 = 44, p45 = 45, p46 = 46, p47 = 47, p48 = 48, p49 = 49, p50 = 50, p51 = 51, p52 = 52, p53 = 53, p54 = 54, p55 = 55, p56 = 56, p57 = 57, p58 = 58, p59 = 59, p60 = 60, p61 = 61, p62 = 62, p63 = 63)
|
|
4376
|
-
end function
|
|
4377
|
-
`);
|
|
4378
|
-
program.validate();
|
|
4379
|
-
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
4380
|
-
});
|
|
4381
|
-
it('flags functions having 64 parameters', () => {
|
|
4382
|
-
program.setFile('source/main.bs', `
|
|
4383
|
-
function test(p1 = 1, p2 = 2, p3 = 3, p4 = 4, p5 = 5, p6 = 6, p7 = 7, p8 = 8, p9 = 9, p10 = 10, p11 = 11, p12 = 12, p13 = 13, p14 = 14, p15 = 15, p16 = 16, p17 = 17, p18 = 18, p19 = 19, p20 = 20, p21 = 21, p22 = 22, p23 = 23, p24 = 24, p25 = 25, p26 = 26, p27 = 27, p28 = 28, p29 = 29, p30 = 30, p31 = 31, p32 = 32, p33 = 33, p34 = 34, p35 = 35, p36 = 36, p37 = 37, p38 = 38, p39 = 39, p40 = 40, p41 = 41, p42 = 42, p43 = 43, p44 = 44, p45 = 45, p46 = 46, p47 = 47, p48 = 48, p49 = 49, p50 = 50, p51 = 51, p52 = 52, p53 = 53, p54 = 54, p55 = 55, p56 = 56, p57 = 57, p58 = 58, p59 = 59, p60 = 60, p61 = 61, p62 = 62, p63 = 63, p64 = 64)
|
|
4384
|
-
end function
|
|
4385
|
-
`);
|
|
4386
|
-
program.validate();
|
|
4387
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(64, 63)), { range: util_1.default.createRange(1, 638, 1, 641) })]);
|
|
4388
|
-
});
|
|
4389
|
-
it('flags functions having 65 parameters', () => {
|
|
4390
|
-
program.setFile('source/main.bs', `
|
|
4391
|
-
function test(p1 = 1, p2 = 2, p3 = 3, p4 = 4, p5 = 5, p6 = 6, p7 = 7, p8 = 8, p9 = 9, p10 = 10, p11 = 11, p12 = 12, p13 = 13, p14 = 14, p15 = 15, p16 = 16, p17 = 17, p18 = 18, p19 = 19, p20 = 20, p21 = 21, p22 = 22, p23 = 23, p24 = 24, p25 = 25, p26 = 26, p27 = 27, p28 = 28, p29 = 29, p30 = 30, p31 = 31, p32 = 32, p33 = 33, p34 = 34, p35 = 35, p36 = 36, p37 = 37, p38 = 38, p39 = 39, p40 = 40, p41 = 41, p42 = 42, p43 = 43, p44 = 44, p45 = 45, p46 = 46, p47 = 47, p48 = 48, p49 = 49, p50 = 50, p51 = 51, p52 = 52, p53 = 53, p54 = 54, p55 = 55, p56 = 56, p57 = 57, p58 = 58, p59 = 59, p60 = 60, p61 = 61, p62 = 62, p63 = 63, p64 = 64, p65 = 65)
|
|
4392
|
-
end function
|
|
4393
|
-
`);
|
|
4394
|
-
program.validate();
|
|
4395
|
-
(0, testHelpers_spec_1.expectDiagnostics)(program, [Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(65, 63)), { range: util_1.default.createRange(1, 638, 1, 641) }), Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(65, 63)), { range: util_1.default.createRange(1, 648, 1, 651) })]);
|
|
4396
|
-
});
|
|
4397
|
-
describe('getClosestExpression', () => {
|
|
4398
|
-
it('returns undefined for missing Position', () => {
|
|
4399
|
-
const file = program.setFile('source/main.bs', `
|
|
4400
|
-
sub Main()
|
|
4401
|
-
if true THEN
|
|
4402
|
-
print "works"
|
|
4403
|
-
end if
|
|
4404
|
-
end sub
|
|
4405
|
-
`);
|
|
4406
|
-
(0, chai_config_spec_1.expect)(file.getClosestExpression(undefined)).to.be.undefined;
|
|
4407
|
-
});
|
|
4408
|
-
it('returns the closest expression at Position', () => {
|
|
4409
|
-
const file = program.setFile('source/main.bs', `
|
|
4410
|
-
sub Main()
|
|
4411
|
-
if true THEN
|
|
4412
|
-
print "works"
|
|
4413
|
-
end if
|
|
4414
|
-
end sub
|
|
4415
|
-
`);
|
|
4416
|
-
(0, chai_config_spec_1.expect)(file.getClosestExpression({ line: 3, character: 34 })).to.be.instanceOf(Expression_1.LiteralExpression);
|
|
4417
|
-
});
|
|
4418
|
-
});
|
|
4419
|
-
});
|
|
4420
|
-
//# sourceMappingURL=BrsFile.spec.js.map
|