brighterscript 1.0.0-alpha.2 → 1.0.0-alpha.20
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/CHANGELOG.md +542 -253
- package/README.md +30 -9
- package/bsconfig.schema.json +13 -1
- package/dist/BsConfig.d.ts +4 -0
- package/dist/Cache.d.ts +3 -8
- package/dist/Cache.js +9 -14
- package/dist/Cache.js.map +1 -1
- package/dist/CodeActionUtil.d.ts +11 -2
- package/dist/CodeActionUtil.js +17 -3
- package/dist/CodeActionUtil.js.map +1 -1
- package/dist/CommentFlagProcessor.d.ts +4 -4
- package/dist/CommentFlagProcessor.js +5 -3
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DependencyGraph.js +5 -4
- package/dist/DependencyGraph.js.map +1 -1
- package/dist/DiagnosticFilterer.js +1 -1
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +59 -4
- package/dist/DiagnosticMessages.js +65 -7
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/LanguageServer.d.ts +4 -14
- package/dist/LanguageServer.js +40 -26
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +2 -0
- package/dist/Logger.js +10 -8
- package/dist/Logger.js.map +1 -1
- package/dist/PluginInterface.d.ts +7 -3
- package/dist/PluginInterface.js +9 -0
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +43 -25
- package/dist/Program.js +180 -82
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +4 -0
- package/dist/ProgramBuilder.js +30 -14
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +100 -28
- package/dist/Scope.js +382 -154
- package/dist/Scope.js.map +1 -1
- package/dist/SemanticTokenUtils.d.ts +14 -0
- package/dist/SemanticTokenUtils.js +81 -0
- package/dist/SemanticTokenUtils.js.map +1 -0
- package/dist/SymbolTable.d.ts +10 -4
- package/dist/SymbolTable.js +40 -13
- package/dist/SymbolTable.js.map +1 -1
- package/dist/XmlScope.d.ts +8 -3
- package/dist/XmlScope.js +65 -27
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/AstEditor.d.ts +33 -0
- package/dist/astUtils/AstEditor.js +107 -0
- package/dist/astUtils/AstEditor.js.map +1 -0
- package/dist/{types/FunctionType.spec.d.ts → astUtils/AstEditor.spec.d.ts} +0 -0
- package/dist/astUtils/AstEditor.spec.js +170 -0
- package/dist/astUtils/AstEditor.spec.js.map +1 -0
- package/dist/astUtils/creators.d.ts +24 -6
- package/dist/astUtils/creators.js +130 -19
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/creators.spec.js +14 -4
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +27 -8
- package/dist/astUtils/reflection.js +66 -1
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +130 -119
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/stackedVisitor.js.map +1 -1
- package/dist/astUtils/stackedVisitor.spec.js +13 -13
- package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +17 -2
- package/dist/astUtils/visitors.js +2 -2
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +31 -29
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/astUtils/xml.d.ts +4 -3
- package/dist/astUtils/xml.js +8 -3
- package/dist/astUtils/xml.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +7 -1
- package/dist/bscPlugin/BscPlugin.js +28 -0
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +4 -4
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +26 -26
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +9 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +97 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +73 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +8 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +52 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +32 -0
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +9 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js +66 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +29 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +183 -0
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
- package/dist/cli.js +9 -3
- package/dist/cli.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +1 -0
- package/dist/diagnosticUtils.js +15 -8
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +12 -14
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/BrsFile.Class.spec.js +634 -145
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +62 -30
- package/dist/files/BrsFile.js +683 -335
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1055 -449
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/XmlFile.d.ts +11 -10
- package/dist/files/XmlFile.js +33 -26
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +302 -237
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +44 -42
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
- package/dist/files/tests/optionalChaning.spec.js +88 -0
- package/dist/files/tests/optionalChaning.spec.js.map +1 -0
- package/dist/globalCallables.d.ts +3 -1
- package/dist/globalCallables.js +424 -152
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +13 -3
- package/dist/index.js +23 -4
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +129 -16
- package/dist/lexer/Lexer.d.ts +19 -1
- package/dist/lexer/Lexer.js +127 -21
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +657 -536
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/Token.d.ts +2 -2
- package/dist/lexer/TokenKind.d.ts +13 -1
- package/dist/lexer/TokenKind.js +60 -3
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/BrsTranspileState.d.ts +7 -0
- package/dist/parser/BrsTranspileState.js +9 -0
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +150 -34
- package/dist/parser/Expression.js +337 -150
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +189 -89
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +152 -29
- package/dist/parser/Parser.js +1095 -501
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.js +687 -266
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +41 -4
- package/dist/parser/SGParser.js +186 -175
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +35 -22
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +206 -38
- package/dist/parser/SGTypes.js +470 -161
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/SGTypes.spec.d.ts +1 -0
- package/dist/parser/SGTypes.spec.js +351 -0
- package/dist/parser/SGTypes.spec.js.map +1 -0
- package/dist/parser/Statement.d.ts +194 -40
- package/dist/parser/Statement.js +597 -160
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +11 -11
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/TranspileState.d.ts +1 -1
- package/dist/parser/TranspileState.js +15 -7
- package/dist/parser/TranspileState.js.map +1 -1
- package/dist/parser/tests/Parser.spec.d.ts +10 -9
- package/dist/parser/tests/Parser.spec.js +15 -11
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +60 -60
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +40 -39
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +213 -194
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +37 -37
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +30 -30
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +119 -119
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +162 -138
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +24 -24
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +41 -40
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +17 -17
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +256 -256
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +87 -87
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +37 -37
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +75 -63
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +41 -41
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +41 -41
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
- package/dist/parser/tests/expression/Relational.spec.js +43 -43
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +9 -9
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +28 -28
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +102 -102
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +36 -36
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/Declaration.spec.js +44 -44
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Dim.spec.js +21 -21
- package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Enum.spec.js +840 -0
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
- package/dist/parser/tests/statement/For.spec.d.ts +1 -0
- package/dist/parser/tests/statement/For.spec.js +46 -0
- package/dist/parser/tests/statement/For.spec.js.map +1 -0
- package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
- package/dist/parser/tests/statement/ForEach.spec.js +37 -0
- package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
- package/dist/parser/tests/statement/Function.spec.js +198 -197
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +15 -14
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +50 -50
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +254 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/LibraryStatement.spec.js +17 -17
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +108 -106
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +40 -40
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +46 -46
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +83 -83
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +12 -11
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/parser/tests/statement/Throw.spec.js +5 -5
- package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +15 -13
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/preprocessor/Chunk.d.ts +1 -1
- package/dist/preprocessor/Chunk.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +5 -5
- package/dist/preprocessor/Manifest.js +14 -35
- package/dist/preprocessor/Manifest.js.map +1 -1
- package/dist/preprocessor/Manifest.spec.d.ts +1 -0
- package/dist/preprocessor/Manifest.spec.js +78 -103
- package/dist/preprocessor/Manifest.spec.js.map +1 -1
- package/dist/preprocessor/Preprocessor.d.ts +1 -1
- package/dist/preprocessor/Preprocessor.js +8 -8
- package/dist/preprocessor/Preprocessor.js.map +1 -1
- package/dist/preprocessor/Preprocessor.spec.js +49 -49
- package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
- package/dist/preprocessor/PreprocessorParser.spec.js +72 -72
- package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
- package/dist/roku-types/data.json +21891 -0
- package/dist/roku-types/index.d.ts +6776 -0
- package/dist/roku-types/index.js +11 -0
- package/dist/roku-types/index.js.map +1 -0
- package/dist/types/ArrayType.d.ts +8 -5
- package/dist/types/ArrayType.js +52 -12
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +72 -11
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/BooleanType.d.ts +4 -2
- package/dist/types/BooleanType.js +9 -4
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BooleanType.spec.js +5 -3
- package/dist/types/BooleanType.spec.js.map +1 -1
- package/dist/types/BscType.d.ts +20 -5
- package/dist/types/BscType.js +24 -0
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/CustomType.d.ts +8 -6
- package/dist/types/CustomType.js +20 -11
- package/dist/types/CustomType.js.map +1 -1
- package/dist/types/DoubleType.d.ts +2 -0
- package/dist/types/DoubleType.js +14 -9
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DoubleType.spec.js +5 -3
- package/dist/types/DoubleType.spec.js.map +1 -1
- package/dist/types/DynamicType.d.ts +2 -0
- package/dist/types/DynamicType.js +6 -2
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/DynamicType.spec.js +2 -2
- package/dist/types/DynamicType.spec.js.map +1 -1
- package/dist/types/FloatType.d.ts +2 -0
- package/dist/types/FloatType.js +14 -9
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +4 -2
- package/dist/types/FloatType.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +7 -31
- package/dist/types/FunctionType.js +11 -57
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/IntegerType.d.ts +2 -0
- package/dist/types/IntegerType.js +14 -9
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/IntegerType.spec.js +5 -3
- package/dist/types/IntegerType.spec.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +13 -4
- package/dist/types/InterfaceType.js +48 -8
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.d.ts +1 -0
- package/dist/types/InterfaceType.spec.js +194 -0
- package/dist/types/InterfaceType.spec.js.map +1 -0
- package/dist/types/InvalidType.d.ts +4 -2
- package/dist/types/InvalidType.js +10 -5
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/InvalidType.spec.js +4 -2
- package/dist/types/InvalidType.spec.js.map +1 -1
- package/dist/types/LazyType.d.ts +8 -7
- package/dist/types/LazyType.js +22 -10
- package/dist/types/LazyType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +2 -0
- package/dist/types/LongIntegerType.js +14 -9
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/LongIntegerType.spec.js +4 -2
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/ObjectType.d.ts +8 -4
- package/dist/types/ObjectType.js +9 -4
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ObjectType.spec.js +2 -2
- package/dist/types/ObjectType.spec.js.map +1 -1
- package/dist/types/StringType.d.ts +4 -2
- package/dist/types/StringType.js +9 -4
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/StringType.spec.js +4 -2
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +28 -0
- package/dist/types/TypedFunctionType.js +88 -0
- package/dist/types/TypedFunctionType.js.map +1 -0
- package/dist/types/TypedFunctionType.spec.d.ts +1 -0
- package/dist/types/TypedFunctionType.spec.js +37 -0
- package/dist/types/TypedFunctionType.spec.js.map +1 -0
- package/dist/types/UninitializedType.js +3 -3
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/VoidType.d.ts +4 -2
- package/dist/types/VoidType.js +8 -4
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/VoidType.spec.js +2 -2
- package/dist/types/VoidType.spec.js.map +1 -1
- package/dist/types/helpers.d.ts +42 -0
- package/dist/types/helpers.js +118 -0
- package/dist/types/helpers.js.map +1 -0
- package/dist/util.d.ts +87 -16
- package/dist/util.js +339 -94
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +19 -2
- package/dist/validators/ClassValidator.js +163 -102
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +26 -15
- package/dist/astUtils/index.d.ts +0 -7
- package/dist/astUtils/index.js +0 -26
- package/dist/astUtils/index.js.map +0 -1
- package/dist/lexer/index.d.ts +0 -3
- package/dist/lexer/index.js +0 -17
- package/dist/lexer/index.js.map +0 -1
- package/dist/parser/index.d.ts +0 -3
- package/dist/parser/index.js +0 -16
- package/dist/parser/index.js.map +0 -1
- package/dist/preprocessor/index.d.ts +0 -3
- package/dist/preprocessor/index.js +0 -16
- package/dist/preprocessor/index.js.map +0 -1
- package/dist/types/FunctionType.spec.js +0 -23
- package/dist/types/FunctionType.spec.js.map +0 -1
|
@@ -2,33 +2,41 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const chai_1 = require("chai");
|
|
4
4
|
const sinonImport = require("sinon");
|
|
5
|
-
const path = require("path");
|
|
6
5
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
7
6
|
const Program_1 = require("../Program");
|
|
8
7
|
const BooleanType_1 = require("../types/BooleanType");
|
|
9
8
|
const DynamicType_1 = require("../types/DynamicType");
|
|
10
|
-
const
|
|
9
|
+
const TypedFunctionType_1 = require("../types/TypedFunctionType");
|
|
11
10
|
const IntegerType_1 = require("../types/IntegerType");
|
|
12
11
|
const StringType_1 = require("../types/StringType");
|
|
13
12
|
const BrsFile_1 = require("./BrsFile");
|
|
14
13
|
const source_map_1 = require("source-map");
|
|
15
|
-
const
|
|
14
|
+
const Lexer_1 = require("../lexer/Lexer");
|
|
15
|
+
const TokenKind_1 = require("../lexer/TokenKind");
|
|
16
16
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
17
17
|
const util_1 = require("../util");
|
|
18
18
|
const PluginInterface_1 = require("../PluginInterface");
|
|
19
19
|
const testHelpers_spec_1 = require("../testHelpers.spec");
|
|
20
20
|
const Parser_1 = require("../parser/Parser");
|
|
21
21
|
const Logger_1 = require("../Logger");
|
|
22
|
+
const Statement_1 = require("../parser/Statement");
|
|
23
|
+
const creators_1 = require("../astUtils/creators");
|
|
24
|
+
const fsExtra = require("fs-extra");
|
|
25
|
+
const ArrayType_1 = require("../types/ArrayType");
|
|
26
|
+
const FloatType_1 = require("../types/FloatType");
|
|
27
|
+
const ObjectType_1 = require("../types/ObjectType");
|
|
22
28
|
const VoidType_1 = require("../types/VoidType");
|
|
23
29
|
let sinon = sinonImport.createSandbox();
|
|
24
30
|
describe('BrsFile', () => {
|
|
25
|
-
let
|
|
31
|
+
let tempDir = (0, util_1.standardizePath) `${process.cwd()}/.tmp`;
|
|
32
|
+
let rootDir = (0, util_1.standardizePath) `${tempDir}/rootDir`;
|
|
26
33
|
let program;
|
|
27
|
-
let srcPath = util_1.standardizePath `${rootDir}/source/main.brs`;
|
|
34
|
+
let srcPath = (0, util_1.standardizePath) `${rootDir}/source/main.brs`;
|
|
28
35
|
let destPath = 'source/main.brs';
|
|
29
36
|
let file;
|
|
30
|
-
let testTranspile = testHelpers_spec_1.getTestTranspile(() => [program, rootDir]);
|
|
37
|
+
let testTranspile = (0, testHelpers_spec_1.getTestTranspile)(() => [program, rootDir]);
|
|
31
38
|
beforeEach(() => {
|
|
39
|
+
fsExtra.emptyDirSync(tempDir);
|
|
32
40
|
program = new Program_1.Program({ rootDir: rootDir, sourceMap: true });
|
|
33
41
|
file = new BrsFile_1.BrsFile(srcPath, destPath, program);
|
|
34
42
|
});
|
|
@@ -37,20 +45,36 @@ describe('BrsFile', () => {
|
|
|
37
45
|
program.dispose();
|
|
38
46
|
});
|
|
39
47
|
it('supports the third parameter in CreateObject', () => {
|
|
40
|
-
|
|
41
|
-
program.addOrReplaceFile('source/main.brs', `
|
|
48
|
+
program.setFile('source/main.brs', `
|
|
42
49
|
sub main()
|
|
43
50
|
regexp = CreateObject("roRegex", "[a-z]+", "i")
|
|
44
51
|
end sub
|
|
45
52
|
`);
|
|
46
53
|
program.validate();
|
|
47
|
-
|
|
54
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
55
|
+
});
|
|
56
|
+
it('supports the 6 params in CreateObject for roRegion', () => {
|
|
57
|
+
program.setFile('source/main.brs', `
|
|
58
|
+
sub createRegion(bitmap as object)
|
|
59
|
+
region = CreateObject("roRegion", bitmap, 20, 40, 100, 200)
|
|
60
|
+
end sub
|
|
61
|
+
`);
|
|
62
|
+
program.validate();
|
|
63
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
48
64
|
});
|
|
49
65
|
it('sets needsTranspiled to true for .bs files', () => {
|
|
50
66
|
//BrightScript
|
|
51
|
-
chai_1.expect(new BrsFile_1.BrsFile(`${rootDir}/source/main.brs`, 'source/main.brs', program).needsTranspiled).to.be.false;
|
|
67
|
+
(0, chai_1.expect)(new BrsFile_1.BrsFile(`${rootDir}/source/main.brs`, 'source/main.brs', program).needsTranspiled).to.be.false;
|
|
52
68
|
//BrighterScript
|
|
53
|
-
chai_1.expect(new BrsFile_1.BrsFile(`${rootDir}/source/main.bs`, 'source/main.bs', program).needsTranspiled).to.be.true;
|
|
69
|
+
(0, chai_1.expect)(new BrsFile_1.BrsFile(`${rootDir}/source/main.bs`, 'source/main.bs', program).needsTranspiled).to.be.true;
|
|
70
|
+
});
|
|
71
|
+
it('computes new import statements after clearing parser references', () => {
|
|
72
|
+
const file = program.setFile('source/main.bs', ``);
|
|
73
|
+
(0, chai_1.expect)(file.ownScriptImports).to.be.empty;
|
|
74
|
+
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')));
|
|
75
|
+
(0, chai_1.expect)(file.ownScriptImports).to.be.empty;
|
|
76
|
+
file.parser.invalidateReferences();
|
|
77
|
+
(0, chai_1.expect)(file.ownScriptImports.map(x => x.text)).to.eql(['pkg:/source/lib.brs']);
|
|
54
78
|
});
|
|
55
79
|
it('allows adding diagnostics', () => {
|
|
56
80
|
const expected = [{
|
|
@@ -59,8 +83,7 @@ describe('BrsFile', () => {
|
|
|
59
83
|
range: undefined
|
|
60
84
|
}];
|
|
61
85
|
file.addDiagnostics(expected);
|
|
62
|
-
|
|
63
|
-
chai_1.expect(actual).deep.equal(expected);
|
|
86
|
+
(0, testHelpers_spec_1.expectDiagnostics)(file, expected);
|
|
64
87
|
});
|
|
65
88
|
describe('getPartialVariableName', () => {
|
|
66
89
|
let entry = {
|
|
@@ -68,72 +91,72 @@ describe('BrsFile', () => {
|
|
|
68
91
|
dest: `source/lib.brs`
|
|
69
92
|
};
|
|
70
93
|
it('creates proper tokens', () => {
|
|
71
|
-
file = program.
|
|
72
|
-
chai_1.expect(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
|
|
73
|
-
chai_1.expect(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
|
|
74
|
-
chai_1.expect(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
|
|
75
|
-
chai_1.expect(file['getPartialVariableName'](file.parser.tokens[4])).to.equal('ModuleA.ModuleB');
|
|
76
|
-
chai_1.expect(file['getPartialVariableName'](file.parser.tokens[3])).to.equal('ModuleA.');
|
|
77
|
-
chai_1.expect(file['getPartialVariableName'](file.parser.tokens[2])).to.equal('ModuleA');
|
|
94
|
+
file = program.setFile(entry, `call(ModuleA.ModuleB.ModuleC.`);
|
|
95
|
+
(0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[7])).to.equal('ModuleA.ModuleB.ModuleC.');
|
|
96
|
+
(0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[6])).to.equal('ModuleA.ModuleB.ModuleC');
|
|
97
|
+
(0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[5])).to.equal('ModuleA.ModuleB.');
|
|
98
|
+
(0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[4])).to.equal('ModuleA.ModuleB');
|
|
99
|
+
(0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[3])).to.equal('ModuleA.');
|
|
100
|
+
(0, chai_1.expect)(file['getPartialVariableName'](file.parser.tokens[2])).to.equal('ModuleA');
|
|
78
101
|
});
|
|
79
102
|
});
|
|
80
103
|
describe('getScopesForFile', () => {
|
|
81
104
|
it('finds the scope for the file', () => {
|
|
82
105
|
var _a;
|
|
83
|
-
let file = program.
|
|
84
|
-
chai_1.expect((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
|
|
106
|
+
let file = program.setFile('source/main.brs', ``);
|
|
107
|
+
(0, chai_1.expect)((_a = program.getScopesForFile(file)[0]) === null || _a === void 0 ? void 0 : _a.name).to.equal('source');
|
|
85
108
|
});
|
|
86
109
|
});
|
|
87
110
|
describe('getCompletions', () => {
|
|
88
111
|
it('does not crash for callfunc on a function call', () => {
|
|
89
|
-
const file = program.
|
|
112
|
+
const file = program.setFile('source/main.brs', `
|
|
90
113
|
sub main()
|
|
91
114
|
getManager()@.
|
|
92
115
|
end sub
|
|
93
116
|
`);
|
|
94
|
-
chai_1.expect(() => {
|
|
117
|
+
(0, chai_1.expect)(() => {
|
|
95
118
|
program.getCompletions(file.srcPath, util_1.default.createPosition(2, 34));
|
|
96
119
|
}).not.to.throw;
|
|
97
120
|
});
|
|
98
121
|
it('suggests pkg paths in strings that match that criteria', () => {
|
|
99
|
-
program.
|
|
122
|
+
program.setFile('source/main.brs', `
|
|
100
123
|
sub main()
|
|
101
124
|
print "pkg:"
|
|
102
125
|
end sub
|
|
103
126
|
`);
|
|
104
127
|
const result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
|
|
105
128
|
const names = result.map(x => x.label);
|
|
106
|
-
chai_1.expect(names.sort()).to.eql([
|
|
129
|
+
(0, chai_1.expect)(names.sort()).to.eql([
|
|
107
130
|
'pkg:/source/main.brs'
|
|
108
131
|
]);
|
|
109
132
|
});
|
|
110
133
|
it('suggests libpkg paths in strings that match that criteria', () => {
|
|
111
|
-
program.
|
|
134
|
+
program.setFile('source/main.brs', `
|
|
112
135
|
sub main()
|
|
113
136
|
print "libpkg:"
|
|
114
137
|
end sub
|
|
115
138
|
`);
|
|
116
139
|
const result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
|
|
117
140
|
const names = result.map(x => x.label);
|
|
118
|
-
chai_1.expect(names.sort()).to.eql([
|
|
141
|
+
(0, chai_1.expect)(names.sort()).to.eql([
|
|
119
142
|
'libpkg:/source/main.brs'
|
|
120
143
|
]);
|
|
121
144
|
});
|
|
122
145
|
it('suggests pkg paths in template strings', () => {
|
|
123
|
-
program.
|
|
146
|
+
program.setFile('source/main.brs', `
|
|
124
147
|
sub main()
|
|
125
148
|
print \`pkg:\`
|
|
126
149
|
end sub
|
|
127
150
|
`);
|
|
128
151
|
const result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 31));
|
|
129
152
|
const names = result.map(x => x.label);
|
|
130
|
-
chai_1.expect(names.sort()).to.eql([
|
|
153
|
+
(0, chai_1.expect)(names.sort()).to.eql([
|
|
131
154
|
'pkg:/source/main.brs'
|
|
132
155
|
]);
|
|
133
156
|
});
|
|
134
157
|
it('waits for the file to be processed before collecting completions', () => {
|
|
135
158
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
136
|
-
program.
|
|
159
|
+
program.setFile('source/main.brs', `
|
|
137
160
|
sub Main()
|
|
138
161
|
print "hello"
|
|
139
162
|
Say
|
|
@@ -144,62 +167,132 @@ describe('BrsFile', () => {
|
|
|
144
167
|
`);
|
|
145
168
|
let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 23));
|
|
146
169
|
let names = result.map(x => x.label);
|
|
147
|
-
chai_1.expect(names).to.includes('Main');
|
|
148
|
-
chai_1.expect(names).to.includes('SayHello');
|
|
170
|
+
(0, chai_1.expect)(names).to.includes('Main');
|
|
171
|
+
(0, chai_1.expect)(names).to.includes('SayHello');
|
|
172
|
+
});
|
|
173
|
+
it('includes every type of item at base level', () => {
|
|
174
|
+
program.setFile('source/main.bs', `
|
|
175
|
+
sub main()
|
|
176
|
+
print
|
|
177
|
+
end sub
|
|
178
|
+
sub speak()
|
|
179
|
+
end sub
|
|
180
|
+
namespace stuff
|
|
181
|
+
end namespace
|
|
182
|
+
class Person
|
|
183
|
+
end class
|
|
184
|
+
enum Direction
|
|
185
|
+
end enum
|
|
186
|
+
`);
|
|
187
|
+
(0, testHelpers_spec_1.expectCompletionsIncludes)(program.getCompletions('source/main.bs', util_1.default.createPosition(2, 26)), [{
|
|
188
|
+
label: 'main',
|
|
189
|
+
kind: vscode_languageserver_1.CompletionItemKind.Function
|
|
190
|
+
}, {
|
|
191
|
+
label: 'speak',
|
|
192
|
+
kind: vscode_languageserver_1.CompletionItemKind.Function
|
|
193
|
+
}, {
|
|
194
|
+
label: 'stuff',
|
|
195
|
+
kind: vscode_languageserver_1.CompletionItemKind.Module
|
|
196
|
+
}, {
|
|
197
|
+
label: 'Person',
|
|
198
|
+
kind: vscode_languageserver_1.CompletionItemKind.Class
|
|
199
|
+
}, {
|
|
200
|
+
label: 'Direction',
|
|
201
|
+
kind: vscode_languageserver_1.CompletionItemKind.Enum
|
|
202
|
+
}]);
|
|
203
|
+
});
|
|
204
|
+
describe('namespaces', () => {
|
|
205
|
+
it('gets full namespace completions at any point through the leading identifier', () => {
|
|
206
|
+
program.setFile('source/main.bs', `
|
|
207
|
+
sub main()
|
|
208
|
+
foo.bar
|
|
209
|
+
end sub
|
|
210
|
+
|
|
211
|
+
namespace foo.bar
|
|
212
|
+
end namespace
|
|
213
|
+
|
|
214
|
+
class Person
|
|
215
|
+
end class
|
|
216
|
+
`);
|
|
217
|
+
const result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(2, 24)).map(x => x.label);
|
|
218
|
+
(0, chai_1.expect)(result).includes('main');
|
|
219
|
+
(0, chai_1.expect)(result).includes('foo');
|
|
220
|
+
(0, chai_1.expect)(result).includes('Person');
|
|
221
|
+
});
|
|
222
|
+
it('gets namespace completions', () => {
|
|
223
|
+
program.setFile('source/main.bs', `
|
|
224
|
+
namespace foo.bar
|
|
225
|
+
function sayHello()
|
|
226
|
+
end function
|
|
227
|
+
end namespace
|
|
228
|
+
|
|
229
|
+
sub Main()
|
|
230
|
+
print "hello"
|
|
231
|
+
foo.ba
|
|
232
|
+
foo.bar.
|
|
233
|
+
end sub
|
|
234
|
+
`);
|
|
235
|
+
let result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(8, 30));
|
|
236
|
+
let names = result.map(x => x.label);
|
|
237
|
+
(0, chai_1.expect)(names).to.includes('bar');
|
|
238
|
+
result = program.getCompletions(`${rootDir}/source/main.bs`, vscode_languageserver_1.Position.create(9, 32));
|
|
239
|
+
names = result.map(x => x.label);
|
|
240
|
+
(0, chai_1.expect)(names).to.includes('sayHello');
|
|
241
|
+
});
|
|
149
242
|
});
|
|
150
243
|
it('always includes `m`', () => {
|
|
151
244
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
152
|
-
program.
|
|
245
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
153
246
|
sub Main()
|
|
154
247
|
|
|
155
248
|
end sub
|
|
156
249
|
`);
|
|
157
250
|
let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
|
|
158
251
|
let names = result.map(x => x.label);
|
|
159
|
-
chai_1.expect(names).to.contain('m');
|
|
252
|
+
(0, chai_1.expect)(names).to.contain('m');
|
|
160
253
|
});
|
|
161
254
|
it('does not fail for missing previousToken', () => {
|
|
162
255
|
//add a single character to the file, and get completions after it
|
|
163
|
-
program.
|
|
164
|
-
chai_1.expect(() => {
|
|
256
|
+
program.setFile('source/main.brs', `i`);
|
|
257
|
+
(0, chai_1.expect)(() => {
|
|
165
258
|
program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(0, 1)).map(x => x.label);
|
|
166
259
|
}).not.to.throw;
|
|
167
260
|
});
|
|
168
261
|
it('includes all keywords`', () => {
|
|
169
262
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
170
|
-
program.
|
|
263
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
171
264
|
sub Main()
|
|
172
265
|
|
|
173
266
|
end sub
|
|
174
267
|
`);
|
|
175
|
-
let keywords = Object.keys(
|
|
268
|
+
let keywords = Object.keys(TokenKind_1.Keywords).filter(x => !x.includes(' '));
|
|
176
269
|
//inside the function
|
|
177
270
|
let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
|
|
178
271
|
let names = result.map(x => x.label);
|
|
179
272
|
for (let keyword of keywords) {
|
|
180
|
-
chai_1.expect(names).to.include(keyword);
|
|
273
|
+
(0, chai_1.expect)(names).to.include(keyword);
|
|
181
274
|
}
|
|
182
275
|
//outside the function
|
|
183
276
|
result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(4, 8));
|
|
184
277
|
names = result.map(x => x.label);
|
|
185
278
|
for (let keyword of keywords) {
|
|
186
|
-
chai_1.expect(names).to.include(keyword);
|
|
279
|
+
(0, chai_1.expect)(names).to.include(keyword);
|
|
187
280
|
}
|
|
188
281
|
});
|
|
189
282
|
it('does not provide completions within a comment', () => {
|
|
190
283
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
191
|
-
program.
|
|
284
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
192
285
|
sub Main()
|
|
193
286
|
'some comment
|
|
194
287
|
end sub
|
|
195
288
|
`);
|
|
196
289
|
//inside the function
|
|
197
290
|
let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 33));
|
|
198
|
-
chai_1.expect(result).to.be.lengthOf(0);
|
|
291
|
+
(0, chai_1.expect)(result).to.be.lengthOf(0);
|
|
199
292
|
});
|
|
200
293
|
it('does not provide duplicate entries for variables', () => {
|
|
201
294
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
202
|
-
program.
|
|
295
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
203
296
|
sub Main()
|
|
204
297
|
name = "bob"
|
|
205
298
|
age = 12
|
|
@@ -210,67 +303,91 @@ describe('BrsFile', () => {
|
|
|
210
303
|
let count = result.reduce((total, x) => {
|
|
211
304
|
return x.label === 'name' ? total + 1 : total;
|
|
212
305
|
}, 0);
|
|
213
|
-
chai_1.expect(count).to.equal(1);
|
|
306
|
+
(0, chai_1.expect)(count).to.equal(1);
|
|
214
307
|
});
|
|
215
308
|
it('does not include `as` and `string` text options when used in function params', () => {
|
|
216
309
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
217
|
-
program.
|
|
310
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
218
311
|
sub Main(name as string)
|
|
219
312
|
|
|
220
313
|
end sub
|
|
221
314
|
`);
|
|
222
315
|
let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 23));
|
|
223
|
-
chai_1.expect(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('as');
|
|
224
|
-
chai_1.expect(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('string');
|
|
316
|
+
(0, chai_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('as');
|
|
317
|
+
(0, chai_1.expect)(result.filter(x => x.kind === vscode_languageserver_1.CompletionItemKind.Text)).not.to.contain('string');
|
|
225
318
|
});
|
|
226
319
|
it('does not provide intellisense results when inside a comment', () => {
|
|
227
320
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
228
|
-
program.
|
|
321
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
229
322
|
sub Main(name as string)
|
|
230
323
|
'this is a comment
|
|
231
324
|
end sub
|
|
232
325
|
`);
|
|
233
326
|
let results = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(2, 30));
|
|
234
|
-
chai_1.expect(results).to.be.empty;
|
|
327
|
+
(0, chai_1.expect)(results).to.be.empty;
|
|
235
328
|
});
|
|
236
329
|
it('does provide intellisence for labels only after a goto keyword', () => {
|
|
237
330
|
var _a;
|
|
238
331
|
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
239
|
-
program.
|
|
332
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
240
333
|
sub Main(name as string)
|
|
241
334
|
something:
|
|
242
335
|
goto \nend sub
|
|
243
336
|
`);
|
|
244
337
|
let results = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 25));
|
|
245
|
-
chai_1.expect(results.length).to.equal(1);
|
|
246
|
-
chai_1.expect((_a = results[0]) === null || _a === void 0 ? void 0 : _a.label).to.equal('something');
|
|
338
|
+
(0, chai_1.expect)(results.length).to.equal(1);
|
|
339
|
+
(0, chai_1.expect)((_a = results[0]) === null || _a === void 0 ? void 0 : _a.label).to.equal('something');
|
|
340
|
+
});
|
|
341
|
+
it('includes properties of objects', () => {
|
|
342
|
+
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
343
|
+
program.setFile('source/main.brs', `
|
|
344
|
+
sub Main()
|
|
345
|
+
myObj = {name:"Bob", age: 34, height:6.0}
|
|
346
|
+
myObj.
|
|
347
|
+
end sub
|
|
348
|
+
`);
|
|
349
|
+
let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 26));
|
|
350
|
+
let names = result.map(x => x.label);
|
|
351
|
+
(0, chai_1.expect)(names).to.contain('name');
|
|
352
|
+
(0, chai_1.expect)(names).to.contain('age');
|
|
353
|
+
(0, chai_1.expect)(names).to.contain('height');
|
|
354
|
+
});
|
|
355
|
+
it('includes properties of m', () => {
|
|
356
|
+
//eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
357
|
+
program.setFile('source/main.brs', `
|
|
358
|
+
sub Main()
|
|
359
|
+
m.someField= "hello"
|
|
360
|
+
m.
|
|
361
|
+
end sub
|
|
362
|
+
`);
|
|
363
|
+
let result = program.getCompletions(`${rootDir}/source/main.brs`, vscode_languageserver_1.Position.create(3, 22));
|
|
364
|
+
let names = result.map(x => x.label);
|
|
365
|
+
(0, chai_1.expect)(names).to.contain('someField');
|
|
247
366
|
});
|
|
248
367
|
});
|
|
249
368
|
describe('comment flags', () => {
|
|
250
369
|
describe('bs:disable-next-line', () => {
|
|
251
370
|
it('disables critical diagnostic issues', () => {
|
|
252
|
-
|
|
253
|
-
program.addOrReplaceFile('source/main.brs', `
|
|
371
|
+
program.setFile('source/main.brs', `
|
|
254
372
|
sub main()
|
|
255
373
|
Dim requestData
|
|
256
374
|
end sub
|
|
257
375
|
`);
|
|
258
376
|
//should have an error
|
|
259
377
|
program.validate();
|
|
260
|
-
|
|
261
|
-
program.
|
|
378
|
+
(0, testHelpers_spec_1.expectHasDiagnostics)(program);
|
|
379
|
+
program.setFile('source/main.brs', `
|
|
262
380
|
sub main()
|
|
263
381
|
'bs:disable-next-line
|
|
264
382
|
Dim requestData
|
|
265
383
|
end sub
|
|
266
384
|
`);
|
|
267
|
-
//should have an error
|
|
385
|
+
//should not have an error
|
|
268
386
|
program.validate();
|
|
269
|
-
|
|
387
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
270
388
|
});
|
|
271
389
|
it('works with leading whitespace', () => {
|
|
272
|
-
|
|
273
|
-
program.addOrReplaceFile('source/main.brs', `
|
|
390
|
+
program.setFile('source/main.brs', `
|
|
274
391
|
sub main()
|
|
275
392
|
' bs:disable-next-line
|
|
276
393
|
=asdf=sadf=
|
|
@@ -278,89 +395,96 @@ describe('BrsFile', () => {
|
|
|
278
395
|
`);
|
|
279
396
|
//should have an error
|
|
280
397
|
program.validate();
|
|
281
|
-
|
|
398
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
282
399
|
});
|
|
283
400
|
it('works for all', () => {
|
|
284
|
-
|
|
285
|
-
let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
401
|
+
let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
286
402
|
sub Main()
|
|
287
403
|
'bs:disable-next-line
|
|
288
404
|
name = "bob
|
|
289
405
|
end sub
|
|
290
406
|
`);
|
|
291
|
-
chai_1.expect(file.commentFlags[0]).to.exist;
|
|
292
|
-
chai_1.expect(file.commentFlags[0]).to.deep.include({
|
|
407
|
+
(0, chai_1.expect)(file.commentFlags[0]).to.exist;
|
|
408
|
+
(0, chai_1.expect)(file.commentFlags[0]).to.deep.include({
|
|
293
409
|
codes: null,
|
|
294
410
|
range: vscode_languageserver_1.Range.create(2, 24, 2, 45),
|
|
295
411
|
affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
|
|
296
412
|
});
|
|
297
413
|
program.validate();
|
|
298
414
|
//the "unterminated string" error should be filtered out
|
|
299
|
-
|
|
415
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
300
416
|
});
|
|
301
417
|
it('works for specific codes', () => {
|
|
302
|
-
|
|
303
|
-
let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
418
|
+
let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
304
419
|
sub Main()
|
|
305
420
|
'bs:disable-next-line: 1083, 1001
|
|
306
421
|
name = "bob
|
|
307
422
|
end sub
|
|
308
423
|
`);
|
|
309
|
-
chai_1.expect(file.commentFlags[0]).to.exist;
|
|
310
|
-
chai_1.expect(file.commentFlags[0]).to.deep.include({
|
|
424
|
+
(0, chai_1.expect)(file.commentFlags[0]).to.exist;
|
|
425
|
+
(0, chai_1.expect)(file.commentFlags[0]).to.deep.include({
|
|
311
426
|
codes: [1083, 1001],
|
|
312
427
|
range: vscode_languageserver_1.Range.create(2, 24, 2, 57),
|
|
313
428
|
affectedRange: util_1.default.createRange(3, 0, 3, Number.MAX_SAFE_INTEGER)
|
|
314
429
|
});
|
|
315
430
|
//the "unterminated string" error should be filtered out
|
|
316
|
-
|
|
431
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
317
432
|
});
|
|
318
|
-
it('
|
|
319
|
-
|
|
320
|
-
let file = program.addOrReplaceFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
433
|
+
it('recognizes non-numeric codes', () => {
|
|
434
|
+
let file = program.setFile('source/main.brs', `
|
|
321
435
|
sub Main()
|
|
322
436
|
'bs:disable-next-line: LINT9999
|
|
323
437
|
name = "bob
|
|
324
438
|
end sub
|
|
325
|
-
|
|
326
|
-
chai_1.expect(file.commentFlags[0]).to.
|
|
327
|
-
|
|
439
|
+
`);
|
|
440
|
+
(0, chai_1.expect)(file.commentFlags[0]).to.exist;
|
|
441
|
+
(0, testHelpers_spec_1.expectHasDiagnostics)(program);
|
|
442
|
+
});
|
|
443
|
+
it('supports disabling non-numeric error codes', () => {
|
|
444
|
+
const program = new Program_1.Program({});
|
|
445
|
+
const file = program.setFile('source/main.brs', `
|
|
446
|
+
sub main()
|
|
447
|
+
something = true 'bs:disable-line: LINT1005
|
|
448
|
+
end sub
|
|
449
|
+
`);
|
|
450
|
+
file.addDiagnostics([{
|
|
451
|
+
code: 'LINT1005',
|
|
452
|
+
file: file,
|
|
453
|
+
message: 'Something is not right',
|
|
454
|
+
range: util_1.default.createRange(2, 16, 2, 26)
|
|
455
|
+
}]);
|
|
456
|
+
const scope = program.getScopesForFile(file)[0];
|
|
457
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(scope);
|
|
328
458
|
});
|
|
329
459
|
it('adds diagnostics for unknown numeric diagnostic codes', () => {
|
|
330
|
-
program.
|
|
460
|
+
program.setFile({ src: `${rootDir} / source / main.brs`, dest: 'source/main.brs' }, `
|
|
331
461
|
sub main()
|
|
332
462
|
print "hi" 'bs:disable-line: 123456 999999 aaaab
|
|
333
463
|
end sub
|
|
334
|
-
|
|
464
|
+
`);
|
|
335
465
|
program.validate();
|
|
336
|
-
|
|
337
|
-
chai_1.expect(program.getDiagnostics()[0]).to.deep.include({
|
|
338
|
-
range: vscode_languageserver_1.Range.create(2, 53, 2, 59)
|
|
339
|
-
});
|
|
340
|
-
chai_1.expect(program.getDiagnostics()[1]).to.deep.include({
|
|
341
|
-
range: vscode_languageserver_1.Range.create(2, 60, 2, 66)
|
|
342
|
-
});
|
|
466
|
+
(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) })]);
|
|
343
467
|
});
|
|
344
468
|
});
|
|
345
469
|
describe('bs:disable-line', () => {
|
|
346
470
|
it('works for all', () => {
|
|
347
|
-
let file = program.
|
|
471
|
+
let file = program.setFile({ src: `${rootDir} / source / main.brs`, dest: 'source/main.brs' }, `
|
|
348
472
|
sub Main()
|
|
349
473
|
z::;;%%%%%% 'bs:disable-line
|
|
350
474
|
end sub
|
|
351
475
|
`);
|
|
352
|
-
chai_1.expect(file.commentFlags[0]).to.exist;
|
|
353
|
-
chai_1.expect(file.commentFlags[0]).to.deep.include({
|
|
476
|
+
(0, chai_1.expect)(file.commentFlags[0]).to.exist;
|
|
477
|
+
(0, chai_1.expect)(file.commentFlags[0]).to.deep.include({
|
|
354
478
|
codes: null,
|
|
355
479
|
range: vscode_languageserver_1.Range.create(2, 36, 2, 52),
|
|
356
480
|
affectedRange: vscode_languageserver_1.Range.create(2, 0, 2, 36)
|
|
357
481
|
});
|
|
358
482
|
program.validate();
|
|
359
483
|
//the "unterminated string" error should be filtered out
|
|
360
|
-
|
|
484
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
361
485
|
});
|
|
362
486
|
it('works for specific codes', () => {
|
|
363
|
-
program.
|
|
487
|
+
program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
364
488
|
sub main()
|
|
365
489
|
'should not have any errors
|
|
366
490
|
DoSomething(1) 'bs:disable-line:1002
|
|
@@ -371,42 +495,41 @@ describe('BrsFile', () => {
|
|
|
371
495
|
end sub
|
|
372
496
|
`);
|
|
373
497
|
program.validate();
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
});
|
|
498
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [{
|
|
499
|
+
range: vscode_languageserver_1.Range.create(5, 24, 5, 35)
|
|
500
|
+
}]);
|
|
378
501
|
});
|
|
379
502
|
it('handles the erraneous `stop` keyword', () => {
|
|
380
503
|
//the current version of BRS causes parse errors after the `parse` keyword, showing error in comments
|
|
381
504
|
//the program should ignore all diagnostics found in brs:* comment lines EXCEPT
|
|
382
505
|
//for the diagnostics about using unknown error codes
|
|
383
|
-
program.
|
|
506
|
+
program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
384
507
|
sub main()
|
|
385
508
|
stop 'bs:disable-line
|
|
386
509
|
print "need a valid line to fix stop error"
|
|
387
510
|
end sub
|
|
388
|
-
|
|
511
|
+
`);
|
|
389
512
|
program.validate();
|
|
390
|
-
|
|
513
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
391
514
|
});
|
|
392
515
|
});
|
|
393
516
|
});
|
|
394
517
|
describe('parse', () => {
|
|
395
518
|
it('supports iife in assignment', () => {
|
|
396
|
-
program.
|
|
519
|
+
program.setFile('source/main.brs', `
|
|
397
520
|
sub main()
|
|
398
|
-
|
|
521
|
+
result = sub()
|
|
399
522
|
end sub()
|
|
400
|
-
|
|
523
|
+
result = (sub()
|
|
401
524
|
end sub)()
|
|
402
525
|
end sub
|
|
403
526
|
`);
|
|
404
|
-
testHelpers_spec_1.expectZeroDiagnostics(program);
|
|
527
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
405
528
|
});
|
|
406
529
|
it('uses the proper parse mode based on file extension', () => {
|
|
407
530
|
function testParseMode(destPath, expectedParseMode) {
|
|
408
|
-
const file = program.
|
|
409
|
-
chai_1.expect(file.parseMode).to.equal(expectedParseMode);
|
|
531
|
+
const file = program.setFile(destPath, '');
|
|
532
|
+
(0, chai_1.expect)(file.parseMode).to.equal(expectedParseMode);
|
|
410
533
|
}
|
|
411
534
|
testParseMode('source/main.brs', Parser_1.ParseMode.BrightScript);
|
|
412
535
|
testParseMode('source/main.spec.brs', Parser_1.ParseMode.BrightScript);
|
|
@@ -416,26 +539,26 @@ describe('BrsFile', () => {
|
|
|
416
539
|
testParseMode('source/main.spec.bs', Parser_1.ParseMode.BrighterScript);
|
|
417
540
|
});
|
|
418
541
|
it('supports labels and goto statements', () => {
|
|
419
|
-
let file = program.
|
|
542
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
420
543
|
sub Main()
|
|
421
544
|
'multiple goto statements on one line
|
|
422
|
-
goto myLabel
|
|
545
|
+
goto myLabel: goto myLabel
|
|
423
546
|
myLabel:
|
|
424
547
|
end sub
|
|
425
548
|
`);
|
|
426
|
-
|
|
549
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
427
550
|
});
|
|
428
551
|
it('supports empty print statements', () => {
|
|
429
|
-
let file = program.
|
|
552
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
430
553
|
sub main()
|
|
431
|
-
|
|
554
|
+
print
|
|
432
555
|
end sub
|
|
433
556
|
`);
|
|
434
|
-
|
|
557
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
435
558
|
});
|
|
436
559
|
describe('conditional compile', () => {
|
|
437
560
|
it('works for upper case keywords', () => {
|
|
438
|
-
let file = program.
|
|
561
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
439
562
|
sub main()
|
|
440
563
|
#CONST someFlag = true
|
|
441
564
|
#IF someFlag
|
|
@@ -447,10 +570,10 @@ describe('BrsFile', () => {
|
|
|
447
570
|
#ENDIF
|
|
448
571
|
end sub
|
|
449
572
|
`);
|
|
450
|
-
|
|
573
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
451
574
|
});
|
|
452
575
|
it('supports single-word #elseif and #endif', () => {
|
|
453
|
-
let file = program.
|
|
576
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
454
577
|
sub main()
|
|
455
578
|
#const someFlag = true
|
|
456
579
|
#if someFlag
|
|
@@ -460,10 +583,10 @@ describe('BrsFile', () => {
|
|
|
460
583
|
#endif
|
|
461
584
|
end sub
|
|
462
585
|
`);
|
|
463
|
-
|
|
586
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
464
587
|
});
|
|
465
588
|
it('supports multi-word #else if and #end if', () => {
|
|
466
|
-
let file = program.
|
|
589
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
467
590
|
sub main()
|
|
468
591
|
#const someFlag = true
|
|
469
592
|
#if someFlag
|
|
@@ -473,84 +596,93 @@ describe('BrsFile', () => {
|
|
|
473
596
|
#end if
|
|
474
597
|
end sub
|
|
475
598
|
`);
|
|
476
|
-
|
|
599
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
477
600
|
});
|
|
478
601
|
it('does not choke on invalid code inside a false conditional compile', () => {
|
|
479
|
-
let file = program.
|
|
602
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
480
603
|
sub main()
|
|
481
604
|
#if false
|
|
482
|
-
non-commented code here should not cause parse errors
|
|
605
|
+
non - commented code here should not cause parse errors
|
|
483
606
|
#end if
|
|
484
607
|
end sub
|
|
485
608
|
`);
|
|
486
|
-
|
|
609
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
487
610
|
});
|
|
488
611
|
it('detects syntax error in #if', () => {
|
|
489
|
-
let file = program.
|
|
612
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
490
613
|
sub main()
|
|
491
614
|
#if true1
|
|
492
615
|
print "true"
|
|
493
616
|
#end if
|
|
494
617
|
end sub
|
|
495
618
|
`);
|
|
496
|
-
|
|
619
|
+
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
620
|
+
DiagnosticMessages_1.DiagnosticMessages.referencedConstDoesNotExist()
|
|
621
|
+
]);
|
|
497
622
|
});
|
|
498
623
|
it('detects syntax error in #const', () => {
|
|
499
|
-
let file = program.
|
|
624
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
500
625
|
sub main()
|
|
501
626
|
#if %
|
|
502
627
|
print "true"
|
|
503
628
|
#end if
|
|
504
629
|
end sub
|
|
505
630
|
`);
|
|
506
|
-
|
|
631
|
+
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
632
|
+
DiagnosticMessages_1.DiagnosticMessages.unexpectedCharacter('%'),
|
|
633
|
+
DiagnosticMessages_1.DiagnosticMessages.invalidHashIfValue()
|
|
634
|
+
]);
|
|
507
635
|
});
|
|
508
636
|
it('detects #const name using reserved word', () => {
|
|
509
|
-
let file = program.
|
|
637
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
510
638
|
sub main()
|
|
511
639
|
#const function = true
|
|
512
640
|
end sub
|
|
513
641
|
`);
|
|
514
|
-
|
|
642
|
+
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
643
|
+
DiagnosticMessages_1.DiagnosticMessages.constNameCannotBeReservedWord(),
|
|
644
|
+
DiagnosticMessages_1.DiagnosticMessages.unexpectedToken('#const')
|
|
645
|
+
]);
|
|
515
646
|
});
|
|
516
647
|
it('detects syntax error in #const', () => {
|
|
517
|
-
let file = program.
|
|
648
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
518
649
|
sub main()
|
|
519
650
|
#const someConst = 123
|
|
520
651
|
end sub
|
|
521
652
|
`);
|
|
522
|
-
|
|
653
|
+
(0, testHelpers_spec_1.expectDiagnostics)(file, [
|
|
654
|
+
DiagnosticMessages_1.DiagnosticMessages.invalidHashConstValue()
|
|
655
|
+
]);
|
|
523
656
|
});
|
|
524
657
|
});
|
|
525
658
|
it('supports stop statement', () => {
|
|
526
|
-
let file = program.
|
|
659
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
527
660
|
sub main()
|
|
528
|
-
|
|
661
|
+
stop
|
|
529
662
|
end sub
|
|
530
663
|
`);
|
|
531
|
-
|
|
664
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
532
665
|
});
|
|
533
666
|
it('supports single-line if statements', () => {
|
|
534
|
-
let file = program.
|
|
667
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
535
668
|
sub main()
|
|
536
669
|
if 1 < 2: return true: end if
|
|
537
670
|
if 1 < 2: return true
|
|
538
671
|
end if
|
|
539
672
|
if false : print "true" : end if
|
|
540
673
|
if true: print "8 worked": else if true: print "not run": else: print "not run": end if
|
|
541
|
-
if true then
|
|
674
|
+
if true then: test = sub() : print "yes" : end sub: end if
|
|
542
675
|
end sub
|
|
543
676
|
`);
|
|
544
|
-
|
|
677
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
545
678
|
});
|
|
546
679
|
it('supports line_num as global variable', () => {
|
|
547
|
-
var _a;
|
|
548
680
|
file.parse(`
|
|
549
681
|
sub Main()
|
|
550
682
|
print LINE_NUM
|
|
551
683
|
end sub
|
|
552
684
|
`);
|
|
553
|
-
|
|
685
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
554
686
|
});
|
|
555
687
|
it('supports many keywords as object property names', () => {
|
|
556
688
|
file.parse(`
|
|
@@ -616,7 +748,7 @@ describe('BrsFile', () => {
|
|
|
616
748
|
person.new = true
|
|
617
749
|
end sub
|
|
618
750
|
`);
|
|
619
|
-
|
|
751
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
620
752
|
});
|
|
621
753
|
it('does not error on numeric literal type designators', () => {
|
|
622
754
|
file.parse(`
|
|
@@ -624,13 +756,13 @@ describe('BrsFile', () => {
|
|
|
624
756
|
print &he2
|
|
625
757
|
print 1.2E+2
|
|
626
758
|
print 2!
|
|
627
|
-
print 12D-12
|
|
759
|
+
print 12D - 12
|
|
628
760
|
print 2.3#
|
|
629
761
|
print &hFEDCBA9876543210&
|
|
630
762
|
print 9876543210&
|
|
631
763
|
end sub
|
|
632
764
|
`);
|
|
633
|
-
|
|
765
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
634
766
|
});
|
|
635
767
|
it('does not error when encountering sub with return type', () => {
|
|
636
768
|
file.parse(`
|
|
@@ -638,7 +770,7 @@ describe('BrsFile', () => {
|
|
|
638
770
|
return
|
|
639
771
|
end sub
|
|
640
772
|
`);
|
|
641
|
-
|
|
773
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
642
774
|
});
|
|
643
775
|
it('does not lose function statements when mismatched end sub', () => {
|
|
644
776
|
file.parse(`
|
|
@@ -650,7 +782,7 @@ describe('BrsFile', () => {
|
|
|
650
782
|
print "hello world"
|
|
651
783
|
end sub
|
|
652
784
|
`);
|
|
653
|
-
chai_1.expect(file.parser.references.functionStatements).to.be.lengthOf(2);
|
|
785
|
+
(0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(2);
|
|
654
786
|
});
|
|
655
787
|
it('does not lose sub scope when mismatched end function', () => {
|
|
656
788
|
file.parse(`
|
|
@@ -662,7 +794,7 @@ describe('BrsFile', () => {
|
|
|
662
794
|
print "hello world"
|
|
663
795
|
end sub
|
|
664
796
|
`);
|
|
665
|
-
chai_1.expect(file.parser.references.functionStatements).to.be.lengthOf(2);
|
|
797
|
+
(0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(2);
|
|
666
798
|
});
|
|
667
799
|
it('does not error with boolean in RHS of set statement', () => {
|
|
668
800
|
file.parse(`
|
|
@@ -673,7 +805,7 @@ describe('BrsFile', () => {
|
|
|
673
805
|
foo.bar = true and false or 3 > 4
|
|
674
806
|
end sub
|
|
675
807
|
`);
|
|
676
|
-
|
|
808
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
677
809
|
});
|
|
678
810
|
it('does not error with boolean in RHS of set statement', () => {
|
|
679
811
|
file.parse(`
|
|
@@ -686,57 +818,57 @@ describe('BrsFile', () => {
|
|
|
686
818
|
m.isTrue = m.isTrue = m.isTrue
|
|
687
819
|
end sub
|
|
688
820
|
`);
|
|
689
|
-
|
|
821
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
690
822
|
});
|
|
691
823
|
it('supports variable names ending with type designators', () => {
|
|
692
824
|
file.parse(`
|
|
693
825
|
sub main()
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
826
|
+
name$ = "bob"
|
|
827
|
+
age% = 1
|
|
828
|
+
height! = 5.5
|
|
829
|
+
salary# = 9.87654321
|
|
830
|
+
someHex& = 13
|
|
699
831
|
end sub
|
|
700
832
|
`);
|
|
701
|
-
|
|
833
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
702
834
|
});
|
|
703
835
|
it('supports multiple spaces between two-word keywords', () => {
|
|
704
836
|
file.parse(`
|
|
705
837
|
sub main()
|
|
706
838
|
if true then
|
|
707
839
|
print "true"
|
|
708
|
-
else
|
|
840
|
+
else if true then
|
|
709
841
|
print "also true"
|
|
710
842
|
end if
|
|
711
843
|
end sub
|
|
712
844
|
`);
|
|
713
|
-
|
|
845
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
714
846
|
});
|
|
715
847
|
it('does not error with `stop` as object key', () => {
|
|
716
848
|
file.parse(`
|
|
717
849
|
function GetObject()
|
|
718
850
|
obj = {
|
|
719
|
-
|
|
851
|
+
stop: function () as void
|
|
720
852
|
|
|
721
|
-
|
|
853
|
+
end function
|
|
722
854
|
}
|
|
723
855
|
return obj
|
|
724
856
|
end function
|
|
725
857
|
`);
|
|
726
|
-
|
|
858
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
727
859
|
});
|
|
728
860
|
it('does not error with `run` as object key', () => {
|
|
729
861
|
file.parse(`
|
|
730
862
|
function GetObject()
|
|
731
863
|
obj = {
|
|
732
|
-
run: function() as void
|
|
864
|
+
run: function () as void
|
|
733
865
|
|
|
734
866
|
end function
|
|
735
|
-
|
|
867
|
+
}
|
|
736
868
|
return obj
|
|
737
869
|
end function
|
|
738
870
|
`);
|
|
739
|
-
|
|
871
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
740
872
|
});
|
|
741
873
|
it('supports assignment operators', () => {
|
|
742
874
|
file.parse(`
|
|
@@ -753,28 +885,28 @@ describe('BrsFile', () => {
|
|
|
753
885
|
print x
|
|
754
886
|
end function
|
|
755
887
|
`);
|
|
756
|
-
|
|
888
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
757
889
|
});
|
|
758
890
|
it('supports `then` as object property', () => {
|
|
759
891
|
file.parse(`
|
|
760
892
|
function Main()
|
|
761
893
|
promise = {
|
|
762
894
|
then: sub()
|
|
763
|
-
|
|
895
|
+
end sub
|
|
764
896
|
}
|
|
765
897
|
promise.then()
|
|
766
898
|
end function
|
|
767
899
|
`);
|
|
768
|
-
|
|
900
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
769
901
|
});
|
|
770
902
|
it('supports function as parameter type', () => {
|
|
771
903
|
file.parse(`
|
|
772
904
|
sub Main()
|
|
773
|
-
doWork = function(callback as function)
|
|
905
|
+
doWork = function (callback as function)
|
|
774
906
|
end function
|
|
775
907
|
end sub
|
|
776
908
|
`);
|
|
777
|
-
|
|
909
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
778
910
|
});
|
|
779
911
|
it('supports increment operator', () => {
|
|
780
912
|
file.parse(`
|
|
@@ -783,8 +915,7 @@ describe('BrsFile', () => {
|
|
|
783
915
|
x++
|
|
784
916
|
end function
|
|
785
917
|
`);
|
|
786
|
-
|
|
787
|
-
chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
|
|
918
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
788
919
|
});
|
|
789
920
|
it('supports decrement operator', () => {
|
|
790
921
|
file.parse(`
|
|
@@ -793,8 +924,7 @@ describe('BrsFile', () => {
|
|
|
793
924
|
x--
|
|
794
925
|
end function
|
|
795
926
|
`);
|
|
796
|
-
|
|
797
|
-
chai_1.expect(file.getDiagnostics()).to.be.lengthOf(0);
|
|
927
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
798
928
|
});
|
|
799
929
|
it('supports writing numbers with decimal but no trailing digit', () => {
|
|
800
930
|
file.parse(`
|
|
@@ -803,7 +933,7 @@ describe('BrsFile', () => {
|
|
|
803
933
|
print x
|
|
804
934
|
end function
|
|
805
935
|
`);
|
|
806
|
-
|
|
936
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
807
937
|
});
|
|
808
938
|
it('supports assignment operators against object properties', () => {
|
|
809
939
|
file.parse(`
|
|
@@ -825,7 +955,7 @@ describe('BrsFile', () => {
|
|
|
825
955
|
print m.age
|
|
826
956
|
end function
|
|
827
957
|
`);
|
|
828
|
-
|
|
958
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
829
959
|
});
|
|
830
960
|
//skipped until `brs` supports this
|
|
831
961
|
it('supports bitshift assignment operators', () => {
|
|
@@ -837,7 +967,7 @@ describe('BrsFile', () => {
|
|
|
837
967
|
print x
|
|
838
968
|
end function
|
|
839
969
|
`);
|
|
840
|
-
|
|
970
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
841
971
|
});
|
|
842
972
|
//skipped until `brs` supports this
|
|
843
973
|
it('supports bitshift assignment operators on objects', () => {
|
|
@@ -849,7 +979,7 @@ describe('BrsFile', () => {
|
|
|
849
979
|
print m.x
|
|
850
980
|
end function
|
|
851
981
|
`);
|
|
852
|
-
|
|
982
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
853
983
|
});
|
|
854
984
|
it('supports leading and trailing periods for numeric literals', () => {
|
|
855
985
|
file.parse(`
|
|
@@ -860,7 +990,7 @@ describe('BrsFile', () => {
|
|
|
860
990
|
print pointOne
|
|
861
991
|
end function
|
|
862
992
|
`);
|
|
863
|
-
|
|
993
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
864
994
|
});
|
|
865
995
|
it('supports bitshift assignment operators on object properties accessed by array syntax', () => {
|
|
866
996
|
file.parse(`
|
|
@@ -871,7 +1001,7 @@ describe('BrsFile', () => {
|
|
|
871
1001
|
print m.x
|
|
872
1002
|
end function
|
|
873
1003
|
`);
|
|
874
|
-
|
|
1004
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
875
1005
|
});
|
|
876
1006
|
it('supports weird period AA accessor', () => {
|
|
877
1007
|
file.parse(`
|
|
@@ -880,67 +1010,71 @@ describe('BrsFile', () => {
|
|
|
880
1010
|
print m.["_uuid"]
|
|
881
1011
|
end function
|
|
882
1012
|
`);
|
|
883
|
-
|
|
1013
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
884
1014
|
});
|
|
885
1015
|
it('adds error for library statements NOT at top of file', () => {
|
|
886
|
-
|
|
1016
|
+
program.setFile('source/file.brs', ``);
|
|
1017
|
+
program.setFile('source/main.bs', `
|
|
887
1018
|
sub main()
|
|
888
1019
|
end sub
|
|
889
1020
|
import "file.brs"
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
1021
|
+
`);
|
|
1022
|
+
program.validate();
|
|
1023
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1024
|
+
DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()
|
|
893
1025
|
]);
|
|
894
1026
|
});
|
|
895
1027
|
it('supports library imports', () => {
|
|
896
|
-
|
|
1028
|
+
program.setFile('source/main.brs', `
|
|
897
1029
|
Library "v30/bslCore.brs"
|
|
898
1030
|
`);
|
|
899
|
-
|
|
1031
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
900
1032
|
});
|
|
901
1033
|
it('adds error for library statements NOT at top of file', () => {
|
|
902
|
-
|
|
1034
|
+
program.setFile('source/main.brs', `
|
|
903
1035
|
sub main()
|
|
904
1036
|
end sub
|
|
905
1037
|
Library "v30/bslCore.brs"
|
|
906
1038
|
`);
|
|
907
|
-
|
|
908
|
-
|
|
1039
|
+
program.validate();
|
|
1040
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1041
|
+
DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
|
|
909
1042
|
]);
|
|
910
1043
|
});
|
|
911
1044
|
it('adds error for library statements inside of function body', () => {
|
|
912
|
-
|
|
1045
|
+
program.setFile('source/main.brs', `
|
|
913
1046
|
sub main()
|
|
914
1047
|
Library "v30/bslCore.brs"
|
|
915
1048
|
end sub
|
|
916
1049
|
`);
|
|
917
|
-
|
|
918
|
-
|
|
1050
|
+
program.validate();
|
|
1051
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1052
|
+
DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()
|
|
919
1053
|
]);
|
|
920
1054
|
});
|
|
921
1055
|
it('supports colons as separators in associative array properties', () => {
|
|
922
1056
|
file.parse(`
|
|
923
1057
|
sub Main()
|
|
924
|
-
obj = {x:0 : y: 1}
|
|
1058
|
+
obj = { x: 0 : y: 1 }
|
|
925
1059
|
end sub
|
|
926
1060
|
`);
|
|
927
|
-
|
|
1061
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
928
1062
|
});
|
|
929
1063
|
it('succeeds when finding variables with "sub" in them', () => {
|
|
930
|
-
let file = program.
|
|
1064
|
+
let file = program.setFile('source/main.brs', `
|
|
931
1065
|
function DoSomething()
|
|
932
1066
|
return value.subType()
|
|
933
1067
|
end function
|
|
934
1068
|
`);
|
|
935
|
-
chai_1.expect(file.callables[0]).to.deep.include({
|
|
1069
|
+
(0, chai_1.expect)(file.callables[0]).to.deep.include({
|
|
936
1070
|
file: file,
|
|
937
1071
|
nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36)
|
|
938
1072
|
});
|
|
939
1073
|
});
|
|
940
1074
|
it('succeeds when finding variables with the word "function" in them', () => {
|
|
941
1075
|
file.parse(`
|
|
942
|
-
|
|
943
|
-
|
|
1076
|
+
function Test()
|
|
1077
|
+
typeCheckFunction = RBS_CMN_GetFunction(invalid, methodName)
|
|
944
1078
|
end function
|
|
945
1079
|
`);
|
|
946
1080
|
});
|
|
@@ -951,14 +1085,14 @@ describe('BrsFile', () => {
|
|
|
951
1085
|
print "A"
|
|
952
1086
|
end function
|
|
953
1087
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1088
|
+
function DoB()
|
|
1089
|
+
print "B"
|
|
1090
|
+
end function
|
|
957
1091
|
`);
|
|
958
|
-
chai_1.expect(file.callables[0].name).to.equal('DoA');
|
|
959
|
-
chai_1.expect(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
|
|
960
|
-
chai_1.expect(file.callables[1].name).to.equal('DoB');
|
|
961
|
-
chai_1.expect(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5,
|
|
1092
|
+
(0, chai_1.expect)(file.callables[0].name).to.equal('DoA');
|
|
1093
|
+
(0, chai_1.expect)(file.callables[0].nameRange).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 28));
|
|
1094
|
+
(0, chai_1.expect)(file.callables[1].name).to.equal('DoB');
|
|
1095
|
+
(0, chai_1.expect)(file.callables[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 25, 5, 28));
|
|
962
1096
|
});
|
|
963
1097
|
it('throws an error if the file has already been parsed', () => {
|
|
964
1098
|
let file = new BrsFile_1.BrsFile('abspath', 'relpath', program);
|
|
@@ -982,11 +1116,11 @@ describe('BrsFile', () => {
|
|
|
982
1116
|
print "A"
|
|
983
1117
|
end function
|
|
984
1118
|
`);
|
|
985
|
-
chai_1.expect(file.callables.length).to.equal(2);
|
|
986
|
-
chai_1.expect(file.callables[0].name).to.equal('DoA');
|
|
987
|
-
chai_1.expect(file.callables[0].nameRange.start.line).to.equal(1);
|
|
988
|
-
chai_1.expect(file.callables[1].name).to.equal('DoA');
|
|
989
|
-
chai_1.expect(file.callables[1].nameRange.start.line).to.equal(5);
|
|
1119
|
+
(0, chai_1.expect)(file.callables.length).to.equal(2);
|
|
1120
|
+
(0, chai_1.expect)(file.callables[0].name).to.equal('DoA');
|
|
1121
|
+
(0, chai_1.expect)(file.callables[0].nameRange.start.line).to.equal(1);
|
|
1122
|
+
(0, chai_1.expect)(file.callables[1].name).to.equal('DoA');
|
|
1123
|
+
(0, chai_1.expect)(file.callables[1].nameRange.start.line).to.equal(5);
|
|
990
1124
|
});
|
|
991
1125
|
it('finds function call line and column numbers', () => {
|
|
992
1126
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -998,11 +1132,11 @@ describe('BrsFile', () => {
|
|
|
998
1132
|
DoC()
|
|
999
1133
|
end function
|
|
1000
1134
|
`);
|
|
1001
|
-
chai_1.expect(file.functionCalls.length).to.equal(2);
|
|
1002
|
-
chai_1.expect(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 28));
|
|
1003
|
-
chai_1.expect(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
|
|
1004
|
-
chai_1.expect(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 25));
|
|
1005
|
-
chai_1.expect(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
|
|
1135
|
+
(0, chai_1.expect)(file.functionCalls.length).to.equal(2);
|
|
1136
|
+
(0, chai_1.expect)(file.functionCalls[0].range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 28));
|
|
1137
|
+
(0, chai_1.expect)(file.functionCalls[0].nameRange).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 23));
|
|
1138
|
+
(0, chai_1.expect)(file.functionCalls[1].range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 25));
|
|
1139
|
+
(0, chai_1.expect)(file.functionCalls[1].nameRange).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 23));
|
|
1006
1140
|
});
|
|
1007
1141
|
it('sanitizes brs errors', () => {
|
|
1008
1142
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -1010,11 +1144,9 @@ describe('BrsFile', () => {
|
|
|
1010
1144
|
function DoSomething
|
|
1011
1145
|
end function
|
|
1012
1146
|
`);
|
|
1013
|
-
|
|
1014
|
-
chai_1.expect(file.getDiagnostics()[0]).to.
|
|
1015
|
-
|
|
1016
|
-
});
|
|
1017
|
-
chai_1.expect(file.getDiagnostics()[0].range.start.line).to.equal(1);
|
|
1147
|
+
(0, testHelpers_spec_1.expectHasDiagnostics)(file);
|
|
1148
|
+
(0, chai_1.expect)(file.getDiagnostics()[0].file).to.equal(file);
|
|
1149
|
+
(0, chai_1.expect)(file.getDiagnostics()[0].range.start.line).to.equal(1);
|
|
1018
1150
|
});
|
|
1019
1151
|
it('supports using the `next` keyword in a for loop', () => {
|
|
1020
1152
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -1025,7 +1157,7 @@ describe('BrsFile', () => {
|
|
|
1025
1157
|
next
|
|
1026
1158
|
end sub
|
|
1027
1159
|
`);
|
|
1028
|
-
|
|
1160
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1029
1161
|
});
|
|
1030
1162
|
//test is not working yet, but will be enabled when brs supports this syntax
|
|
1031
1163
|
it('supports assigning functions to objects', () => {
|
|
@@ -1038,7 +1170,7 @@ describe('BrsFile', () => {
|
|
|
1038
1170
|
end sub
|
|
1039
1171
|
end function
|
|
1040
1172
|
`);
|
|
1041
|
-
|
|
1173
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(file);
|
|
1042
1174
|
});
|
|
1043
1175
|
});
|
|
1044
1176
|
describe('findCallables', () => {
|
|
@@ -1050,7 +1182,7 @@ describe('BrsFile', () => {
|
|
|
1050
1182
|
end sub
|
|
1051
1183
|
`);
|
|
1052
1184
|
let callable = file.callables[0];
|
|
1053
|
-
chai_1.expect(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
|
|
1185
|
+
(0, chai_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
|
|
1054
1186
|
});
|
|
1055
1187
|
it('finds correct body range even with inner function', () => {
|
|
1056
1188
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -1063,7 +1195,7 @@ describe('BrsFile', () => {
|
|
|
1063
1195
|
end sub
|
|
1064
1196
|
`);
|
|
1065
1197
|
let callable = file.callables[0];
|
|
1066
|
-
chai_1.expect(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 6, 23));
|
|
1198
|
+
(0, chai_1.expect)(callable.range).to.eql(vscode_languageserver_1.Range.create(1, 16, 6, 23));
|
|
1067
1199
|
});
|
|
1068
1200
|
it('finds callable parameters', () => {
|
|
1069
1201
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -1073,24 +1205,24 @@ describe('BrsFile', () => {
|
|
|
1073
1205
|
end function
|
|
1074
1206
|
`);
|
|
1075
1207
|
let callable = file.callables[0];
|
|
1076
|
-
chai_1.expect(callable.params[0]).to.deep.include({
|
|
1208
|
+
(0, chai_1.expect)(callable.params[0]).to.deep.include({
|
|
1077
1209
|
name: 'a',
|
|
1078
1210
|
isOptional: false,
|
|
1079
1211
|
isRestArgument: false
|
|
1080
1212
|
});
|
|
1081
|
-
chai_1.expect(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
|
|
1082
|
-
chai_1.expect(callable.params[1]).to.deep.include({
|
|
1213
|
+
(0, chai_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
|
|
1214
|
+
(0, chai_1.expect)(callable.params[1]).to.deep.include({
|
|
1083
1215
|
name: 'b',
|
|
1084
1216
|
isOptional: false,
|
|
1085
1217
|
isRestArgument: false
|
|
1086
1218
|
});
|
|
1087
|
-
chai_1.expect(callable.params[1].type).instanceof(DynamicType_1.DynamicType);
|
|
1088
|
-
chai_1.expect(callable.params[2]).to.deep.include({
|
|
1219
|
+
(0, chai_1.expect)(callable.params[1].type).instanceof(DynamicType_1.DynamicType);
|
|
1220
|
+
(0, chai_1.expect)(callable.params[2]).to.deep.include({
|
|
1089
1221
|
name: 'c',
|
|
1090
1222
|
isOptional: false,
|
|
1091
1223
|
isRestArgument: false
|
|
1092
1224
|
});
|
|
1093
|
-
chai_1.expect(callable.params[2].type).instanceof(DynamicType_1.DynamicType);
|
|
1225
|
+
(0, chai_1.expect)(callable.params[2].type).instanceof(DynamicType_1.DynamicType);
|
|
1094
1226
|
});
|
|
1095
1227
|
it('finds optional parameters', () => {
|
|
1096
1228
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -1100,12 +1232,12 @@ describe('BrsFile', () => {
|
|
|
1100
1232
|
end function
|
|
1101
1233
|
`);
|
|
1102
1234
|
let callable = file.callables[0];
|
|
1103
|
-
chai_1.expect(callable.params[0]).to.deep.include({
|
|
1235
|
+
(0, chai_1.expect)(callable.params[0]).to.deep.include({
|
|
1104
1236
|
name: 'a',
|
|
1105
1237
|
isOptional: true,
|
|
1106
1238
|
isRestArgument: false
|
|
1107
1239
|
});
|
|
1108
|
-
chai_1.expect(callable.params[0].type).instanceof(IntegerType_1.IntegerType);
|
|
1240
|
+
(0, chai_1.expect)(callable.params[0].type).instanceof(IntegerType_1.IntegerType);
|
|
1109
1241
|
});
|
|
1110
1242
|
it('finds parameter types', () => {
|
|
1111
1243
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -1115,24 +1247,24 @@ describe('BrsFile', () => {
|
|
|
1115
1247
|
end function
|
|
1116
1248
|
`);
|
|
1117
1249
|
let callable = file.callables[0];
|
|
1118
|
-
chai_1.expect(callable.params[0]).to.deep.include({
|
|
1250
|
+
(0, chai_1.expect)(callable.params[0]).to.deep.include({
|
|
1119
1251
|
name: 'a',
|
|
1120
1252
|
isOptional: false,
|
|
1121
1253
|
isRestArgument: false
|
|
1122
1254
|
});
|
|
1123
|
-
chai_1.expect(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
|
|
1124
|
-
chai_1.expect(callable.params[1]).to.deep.include({
|
|
1255
|
+
(0, chai_1.expect)(callable.params[0].type).instanceof(DynamicType_1.DynamicType);
|
|
1256
|
+
(0, chai_1.expect)(callable.params[1]).to.deep.include({
|
|
1125
1257
|
name: 'b',
|
|
1126
1258
|
isOptional: false,
|
|
1127
1259
|
isRestArgument: false
|
|
1128
1260
|
});
|
|
1129
|
-
chai_1.expect(callable.params[1].type).instanceof(IntegerType_1.IntegerType);
|
|
1130
|
-
chai_1.expect(callable.params[2]).to.deep.include({
|
|
1261
|
+
(0, chai_1.expect)(callable.params[1].type).instanceof(IntegerType_1.IntegerType);
|
|
1262
|
+
(0, chai_1.expect)(callable.params[2]).to.deep.include({
|
|
1131
1263
|
name: 'c',
|
|
1132
1264
|
isOptional: false,
|
|
1133
1265
|
isRestArgument: false
|
|
1134
1266
|
});
|
|
1135
|
-
chai_1.expect(callable.params[2].type).instanceof(StringType_1.StringType);
|
|
1267
|
+
(0, chai_1.expect)(callable.params[2].type).instanceof(StringType_1.StringType);
|
|
1136
1268
|
});
|
|
1137
1269
|
});
|
|
1138
1270
|
describe('findCallableInvocations', () => {
|
|
@@ -1143,8 +1275,12 @@ describe('BrsFile', () => {
|
|
|
1143
1275
|
DoSomething("name", 12, true)
|
|
1144
1276
|
end function
|
|
1145
1277
|
`);
|
|
1146
|
-
chai_1.expect(file.functionCalls.length).to.equal(1);
|
|
1147
|
-
|
|
1278
|
+
(0, chai_1.expect)(file.functionCalls.length).to.equal(1);
|
|
1279
|
+
const argsMap = file.functionCalls[0].args.map(arg => {
|
|
1280
|
+
// disregard arg.expression, etc.
|
|
1281
|
+
return { type: arg.type, range: arg.range, text: arg.text };
|
|
1282
|
+
});
|
|
1283
|
+
(0, chai_1.expect)(argsMap).to.eql([{
|
|
1148
1284
|
type: new StringType_1.StringType(),
|
|
1149
1285
|
range: util_1.default.createRange(2, 32, 2, 38),
|
|
1150
1286
|
text: '"name"'
|
|
@@ -1159,8 +1295,7 @@ describe('BrsFile', () => {
|
|
|
1159
1295
|
}]);
|
|
1160
1296
|
});
|
|
1161
1297
|
it('finds function calls nested inside statements', () => {
|
|
1162
|
-
|
|
1163
|
-
program.addOrReplaceFile(`source/main.brs`, `
|
|
1298
|
+
program.setFile(`source/main.brs`, `
|
|
1164
1299
|
sub main()
|
|
1165
1300
|
if true then
|
|
1166
1301
|
DoesNotExist(1, 2)
|
|
@@ -1168,7 +1303,9 @@ describe('BrsFile', () => {
|
|
|
1168
1303
|
end sub
|
|
1169
1304
|
`);
|
|
1170
1305
|
program.validate();
|
|
1171
|
-
|
|
1306
|
+
(0, testHelpers_spec_1.expectDiagnostics)(program, [
|
|
1307
|
+
DiagnosticMessages_1.DiagnosticMessages.callToUnknownFunction('DoesNotExist', 'source')
|
|
1308
|
+
]);
|
|
1172
1309
|
});
|
|
1173
1310
|
it('finds arguments with variable values', () => {
|
|
1174
1311
|
let file = new BrsFile_1.BrsFile('absolute_path/file.brs', 'relative_path/file.brs', program);
|
|
@@ -1180,17 +1317,17 @@ describe('BrsFile', () => {
|
|
|
1180
1317
|
DoSomething(count, name, isAlive)
|
|
1181
1318
|
end function
|
|
1182
1319
|
`);
|
|
1183
|
-
chai_1.expect(file.functionCalls.length).to.equal(1);
|
|
1184
|
-
chai_1.expect(file.functionCalls[0].args[0]).deep.include({
|
|
1185
|
-
type: new
|
|
1320
|
+
(0, chai_1.expect)(file.functionCalls.length).to.equal(1);
|
|
1321
|
+
(0, chai_1.expect)(file.functionCalls[0].args[0]).deep.include({
|
|
1322
|
+
type: new IntegerType_1.IntegerType(),
|
|
1186
1323
|
text: 'count'
|
|
1187
1324
|
});
|
|
1188
|
-
chai_1.expect(file.functionCalls[0].args[1]).deep.include({
|
|
1189
|
-
type: new
|
|
1325
|
+
(0, chai_1.expect)(file.functionCalls[0].args[1]).deep.include({
|
|
1326
|
+
type: new StringType_1.StringType(),
|
|
1190
1327
|
text: 'name'
|
|
1191
1328
|
});
|
|
1192
|
-
chai_1.expect(file.functionCalls[0].args[2]).deep.include({
|
|
1193
|
-
type: new
|
|
1329
|
+
(0, chai_1.expect)(file.functionCalls[0].args[2]).deep.include({
|
|
1330
|
+
type: new BooleanType_1.BooleanType(),
|
|
1194
1331
|
text: 'isAlive'
|
|
1195
1332
|
});
|
|
1196
1333
|
});
|
|
@@ -1200,20 +1337,20 @@ describe('BrsFile', () => {
|
|
|
1200
1337
|
it('skips top-level statements', () => {
|
|
1201
1338
|
let file = new BrsFile_1.BrsFile('absolute', 'relative', program);
|
|
1202
1339
|
file.parse('name = "Bob"');
|
|
1203
|
-
chai_1.expect(file.callables.length).to.equal(0);
|
|
1340
|
+
(0, chai_1.expect)(file.callables.length).to.equal(0);
|
|
1204
1341
|
});
|
|
1205
1342
|
it('finds return type', () => {
|
|
1206
|
-
let file = program.
|
|
1343
|
+
let file = program.setFile('source/main.brs', `
|
|
1207
1344
|
function DoSomething() as string
|
|
1208
1345
|
end function
|
|
1209
1346
|
`);
|
|
1210
|
-
chai_1.expect(file.callables[0]).to.deep.include({
|
|
1347
|
+
(0, chai_1.expect)(file.callables[0]).to.deep.include({
|
|
1211
1348
|
file: file,
|
|
1212
1349
|
nameRange: vscode_languageserver_1.Range.create(1, 25, 1, 36),
|
|
1213
1350
|
name: 'DoSomething',
|
|
1214
1351
|
params: []
|
|
1215
1352
|
});
|
|
1216
|
-
chai_1.expect(file.callables[0].type.returnType).instanceof(StringType_1.StringType);
|
|
1353
|
+
(0, chai_1.expect)(file.callables[0].type.returnType).instanceof(StringType_1.StringType);
|
|
1217
1354
|
});
|
|
1218
1355
|
});
|
|
1219
1356
|
describe('function local variable handling', () => {
|
|
@@ -1223,7 +1360,7 @@ describe('BrsFile', () => {
|
|
|
1223
1360
|
name = 'bob"
|
|
1224
1361
|
end sub
|
|
1225
1362
|
`);
|
|
1226
|
-
chai_1.expect(file.parser.references.functionStatements[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
|
|
1363
|
+
(0, chai_1.expect)(file.parser.references.functionStatements[0].range).to.eql(vscode_languageserver_1.Range.create(1, 16, 3, 23));
|
|
1227
1364
|
});
|
|
1228
1365
|
it('creates scopes for parent and child functions', () => {
|
|
1229
1366
|
file.parse(`
|
|
@@ -1237,7 +1374,7 @@ describe('BrsFile', () => {
|
|
|
1237
1374
|
end sub)
|
|
1238
1375
|
end sub
|
|
1239
1376
|
`);
|
|
1240
|
-
chai_1.expect(file.parser.references.functionExpressions).to.be.length(3);
|
|
1377
|
+
(0, chai_1.expect)(file.parser.references.functionExpressions).to.be.length(3);
|
|
1241
1378
|
});
|
|
1242
1379
|
it('finds variables declared in function expressions', () => {
|
|
1243
1380
|
file.parse(`
|
|
@@ -1251,13 +1388,13 @@ describe('BrsFile', () => {
|
|
|
1251
1388
|
end sub)
|
|
1252
1389
|
end sub
|
|
1253
1390
|
`);
|
|
1254
|
-
testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1255
|
-
['sayHi', new
|
|
1391
|
+
(0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1392
|
+
['sayHi', new TypedFunctionType_1.TypedFunctionType(new VoidType_1.VoidType(), true), util_1.default.createRange(2, 20, 2, 25)]
|
|
1256
1393
|
]);
|
|
1257
|
-
testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[1].symbolTable, [
|
|
1394
|
+
(0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[1].symbolTable, [
|
|
1258
1395
|
['age', new IntegerType_1.IntegerType(), util_1.default.createRange(3, 24, 3, 27)]
|
|
1259
1396
|
]);
|
|
1260
|
-
testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[2].symbolTable, [
|
|
1397
|
+
(0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[2].symbolTable, [
|
|
1261
1398
|
['name', new StringType_1.StringType(), util_1.default.createRange(7, 24, 7, 28)]
|
|
1262
1399
|
]);
|
|
1263
1400
|
});
|
|
@@ -1269,12 +1406,12 @@ describe('BrsFile', () => {
|
|
|
1269
1406
|
end if
|
|
1270
1407
|
end sub
|
|
1271
1408
|
`);
|
|
1272
|
-
testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1409
|
+
(0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1273
1410
|
['theLength', new IntegerType_1.IntegerType(), util_1.default.createRange(3, 24, 3, 33)]
|
|
1274
1411
|
]);
|
|
1275
1412
|
});
|
|
1276
1413
|
it('finds value from global return', () => {
|
|
1277
|
-
let file = program.
|
|
1414
|
+
let file = program.setFile('source/main.brs', `
|
|
1278
1415
|
sub Main()
|
|
1279
1416
|
myName = GetName()
|
|
1280
1417
|
end sub
|
|
@@ -1283,20 +1420,20 @@ describe('BrsFile', () => {
|
|
|
1283
1420
|
return "bob"
|
|
1284
1421
|
end function
|
|
1285
1422
|
`);
|
|
1286
|
-
testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1423
|
+
(0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1287
1424
|
['myName', new StringType_1.StringType(), util_1.default.createRange(2, 19, 2, 25)]
|
|
1288
1425
|
]);
|
|
1289
1426
|
});
|
|
1290
1427
|
it('finds variable type from other variable', () => {
|
|
1291
1428
|
file.parse(`
|
|
1292
1429
|
sub Main()
|
|
1293
|
-
|
|
1294
|
-
|
|
1430
|
+
name = "bob"
|
|
1431
|
+
nameCopy = name
|
|
1295
1432
|
end sub
|
|
1296
1433
|
`);
|
|
1297
|
-
testHelpers_spec_1.expectSymbolTableEquals(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1298
|
-
['name', new StringType_1.StringType(), util_1.default.createRange(2,
|
|
1299
|
-
['nameCopy', new StringType_1.StringType(), util_1.default.createRange(3,
|
|
1434
|
+
(0, testHelpers_spec_1.expectSymbolTableEquals)(file.parser.references.functionExpressions[0].symbolTable, [
|
|
1435
|
+
['name', new StringType_1.StringType(), util_1.default.createRange(2, 20, 2, 24)],
|
|
1436
|
+
['nameCopy', new StringType_1.StringType(), util_1.default.createRange(3, 20, 3, 28)]
|
|
1300
1437
|
]);
|
|
1301
1438
|
});
|
|
1302
1439
|
it('sets proper range for functions', () => {
|
|
@@ -1307,8 +1444,7 @@ describe('BrsFile', () => {
|
|
|
1307
1444
|
end function
|
|
1308
1445
|
end sub
|
|
1309
1446
|
`);
|
|
1310
|
-
chai_1.expect(file.parser.references.functionExpressions).to.
|
|
1311
|
-
chai_1.expect(file.parser.references.functionExpressions.map(x => x.range)).to.eql([
|
|
1447
|
+
(0, chai_1.expect)(file.parser.references.functionExpressions.map(x => x.range)).to.eql([
|
|
1312
1448
|
util_1.default.createRange(1, 16, 5, 23),
|
|
1313
1449
|
util_1.default.createRange(2, 30, 4, 32)
|
|
1314
1450
|
]);
|
|
@@ -1316,37 +1452,37 @@ describe('BrsFile', () => {
|
|
|
1316
1452
|
});
|
|
1317
1453
|
describe('getHover', () => {
|
|
1318
1454
|
it('works for param types', () => {
|
|
1319
|
-
let file = program.
|
|
1455
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
1320
1456
|
sub DoSomething(name as string)
|
|
1321
1457
|
name = 1
|
|
1322
|
-
sayMyName = function(name as string)
|
|
1458
|
+
sayMyName = function (name as string)
|
|
1323
1459
|
end function
|
|
1324
1460
|
end sub
|
|
1325
1461
|
`);
|
|
1326
1462
|
//hover over the `name = 1` line
|
|
1327
1463
|
let hover = file.getHover(vscode_languageserver_1.Position.create(2, 24));
|
|
1328
|
-
chai_1.expect(hover).to.exist;
|
|
1329
|
-
chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 24));
|
|
1464
|
+
(0, chai_1.expect)(hover).to.exist;
|
|
1465
|
+
(0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 24));
|
|
1330
1466
|
//hover over the `name` parameter declaration
|
|
1331
1467
|
hover = file.getHover(vscode_languageserver_1.Position.create(1, 34));
|
|
1332
|
-
chai_1.expect(hover).to.exist;
|
|
1333
|
-
chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 32, 1, 36));
|
|
1468
|
+
(0, chai_1.expect)(hover).to.exist;
|
|
1469
|
+
(0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 32, 1, 36));
|
|
1334
1470
|
});
|
|
1335
1471
|
//ignore this for now...it's not a huge deal
|
|
1336
1472
|
it('does not match on keywords or data types', () => {
|
|
1337
|
-
let file = program.
|
|
1473
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
1338
1474
|
sub Main(name as string)
|
|
1339
1475
|
end sub
|
|
1340
|
-
sub as()
|
|
1476
|
+
sub as ()
|
|
1341
1477
|
end sub
|
|
1342
1478
|
`);
|
|
1343
|
-
//hover over the `as`
|
|
1344
|
-
chai_1.expect(file.getHover(vscode_languageserver_1.Position.create(1, 31))).not.to.exist;
|
|
1479
|
+
//hover over the `as `
|
|
1480
|
+
(0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 31))).not.to.exist;
|
|
1345
1481
|
//hover over the `string`
|
|
1346
|
-
chai_1.expect(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
|
|
1482
|
+
(0, chai_1.expect)(file.getHover(vscode_languageserver_1.Position.create(1, 36))).not.to.exist;
|
|
1347
1483
|
});
|
|
1348
1484
|
it('finds declared function', () => {
|
|
1349
|
-
let file = program.
|
|
1485
|
+
let file = program.setFile({ src: `${rootDir} /source/main.brs`, dest: 'source/main.brs' }, `
|
|
1350
1486
|
function Main(count = 1)
|
|
1351
1487
|
firstName = "bob"
|
|
1352
1488
|
age = 21
|
|
@@ -1354,12 +1490,16 @@ describe('BrsFile', () => {
|
|
|
1354
1490
|
end function
|
|
1355
1491
|
`);
|
|
1356
1492
|
let hover = file.getHover(vscode_languageserver_1.Position.create(1, 28));
|
|
1357
|
-
chai_1.expect(hover).to.exist;
|
|
1358
|
-
chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
|
|
1359
|
-
chai_1.expect(hover.contents).to.equal(
|
|
1493
|
+
(0, chai_1.expect)(hover).to.exist;
|
|
1494
|
+
(0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(1, 25, 1, 29));
|
|
1495
|
+
(0, chai_1.expect)(hover.contents).to.equal([
|
|
1496
|
+
'```brightscript',
|
|
1497
|
+
'function Main(count? as integer) as dynamic',
|
|
1498
|
+
'```'
|
|
1499
|
+
].join('\n'));
|
|
1360
1500
|
});
|
|
1361
1501
|
it('finds variable function hover in same scope', () => {
|
|
1362
|
-
let file = program.
|
|
1502
|
+
let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
1363
1503
|
sub Main()
|
|
1364
1504
|
sayMyName = sub(name as string)
|
|
1365
1505
|
end sub
|
|
@@ -1368,11 +1508,39 @@ describe('BrsFile', () => {
|
|
|
1368
1508
|
end sub
|
|
1369
1509
|
`);
|
|
1370
1510
|
let hover = file.getHover(vscode_languageserver_1.Position.create(5, 24));
|
|
1371
|
-
chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
|
|
1372
|
-
chai_1.expect(hover.contents).to.equal(
|
|
1511
|
+
(0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(5, 20, 5, 29));
|
|
1512
|
+
(0, chai_1.expect)(hover.contents).to.equal([
|
|
1513
|
+
'```brightscript',
|
|
1514
|
+
'sub (name as string) as void',
|
|
1515
|
+
'```'
|
|
1516
|
+
].join('\n'));
|
|
1517
|
+
});
|
|
1518
|
+
it('does not crash when hovering on built-in functions', async () => {
|
|
1519
|
+
let file = program.setFile('source/main.brs', `
|
|
1520
|
+
function doUcase(text)
|
|
1521
|
+
return ucase(text)
|
|
1522
|
+
end function
|
|
1523
|
+
`);
|
|
1524
|
+
(0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 30))).contents).to.equal([
|
|
1525
|
+
'```brightscript',
|
|
1526
|
+
'function UCase(s as string) as string',
|
|
1527
|
+
'```'
|
|
1528
|
+
].join('\n'));
|
|
1529
|
+
});
|
|
1530
|
+
it('does not crash when hovering on object method call', async () => {
|
|
1531
|
+
let file = program.setFile('source/main.brs', `
|
|
1532
|
+
function getInstr(url, text)
|
|
1533
|
+
return url.instr(text)
|
|
1534
|
+
end function
|
|
1535
|
+
`);
|
|
1536
|
+
(0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(2, 35))).contents).to.equal([
|
|
1537
|
+
'```brightscript',
|
|
1538
|
+
'instr as dynamic',
|
|
1539
|
+
'```'
|
|
1540
|
+
].join('\n'));
|
|
1373
1541
|
});
|
|
1374
1542
|
it('finds function hover in file scope', () => {
|
|
1375
|
-
let file = program.
|
|
1543
|
+
let file = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
1376
1544
|
sub Main()
|
|
1377
1545
|
sayMyName()
|
|
1378
1546
|
end sub
|
|
@@ -1382,82 +1550,132 @@ describe('BrsFile', () => {
|
|
|
1382
1550
|
end sub
|
|
1383
1551
|
`);
|
|
1384
1552
|
let hover = file.getHover(vscode_languageserver_1.Position.create(2, 25));
|
|
1385
|
-
chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
|
|
1386
|
-
chai_1.expect(hover.contents).to.equal(
|
|
1553
|
+
(0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
|
|
1554
|
+
(0, chai_1.expect)(hover.contents).to.equal([
|
|
1555
|
+
'```brightscript',
|
|
1556
|
+
'sub sayMyName() as void',
|
|
1557
|
+
'```'
|
|
1558
|
+
].join('\n'));
|
|
1387
1559
|
});
|
|
1388
1560
|
it('finds function hover in scope', () => {
|
|
1389
1561
|
let rootDir = process.cwd();
|
|
1390
1562
|
program = new Program_1.Program({
|
|
1391
1563
|
rootDir: rootDir
|
|
1392
1564
|
});
|
|
1393
|
-
let mainFile = program.
|
|
1565
|
+
let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
1394
1566
|
sub Main()
|
|
1395
1567
|
sayMyName()
|
|
1396
1568
|
end sub
|
|
1397
1569
|
`);
|
|
1398
|
-
program.
|
|
1570
|
+
program.setFile({ src: `${rootDir}/source/lib.brs`, dest: 'source/lib.brs' }, `
|
|
1399
1571
|
sub sayMyName(name as string)
|
|
1400
1572
|
|
|
1401
1573
|
end sub
|
|
1402
1574
|
`);
|
|
1403
1575
|
let hover = mainFile.getHover(vscode_languageserver_1.Position.create(2, 25));
|
|
1404
|
-
chai_1.expect(hover).to.exist;
|
|
1405
|
-
chai_1.expect(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
|
|
1406
|
-
chai_1.expect(hover.contents).to.equal(
|
|
1576
|
+
(0, chai_1.expect)(hover).to.exist;
|
|
1577
|
+
(0, chai_1.expect)(hover.range).to.eql(vscode_languageserver_1.Range.create(2, 20, 2, 29));
|
|
1578
|
+
(0, chai_1.expect)(hover.contents).to.equal([
|
|
1579
|
+
'```brightscript',
|
|
1580
|
+
'sub sayMyName(name as string) as void',
|
|
1581
|
+
'```'
|
|
1582
|
+
].join('\n'));
|
|
1583
|
+
});
|
|
1584
|
+
it('includes markdown comments in hover.', async () => {
|
|
1585
|
+
let rootDir = process.cwd();
|
|
1586
|
+
program = new Program_1.Program({
|
|
1587
|
+
rootDir: rootDir
|
|
1588
|
+
});
|
|
1589
|
+
const file = program.setFile('source/lib.brs', `
|
|
1590
|
+
'
|
|
1591
|
+
' The main function
|
|
1592
|
+
'
|
|
1593
|
+
sub main()
|
|
1594
|
+
log("hello")
|
|
1595
|
+
end sub
|
|
1596
|
+
|
|
1597
|
+
'
|
|
1598
|
+
' Prints a message to the log.
|
|
1599
|
+
' Works with *markdown* **content**
|
|
1600
|
+
'
|
|
1601
|
+
sub log(message as string)
|
|
1602
|
+
print message
|
|
1603
|
+
end sub
|
|
1604
|
+
`);
|
|
1605
|
+
//hover over log("hello")
|
|
1606
|
+
(0, chai_1.expect)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(5, 22))).contents).to.equal([
|
|
1607
|
+
'```brightscript',
|
|
1608
|
+
'sub log(message as string) as void',
|
|
1609
|
+
'```',
|
|
1610
|
+
'***',
|
|
1611
|
+
'',
|
|
1612
|
+
' Prints a message to the log.',
|
|
1613
|
+
' Works with *markdown* **content**',
|
|
1614
|
+
''
|
|
1615
|
+
].join('\n'));
|
|
1616
|
+
//hover over sub ma|in()
|
|
1617
|
+
(0, chai_1.expect)((0, testHelpers_spec_1.trim)((await program.getHover(file.srcPath, vscode_languageserver_1.Position.create(4, 22))).contents.toString())).to.equal((0, testHelpers_spec_1.trim) `
|
|
1618
|
+
\`\`\`brightscript
|
|
1619
|
+
sub main() as void
|
|
1620
|
+
\`\`\`
|
|
1621
|
+
***
|
|
1622
|
+
|
|
1623
|
+
The main function
|
|
1624
|
+
`);
|
|
1407
1625
|
});
|
|
1408
1626
|
it('handles mixed case `then` partions of conditionals', () => {
|
|
1409
|
-
let mainFile = program.
|
|
1627
|
+
let mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
1410
1628
|
sub Main()
|
|
1411
1629
|
if true then
|
|
1412
1630
|
print "works"
|
|
1413
1631
|
end if
|
|
1414
1632
|
end sub
|
|
1415
1633
|
`);
|
|
1416
|
-
|
|
1417
|
-
mainFile = program.
|
|
1634
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
|
|
1635
|
+
mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
1418
1636
|
sub Main()
|
|
1419
1637
|
if true Then
|
|
1420
1638
|
print "works"
|
|
1421
1639
|
end if
|
|
1422
1640
|
end sub
|
|
1423
1641
|
`);
|
|
1424
|
-
|
|
1425
|
-
mainFile = program.
|
|
1642
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
|
|
1643
|
+
mainFile = program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
1426
1644
|
sub Main()
|
|
1427
1645
|
if true THEN
|
|
1428
1646
|
print "works"
|
|
1429
1647
|
end if
|
|
1430
1648
|
end sub
|
|
1431
1649
|
`);
|
|
1432
|
-
|
|
1650
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(mainFile);
|
|
1433
1651
|
});
|
|
1434
1652
|
it('displays the context from multiple scopes', () => {
|
|
1435
|
-
let commonFile = program.
|
|
1653
|
+
let commonFile = program.setFile('source/common.brs', `
|
|
1436
1654
|
sub displayPi()
|
|
1437
1655
|
pi = getPi()
|
|
1438
1656
|
print pi
|
|
1439
1657
|
end sub
|
|
1440
1658
|
`);
|
|
1441
|
-
let scope1File = program.
|
|
1659
|
+
let scope1File = program.setFile('components/comp1/scope1.brs', `
|
|
1442
1660
|
function getPi() as string
|
|
1443
1661
|
return "apple"
|
|
1444
1662
|
end function
|
|
1445
1663
|
`);
|
|
1446
|
-
chai_1.expect(scope1File.getDiagnostics()).to.be.lengthOf(0);
|
|
1447
|
-
program.
|
|
1664
|
+
(0, chai_1.expect)(scope1File.getDiagnostics()).to.be.lengthOf(0);
|
|
1665
|
+
program.setFile('components/comp1/comp1.xml', (0, testHelpers_spec_1.trim) `
|
|
1448
1666
|
<?xml version="1.0" encoding="utf-8" ?>
|
|
1449
1667
|
<component name="Component1" extends="Group">
|
|
1450
1668
|
<script type="text/brightscript" uri="scope1.brs" />
|
|
1451
1669
|
<script type="text/brightscript" uri="pkg:/source/common.brs" />
|
|
1452
1670
|
</component>
|
|
1453
1671
|
`);
|
|
1454
|
-
let scope2File = program.
|
|
1672
|
+
let scope2File = program.setFile('components/comp2/scope2.brs', `
|
|
1455
1673
|
function getPi() as float
|
|
1456
1674
|
return 3.14
|
|
1457
1675
|
end function
|
|
1458
1676
|
`);
|
|
1459
|
-
chai_1.expect(scope2File.getDiagnostics()).to.be.lengthOf(0);
|
|
1460
|
-
program.
|
|
1677
|
+
(0, chai_1.expect)(scope2File.getDiagnostics()).to.be.lengthOf(0);
|
|
1678
|
+
program.setFile('components/comp2/comp2.xml', (0, testHelpers_spec_1.trim) `
|
|
1461
1679
|
<?xml version="1.0" encoding="utf-8" ?>
|
|
1462
1680
|
<component name="Component2" extends="Group">
|
|
1463
1681
|
<script type="text/brightscript" uri="scope2.brs" />
|
|
@@ -1466,15 +1684,65 @@ describe('BrsFile', () => {
|
|
|
1466
1684
|
`);
|
|
1467
1685
|
program.validate();
|
|
1468
1686
|
let funcCallHover = commonFile.getHover(vscode_languageserver_1.Position.create(2, 27));
|
|
1469
|
-
chai_1.expect(funcCallHover).to.
|
|
1470
|
-
|
|
1687
|
+
(0, chai_1.expect)(funcCallHover === null || funcCallHover === void 0 ? void 0 : funcCallHover.contents).to.equal([
|
|
1688
|
+
'```brightscript',
|
|
1689
|
+
'function getPi() as string | function getPi() as float | getPi as uninitialized',
|
|
1690
|
+
'```'
|
|
1691
|
+
].join('\n'));
|
|
1471
1692
|
let variableHover = commonFile.getHover(vscode_languageserver_1.Position.create(3, 27));
|
|
1472
|
-
chai_1.expect(variableHover).to.
|
|
1473
|
-
|
|
1693
|
+
(0, chai_1.expect)(variableHover === null || variableHover === void 0 ? void 0 : variableHover.contents).to.equal([
|
|
1694
|
+
'```brightscript',
|
|
1695
|
+
'pi as string | pi as float | pi as uninitialized',
|
|
1696
|
+
'```'
|
|
1697
|
+
].join('\n'));
|
|
1698
|
+
});
|
|
1699
|
+
it('finds function with custom types as parameters and return types', () => {
|
|
1700
|
+
let file = program.setFile('source/main.bs', `
|
|
1701
|
+
sub main()
|
|
1702
|
+
k = new MyKlass()
|
|
1703
|
+
processMyKlass(k)
|
|
1704
|
+
end sub
|
|
1705
|
+
|
|
1706
|
+
function processMyKlass(data as MyKlass) as MyKlass
|
|
1707
|
+
return data
|
|
1708
|
+
end function
|
|
1709
|
+
|
|
1710
|
+
class MyKlass
|
|
1711
|
+
end class
|
|
1712
|
+
`);
|
|
1713
|
+
let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
|
|
1714
|
+
(0, chai_1.expect)(hover).to.exist;
|
|
1715
|
+
(0, chai_1.expect)(hover.contents).to.equal([
|
|
1716
|
+
'```brightscript',
|
|
1717
|
+
'function processMyKlass(data as MyKlass) as MyKlass',
|
|
1718
|
+
'```'
|
|
1719
|
+
].join('\n'));
|
|
1720
|
+
});
|
|
1721
|
+
it('finds function with arrays as parameters and return types', () => {
|
|
1722
|
+
let file = program.setFile('source/main.bs', `
|
|
1723
|
+
sub main()
|
|
1724
|
+
k = new MyKlass()
|
|
1725
|
+
processData([k])
|
|
1726
|
+
end sub
|
|
1727
|
+
|
|
1728
|
+
function processData(data as MyKlass[]) as MyKlass[]
|
|
1729
|
+
return data
|
|
1730
|
+
end function
|
|
1731
|
+
|
|
1732
|
+
class MyKlass
|
|
1733
|
+
end class
|
|
1734
|
+
`);
|
|
1735
|
+
let hover = file.getHover(vscode_languageserver_1.Position.create(3, 29));
|
|
1736
|
+
(0, chai_1.expect)(hover).to.exist;
|
|
1737
|
+
(0, chai_1.expect)(hover.contents).to.equal([
|
|
1738
|
+
'```brightscript',
|
|
1739
|
+
'function processData(data as MyKlass[]) as MyKlass[]',
|
|
1740
|
+
'```'
|
|
1741
|
+
].join('\n'));
|
|
1474
1742
|
});
|
|
1475
1743
|
});
|
|
1476
1744
|
it('does not throw when encountering incomplete import statement', () => {
|
|
1477
|
-
program.
|
|
1745
|
+
program.setFile({ src: `${rootDir}/source/main.brs`, dest: 'source/main.brs' }, `
|
|
1478
1746
|
import
|
|
1479
1747
|
sub main()
|
|
1480
1748
|
end sub
|
|
@@ -1483,6 +1751,135 @@ describe('BrsFile', () => {
|
|
|
1483
1751
|
//this test will throw an exception if something went wrong
|
|
1484
1752
|
});
|
|
1485
1753
|
describe('transpile', () => {
|
|
1754
|
+
it('excludes trailing commas in array literals', () => {
|
|
1755
|
+
testTranspile(`
|
|
1756
|
+
sub main()
|
|
1757
|
+
arr = [
|
|
1758
|
+
1,
|
|
1759
|
+
2,
|
|
1760
|
+
3
|
|
1761
|
+
]
|
|
1762
|
+
obj = {
|
|
1763
|
+
one: 1,
|
|
1764
|
+
two: 2,
|
|
1765
|
+
three: 3
|
|
1766
|
+
}
|
|
1767
|
+
end sub
|
|
1768
|
+
`, `
|
|
1769
|
+
sub main()
|
|
1770
|
+
arr = [
|
|
1771
|
+
1
|
|
1772
|
+
2
|
|
1773
|
+
3
|
|
1774
|
+
]
|
|
1775
|
+
obj = {
|
|
1776
|
+
one: 1
|
|
1777
|
+
two: 2
|
|
1778
|
+
three: 3
|
|
1779
|
+
}
|
|
1780
|
+
end sub
|
|
1781
|
+
`);
|
|
1782
|
+
});
|
|
1783
|
+
it('transpiles if statement keywords as provided', () => {
|
|
1784
|
+
const code = `
|
|
1785
|
+
If True Then
|
|
1786
|
+
Print True
|
|
1787
|
+
Else If True Then
|
|
1788
|
+
print True
|
|
1789
|
+
Else If False Then
|
|
1790
|
+
Print False
|
|
1791
|
+
Else
|
|
1792
|
+
Print False
|
|
1793
|
+
End If
|
|
1794
|
+
`;
|
|
1795
|
+
testTranspile(code);
|
|
1796
|
+
testTranspile(code.toLowerCase());
|
|
1797
|
+
testTranspile(code.toUpperCase());
|
|
1798
|
+
});
|
|
1799
|
+
it('does not transpile `then` tokens', () => {
|
|
1800
|
+
const code = `
|
|
1801
|
+
if true
|
|
1802
|
+
print true
|
|
1803
|
+
else if true
|
|
1804
|
+
print false
|
|
1805
|
+
end if
|
|
1806
|
+
`;
|
|
1807
|
+
testTranspile(code);
|
|
1808
|
+
});
|
|
1809
|
+
it('honors spacing between multi-word tokens', () => {
|
|
1810
|
+
testTranspile(`
|
|
1811
|
+
if true
|
|
1812
|
+
print true
|
|
1813
|
+
elseif true
|
|
1814
|
+
print false
|
|
1815
|
+
endif
|
|
1816
|
+
`);
|
|
1817
|
+
});
|
|
1818
|
+
it('handles when only some of the statements have `then`', () => {
|
|
1819
|
+
testTranspile(`
|
|
1820
|
+
if true
|
|
1821
|
+
else if true then
|
|
1822
|
+
else if true
|
|
1823
|
+
else if true then
|
|
1824
|
+
if true then
|
|
1825
|
+
return true
|
|
1826
|
+
end if
|
|
1827
|
+
end if
|
|
1828
|
+
`);
|
|
1829
|
+
});
|
|
1830
|
+
it('retains casing of parameter types', () => {
|
|
1831
|
+
function test(type) {
|
|
1832
|
+
testTranspile(`
|
|
1833
|
+
sub one(a as ${type}, b as ${type.toUpperCase()}, c as ${type.toLowerCase()})
|
|
1834
|
+
end sub
|
|
1835
|
+
`);
|
|
1836
|
+
}
|
|
1837
|
+
test('Boolean');
|
|
1838
|
+
test('Double');
|
|
1839
|
+
test('Dynamic');
|
|
1840
|
+
test('Float');
|
|
1841
|
+
test('Integer');
|
|
1842
|
+
test('LongInteger');
|
|
1843
|
+
test('Object');
|
|
1844
|
+
test('String');
|
|
1845
|
+
});
|
|
1846
|
+
it('retains casing of return types', () => {
|
|
1847
|
+
function test(type) {
|
|
1848
|
+
testTranspile(`
|
|
1849
|
+
sub one() as ${type}
|
|
1850
|
+
end sub
|
|
1851
|
+
|
|
1852
|
+
sub two() as ${type.toLowerCase()}
|
|
1853
|
+
end sub
|
|
1854
|
+
|
|
1855
|
+
sub three() as ${type.toUpperCase()}
|
|
1856
|
+
end sub
|
|
1857
|
+
`);
|
|
1858
|
+
}
|
|
1859
|
+
test('Boolean');
|
|
1860
|
+
test('Double');
|
|
1861
|
+
test('Dynamic');
|
|
1862
|
+
test('Float');
|
|
1863
|
+
test('Integer');
|
|
1864
|
+
test('LongInteger');
|
|
1865
|
+
test('Object');
|
|
1866
|
+
test('String');
|
|
1867
|
+
test('Void');
|
|
1868
|
+
});
|
|
1869
|
+
it('retains casing of literal types', () => {
|
|
1870
|
+
function test(type) {
|
|
1871
|
+
testTranspile(`
|
|
1872
|
+
sub main()
|
|
1873
|
+
thing = ${type}
|
|
1874
|
+
thing = ${type.toLowerCase()}
|
|
1875
|
+
thing = ${type.toUpperCase()}
|
|
1876
|
+
end sub
|
|
1877
|
+
`);
|
|
1878
|
+
}
|
|
1879
|
+
test('Invalid');
|
|
1880
|
+
test('True');
|
|
1881
|
+
test('False');
|
|
1882
|
+
});
|
|
1486
1883
|
describe('throwStatement', () => {
|
|
1487
1884
|
it('transpiles properly', () => {
|
|
1488
1885
|
testTranspile(`
|
|
@@ -1621,7 +2018,7 @@ describe('BrsFile', () => {
|
|
|
1621
2018
|
`, `
|
|
1622
2019
|
function Vertibrates_Birds_GetAllBirds()
|
|
1623
2020
|
return [
|
|
1624
|
-
Vertibrates_Birds_GetDuck()
|
|
2021
|
+
Vertibrates_Birds_GetDuck()
|
|
1625
2022
|
Vertibrates_Birds_GetGoose()
|
|
1626
2023
|
]
|
|
1627
2024
|
end function
|
|
@@ -1731,29 +2128,6 @@ describe('BrsFile', () => {
|
|
|
1731
2128
|
end sub
|
|
1732
2129
|
`, null, 'trim');
|
|
1733
2130
|
});
|
|
1734
|
-
it('adds `then` when missing', () => {
|
|
1735
|
-
testTranspile(`
|
|
1736
|
-
sub a()
|
|
1737
|
-
if true
|
|
1738
|
-
print "true"
|
|
1739
|
-
else if true
|
|
1740
|
-
print "true"
|
|
1741
|
-
else
|
|
1742
|
-
print "true"
|
|
1743
|
-
end if
|
|
1744
|
-
end sub
|
|
1745
|
-
`, `
|
|
1746
|
-
sub a()
|
|
1747
|
-
if true then
|
|
1748
|
-
print "true"
|
|
1749
|
-
else if true then
|
|
1750
|
-
print "true"
|
|
1751
|
-
else
|
|
1752
|
-
print "true"
|
|
1753
|
-
end if
|
|
1754
|
-
end sub
|
|
1755
|
-
`, 'trim');
|
|
1756
|
-
});
|
|
1757
2131
|
it('does not add leading or trailing newlines', () => {
|
|
1758
2132
|
testTranspile(`function abc()\nend function`, undefined, 'none');
|
|
1759
2133
|
});
|
|
@@ -1770,18 +2144,18 @@ describe('BrsFile', () => {
|
|
|
1770
2144
|
return consumer.generatedPositionFor({
|
|
1771
2145
|
line: 3,
|
|
1772
2146
|
column: 0,
|
|
1773
|
-
source: util_1.standardizePath `${rootDir}/source/main.bs`,
|
|
2147
|
+
source: (0, util_1.standardizePath) `${rootDir}/source/main.bs`,
|
|
1774
2148
|
bias: source_map_1.SourceMapConsumer.LEAST_UPPER_BOUND
|
|
1775
2149
|
});
|
|
1776
2150
|
});
|
|
1777
|
-
chai_1.expect(location.line).to.eql(2);
|
|
1778
|
-
chai_1.expect(location.column).eql(4);
|
|
2151
|
+
(0, chai_1.expect)(location.line).to.eql(2);
|
|
2152
|
+
(0, chai_1.expect)(location.column).eql(4);
|
|
1779
2153
|
});
|
|
1780
2154
|
it('computes correct locations for sourcemap', async () => {
|
|
1781
2155
|
let source = `function abc(name)\n firstName = name\nend function`;
|
|
1782
|
-
let tokens =
|
|
2156
|
+
let tokens = Lexer_1.Lexer.scan(source).tokens
|
|
1783
2157
|
//remove newlines and EOF
|
|
1784
|
-
.filter(x => x.kind !==
|
|
2158
|
+
.filter(x => x.kind !== TokenKind_1.TokenKind.Eof && x.kind !== TokenKind_1.TokenKind.Newline);
|
|
1785
2159
|
program.options.sourceMap = true;
|
|
1786
2160
|
let result = testTranspile(source, source, 'none');
|
|
1787
2161
|
//load the source map
|
|
@@ -1803,7 +2177,7 @@ describe('BrsFile', () => {
|
|
|
1803
2177
|
originalPosition.line - 1, originalPosition.column)
|
|
1804
2178
|
};
|
|
1805
2179
|
});
|
|
1806
|
-
chai_1.expect(sourcemapResult).to.eql(tokenResult);
|
|
2180
|
+
(0, chai_1.expect)(sourcemapResult).to.eql(tokenResult);
|
|
1807
2181
|
});
|
|
1808
2182
|
});
|
|
1809
2183
|
it('handles empty if block', () => {
|
|
@@ -1890,20 +2264,20 @@ describe('BrsFile', () => {
|
|
|
1890
2264
|
testTranspile(`
|
|
1891
2265
|
sub doSomething()
|
|
1892
2266
|
person = {
|
|
1893
|
-
age: 12
|
|
2267
|
+
age: 12 'comment
|
|
1894
2268
|
name: "child"
|
|
1895
2269
|
}
|
|
1896
2270
|
person = {
|
|
1897
|
-
age: 12
|
|
2271
|
+
age: 12 'comment
|
|
1898
2272
|
name: "child" 'comment
|
|
1899
2273
|
}
|
|
1900
2274
|
person = {
|
|
1901
|
-
age: 12
|
|
2275
|
+
age: 12 'comment
|
|
1902
2276
|
name: "child"
|
|
1903
2277
|
'comment
|
|
1904
2278
|
}
|
|
1905
2279
|
person = {
|
|
1906
|
-
age: 12
|
|
2280
|
+
age: 12 'comment
|
|
1907
2281
|
name: "child" 'comment
|
|
1908
2282
|
'comment
|
|
1909
2283
|
}
|
|
@@ -1918,8 +2292,8 @@ describe('BrsFile', () => {
|
|
|
1918
2292
|
'a function that does something
|
|
1919
2293
|
function doSomething(age as integer, name = "bob") 'comment
|
|
1920
2294
|
person = { 'comment
|
|
1921
|
-
name: "parent"
|
|
1922
|
-
"age": 12
|
|
2295
|
+
name: "parent" 'comment
|
|
2296
|
+
"age": 12
|
|
1923
2297
|
'comment as whole line
|
|
1924
2298
|
child: { 'comment
|
|
1925
2299
|
name: "child" 'comment
|
|
@@ -1955,8 +2329,8 @@ describe('BrsFile', () => {
|
|
|
1955
2329
|
stop 'comment
|
|
1956
2330
|
indexes = [ 'comment
|
|
1957
2331
|
'comment on its own line
|
|
1958
|
-
1
|
|
1959
|
-
2
|
|
2332
|
+
1 'comment
|
|
2333
|
+
2 'comment
|
|
1960
2334
|
3 'comment
|
|
1961
2335
|
] 'comment
|
|
1962
2336
|
firstIndex = indexes[0] 'comment
|
|
@@ -1997,25 +2371,25 @@ describe('BrsFile', () => {
|
|
|
1997
2371
|
`);
|
|
1998
2372
|
});
|
|
1999
2373
|
it('simple mapped files include a reference to the source map', () => {
|
|
2000
|
-
let file = program.
|
|
2374
|
+
let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
|
|
2001
2375
|
sub logInfo()
|
|
2002
2376
|
end sub
|
|
2003
2377
|
`);
|
|
2004
2378
|
file.needsTranspiled = false;
|
|
2005
2379
|
const { code } = file.transpile();
|
|
2006
|
-
chai_1.expect(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
|
|
2380
|
+
(0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
|
|
2007
2381
|
});
|
|
2008
2382
|
it('AST generated files include a reference to the source map', () => {
|
|
2009
|
-
let file = program.
|
|
2383
|
+
let file = program.setFile('source/logger.brs', (0, testHelpers_spec_1.trim) `
|
|
2010
2384
|
sub logInfo()
|
|
2011
2385
|
end sub
|
|
2012
2386
|
`);
|
|
2013
2387
|
file.needsTranspiled = true;
|
|
2014
2388
|
const { code } = file.transpile();
|
|
2015
|
-
chai_1.expect(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
|
|
2389
|
+
(0, chai_1.expect)(code.endsWith(`'//# sourceMappingURL=./logger.brs.map`)).to.be.true;
|
|
2016
2390
|
});
|
|
2017
2391
|
it('replaces custom types in parameter types and return types', () => {
|
|
2018
|
-
program.
|
|
2392
|
+
program.setFile('source/SomeKlass.bs', `
|
|
2019
2393
|
class SomeKlass
|
|
2020
2394
|
end class
|
|
2021
2395
|
`);
|
|
@@ -2039,14 +2413,13 @@ describe('BrsFile', () => {
|
|
|
2039
2413
|
describe('callfunc operator', () => {
|
|
2040
2414
|
describe('transpile', () => {
|
|
2041
2415
|
it('does not produce diagnostics', () => {
|
|
2042
|
-
|
|
2043
|
-
program.addOrReplaceFile('source/main.bs', `
|
|
2416
|
+
program.setFile('source/main.bs', `
|
|
2044
2417
|
sub main()
|
|
2045
2418
|
someObject@.someFunction(paramObject.value)
|
|
2046
2419
|
end sub
|
|
2047
2420
|
`);
|
|
2048
2421
|
program.validate();
|
|
2049
|
-
|
|
2422
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2050
2423
|
});
|
|
2051
2424
|
it('sets invalid on empty callfunc', () => {
|
|
2052
2425
|
testTranspile(`
|
|
@@ -2086,116 +2459,116 @@ describe('BrsFile', () => {
|
|
|
2086
2459
|
name: 'transform callback',
|
|
2087
2460
|
afterFileParse: onParsed
|
|
2088
2461
|
});
|
|
2089
|
-
file = program.
|
|
2462
|
+
file = program.setFile({ src: `absolute_path/file${ext}`, dest: `relative_path/file${ext}` }, `
|
|
2090
2463
|
sub Sum()
|
|
2091
2464
|
print "hello world"
|
|
2092
2465
|
end sub
|
|
2093
2466
|
`);
|
|
2094
|
-
chai_1.expect(file.extension).to.equal(ext);
|
|
2467
|
+
(0, chai_1.expect)(file.extension).to.equal(ext);
|
|
2095
2468
|
return file;
|
|
2096
2469
|
}
|
|
2097
2470
|
it('called for BRS file', () => {
|
|
2098
2471
|
const onParsed = sinon.spy();
|
|
2099
2472
|
parseFileWithCallback('.brs', onParsed);
|
|
2100
|
-
chai_1.expect(onParsed.callCount).to.equal(1);
|
|
2473
|
+
(0, chai_1.expect)(onParsed.callCount).to.equal(1);
|
|
2101
2474
|
});
|
|
2102
2475
|
it('called for BS file', () => {
|
|
2103
2476
|
const onParsed = sinon.spy();
|
|
2104
2477
|
parseFileWithCallback('.bs', onParsed);
|
|
2105
|
-
chai_1.expect(onParsed.callCount).to.equal(1);
|
|
2478
|
+
(0, chai_1.expect)(onParsed.callCount).to.equal(1);
|
|
2106
2479
|
});
|
|
2107
2480
|
});
|
|
2108
2481
|
describe('typedefKey', () => {
|
|
2109
2482
|
it('works for .brs files', () => {
|
|
2110
|
-
chai_1.expect(util_1.standardizePath((program.
|
|
2483
|
+
(0, chai_1.expect)((0, util_1.standardizePath)((program.setFile('source/main.brs', '')).typedefSrcPath)).to.equal((0, util_1.standardizePath) `${rootDir.toLowerCase()}/source/main.d.bs`);
|
|
2111
2484
|
});
|
|
2112
2485
|
it('returns undefined for files that should not have a typedef', () => {
|
|
2113
|
-
chai_1.expect((program.
|
|
2114
|
-
chai_1.expect((program.
|
|
2115
|
-
const xmlFile = program.
|
|
2116
|
-
chai_1.expect(xmlFile.typedefSrcPath).to.be.undefined;
|
|
2486
|
+
(0, chai_1.expect)((program.setFile('source/main.bs', '')).typedefSrcPath).to.be.undefined;
|
|
2487
|
+
(0, chai_1.expect)((program.setFile('source/main.d.bs', '')).typedefSrcPath).to.be.undefined;
|
|
2488
|
+
const xmlFile = program.setFile('components/comp.xml', '');
|
|
2489
|
+
(0, chai_1.expect)(xmlFile.typedefSrcPath).to.be.undefined;
|
|
2117
2490
|
});
|
|
2118
2491
|
});
|
|
2119
2492
|
describe('type definitions', () => {
|
|
2120
2493
|
it('only exposes defined functions even if source has more', () => {
|
|
2121
2494
|
//parse the .brs file first so it doesn't know about the typedef
|
|
2122
|
-
program.
|
|
2495
|
+
program.setFile('source/main.brs', `
|
|
2123
2496
|
sub main()
|
|
2124
2497
|
end sub
|
|
2125
2498
|
sub speak()
|
|
2126
2499
|
end sub
|
|
2127
2500
|
`);
|
|
2128
|
-
program.
|
|
2501
|
+
program.setFile('source/main.d.bs', `
|
|
2129
2502
|
sub main()
|
|
2130
2503
|
end sub
|
|
2131
2504
|
`);
|
|
2132
2505
|
const sourceScope = program.getScopeByName('source');
|
|
2133
2506
|
const functionNames = sourceScope.getAllCallables().map(x => x.callable.name);
|
|
2134
|
-
chai_1.expect(functionNames).to.include('main');
|
|
2135
|
-
chai_1.expect(functionNames).not.to.include('speak');
|
|
2507
|
+
(0, chai_1.expect)(functionNames).to.include('main');
|
|
2508
|
+
(0, chai_1.expect)(functionNames).not.to.include('speak');
|
|
2136
2509
|
});
|
|
2137
2510
|
it('reacts to typedef file changes', () => {
|
|
2138
|
-
let file = program.
|
|
2511
|
+
let file = program.setFile('source/main.brs', `
|
|
2139
2512
|
sub main()
|
|
2140
2513
|
end sub
|
|
2141
2514
|
sub speak()
|
|
2142
2515
|
end sub
|
|
2143
2516
|
`);
|
|
2144
|
-
chai_1.expect(file.hasTypedef).to.be.false;
|
|
2145
|
-
chai_1.expect(file.typedefFile).not.to.exist;
|
|
2146
|
-
program.
|
|
2517
|
+
(0, chai_1.expect)(file.hasTypedef).to.be.false;
|
|
2518
|
+
(0, chai_1.expect)(file.typedefFile).not.to.exist;
|
|
2519
|
+
program.setFile('source/main.d.bs', `
|
|
2147
2520
|
sub main()
|
|
2148
2521
|
end sub
|
|
2149
2522
|
`);
|
|
2150
|
-
chai_1.expect(file.hasTypedef).to.be.true;
|
|
2151
|
-
chai_1.expect(file.typedefFile).to.exist;
|
|
2523
|
+
(0, chai_1.expect)(file.hasTypedef).to.be.true;
|
|
2524
|
+
(0, chai_1.expect)(file.typedefFile).to.exist;
|
|
2152
2525
|
//add replace file, does it still find the typedef
|
|
2153
|
-
file = program.
|
|
2526
|
+
file = program.setFile('source/main.brs', `
|
|
2154
2527
|
sub main()
|
|
2155
2528
|
end sub
|
|
2156
2529
|
sub speak()
|
|
2157
2530
|
end sub
|
|
2158
2531
|
`);
|
|
2159
|
-
chai_1.expect(file.hasTypedef).to.be.true;
|
|
2160
|
-
chai_1.expect(file.typedefFile).to.exist;
|
|
2161
|
-
program.removeFile(util_1.standardizePath `${rootDir}/source/main.d.bs`);
|
|
2162
|
-
chai_1.expect(file.hasTypedef).to.be.false;
|
|
2163
|
-
chai_1.expect(file.typedefFile).not.to.exist;
|
|
2532
|
+
(0, chai_1.expect)(file.hasTypedef).to.be.true;
|
|
2533
|
+
(0, chai_1.expect)(file.typedefFile).to.exist;
|
|
2534
|
+
program.removeFile((0, util_1.standardizePath) `${rootDir}/source/main.d.bs`);
|
|
2535
|
+
(0, chai_1.expect)(file.hasTypedef).to.be.false;
|
|
2536
|
+
(0, chai_1.expect)(file.typedefFile).not.to.exist;
|
|
2164
2537
|
});
|
|
2165
2538
|
});
|
|
2166
2539
|
describe('typedef', () => {
|
|
2167
2540
|
it('sets typedef path properly', () => {
|
|
2168
|
-
chai_1.expect((program.
|
|
2169
|
-
chai_1.expect((program.
|
|
2170
|
-
chai_1.expect((program.
|
|
2541
|
+
(0, chai_1.expect)((program.setFile('source/main1.brs', '')).typedefSrcPath).to.equal((0, util_1.standardizePath) `${rootDir}/source/main1.d.bs`.toLowerCase());
|
|
2542
|
+
(0, chai_1.expect)((program.setFile('source/main2.d.bs', '')).typedefSrcPath).to.equal(undefined);
|
|
2543
|
+
(0, chai_1.expect)((program.setFile('source/main3.bs', '')).typedefSrcPath).to.equal(undefined);
|
|
2171
2544
|
//works for dest with `.brs` extension
|
|
2172
|
-
chai_1.expect((program.
|
|
2545
|
+
(0, chai_1.expect)((program.setFile({ src: 'source/main4.bs', dest: 'source/main4.brs' }, '')).typedefSrcPath).to.equal(undefined);
|
|
2173
2546
|
});
|
|
2174
2547
|
it('does not link when missing from program', () => {
|
|
2175
|
-
const file = program.
|
|
2176
|
-
chai_1.expect(file.typedefFile).not.to.exist;
|
|
2548
|
+
const file = program.setFile('source/main.brs', ``);
|
|
2549
|
+
(0, chai_1.expect)(file.typedefFile).not.to.exist;
|
|
2177
2550
|
});
|
|
2178
2551
|
it('links typedef when added BEFORE .brs file', () => {
|
|
2179
|
-
const typedef = program.
|
|
2180
|
-
const file = program.
|
|
2181
|
-
chai_1.expect(file.typedefFile).to.equal(typedef);
|
|
2552
|
+
const typedef = program.setFile('source/main.d.bs', ``);
|
|
2553
|
+
const file = program.setFile('source/main.brs', ``);
|
|
2554
|
+
(0, chai_1.expect)(file.typedefFile).to.equal(typedef);
|
|
2182
2555
|
});
|
|
2183
2556
|
it('links typedef when added AFTER .brs file', () => {
|
|
2184
|
-
const file = program.
|
|
2185
|
-
const typedef = program.
|
|
2186
|
-
chai_1.expect(file.typedefFile).to.eql(typedef);
|
|
2557
|
+
const file = program.setFile('source/main.brs', ``);
|
|
2558
|
+
const typedef = program.setFile('source/main.d.bs', ``);
|
|
2559
|
+
(0, chai_1.expect)(file.typedefFile).to.eql(typedef);
|
|
2187
2560
|
});
|
|
2188
2561
|
it('removes typedef link when typedef is removed', () => {
|
|
2189
|
-
const typedef = program.
|
|
2190
|
-
const file = program.
|
|
2562
|
+
const typedef = program.setFile('source/main.d.bs', ``);
|
|
2563
|
+
const file = program.setFile('source/main.brs', ``);
|
|
2191
2564
|
program.removeFile(typedef.srcPath);
|
|
2192
|
-
chai_1.expect(file.typedefFile).to.be.undefined;
|
|
2565
|
+
(0, chai_1.expect)(file.typedefFile).to.be.undefined;
|
|
2193
2566
|
});
|
|
2194
2567
|
});
|
|
2195
2568
|
describe('getTypedef', () => {
|
|
2196
2569
|
function testTypedef(original, expected) {
|
|
2197
|
-
let file = program.
|
|
2198
|
-
chai_1.expect(file.getTypedef()).to.eql(expected);
|
|
2570
|
+
let file = program.setFile('source/main.brs', original);
|
|
2571
|
+
(0, chai_1.expect)(file.getTypedef().trimEnd()).to.eql(expected);
|
|
2199
2572
|
}
|
|
2200
2573
|
it('includes namespace on extend class names', () => {
|
|
2201
2574
|
testTypedef(`
|
|
@@ -2204,11 +2577,16 @@ describe('BrsFile', () => {
|
|
|
2204
2577
|
end class
|
|
2205
2578
|
class Duck extends Bird
|
|
2206
2579
|
end class
|
|
2207
|
-
end namespace
|
|
2580
|
+
end namespace
|
|
2581
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2208
2582
|
namespace AnimalKingdom
|
|
2209
2583
|
class Bird
|
|
2584
|
+
sub new()
|
|
2585
|
+
end sub
|
|
2210
2586
|
end class
|
|
2211
2587
|
class Duck extends AnimalKingdom.Bird
|
|
2588
|
+
sub new()
|
|
2589
|
+
end sub
|
|
2212
2590
|
end class
|
|
2213
2591
|
end namespace
|
|
2214
2592
|
`);
|
|
@@ -2218,7 +2596,7 @@ describe('BrsFile', () => {
|
|
|
2218
2596
|
sub main(param1 as string)
|
|
2219
2597
|
print "main"
|
|
2220
2598
|
end sub
|
|
2221
|
-
`, testHelpers_spec_1.trim `
|
|
2599
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2222
2600
|
sub main(param1 as string)
|
|
2223
2601
|
end sub
|
|
2224
2602
|
`);
|
|
@@ -2241,13 +2619,15 @@ describe('BrsFile', () => {
|
|
|
2241
2619
|
end function
|
|
2242
2620
|
end class
|
|
2243
2621
|
end namespace
|
|
2244
|
-
`, testHelpers_spec_1.trim `
|
|
2622
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2245
2623
|
namespace test
|
|
2246
2624
|
@an
|
|
2247
2625
|
@anFunc("value")
|
|
2248
2626
|
function getDuck()
|
|
2249
2627
|
end function
|
|
2250
2628
|
class Duck
|
|
2629
|
+
sub new()
|
|
2630
|
+
end sub
|
|
2251
2631
|
@anMember
|
|
2252
2632
|
@anMember("field")
|
|
2253
2633
|
private thing as dynamic
|
|
@@ -2262,7 +2642,7 @@ describe('BrsFile', () => {
|
|
|
2262
2642
|
it('includes import statements', () => {
|
|
2263
2643
|
testTypedef(`
|
|
2264
2644
|
import "pkg:/source/lib.brs"
|
|
2265
|
-
`, testHelpers_spec_1.trim `
|
|
2645
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2266
2646
|
import "pkg:/source/lib.brs"
|
|
2267
2647
|
`);
|
|
2268
2648
|
});
|
|
@@ -2276,7 +2656,7 @@ describe('BrsFile', () => {
|
|
|
2276
2656
|
sub logInfo()
|
|
2277
2657
|
end sub
|
|
2278
2658
|
end namespace
|
|
2279
|
-
`, testHelpers_spec_1.trim `
|
|
2659
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2280
2660
|
namespace Name
|
|
2281
2661
|
sub logInfo()
|
|
2282
2662
|
end sub
|
|
@@ -2305,8 +2685,10 @@ describe('BrsFile', () => {
|
|
|
2305
2685
|
end sub
|
|
2306
2686
|
end class
|
|
2307
2687
|
end namespace
|
|
2308
|
-
`, testHelpers_spec_1.trim `
|
|
2688
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2309
2689
|
class Person
|
|
2690
|
+
sub new()
|
|
2691
|
+
end sub
|
|
2310
2692
|
public name as string
|
|
2311
2693
|
public age as integer
|
|
2312
2694
|
public sub getAge() as integer
|
|
@@ -2314,6 +2696,8 @@ describe('BrsFile', () => {
|
|
|
2314
2696
|
end class
|
|
2315
2697
|
namespace NameA.NameB
|
|
2316
2698
|
class Person
|
|
2699
|
+
sub new()
|
|
2700
|
+
end sub
|
|
2317
2701
|
public name as string
|
|
2318
2702
|
public age as integer
|
|
2319
2703
|
public sub getAge() as integer
|
|
@@ -2322,14 +2706,27 @@ describe('BrsFile', () => {
|
|
|
2322
2706
|
end namespace
|
|
2323
2707
|
`);
|
|
2324
2708
|
});
|
|
2709
|
+
it('creates constructor properly', () => {
|
|
2710
|
+
testTypedef(`
|
|
2711
|
+
class Parent
|
|
2712
|
+
end class
|
|
2713
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2714
|
+
class Parent
|
|
2715
|
+
sub new()
|
|
2716
|
+
end sub
|
|
2717
|
+
end class
|
|
2718
|
+
`);
|
|
2719
|
+
});
|
|
2325
2720
|
it('sets properties to dynamic when initialized to invalid', () => {
|
|
2326
2721
|
testTypedef(`
|
|
2327
2722
|
class Human
|
|
2328
2723
|
public firstName = invalid
|
|
2329
2724
|
public lastName as string = invalid
|
|
2330
2725
|
end class
|
|
2331
|
-
`, testHelpers_spec_1.trim `
|
|
2726
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2332
2727
|
class Human
|
|
2728
|
+
sub new()
|
|
2729
|
+
end sub
|
|
2333
2730
|
public firstName as dynamic
|
|
2334
2731
|
public lastName as string
|
|
2335
2732
|
end class
|
|
@@ -2347,7 +2744,7 @@ describe('BrsFile', () => {
|
|
|
2347
2744
|
super(name)
|
|
2348
2745
|
end sub
|
|
2349
2746
|
end class
|
|
2350
|
-
`, testHelpers_spec_1.trim `
|
|
2747
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2351
2748
|
class Human
|
|
2352
2749
|
sub new(name as string)
|
|
2353
2750
|
end sub
|
|
@@ -2374,8 +2771,10 @@ describe('BrsFile', () => {
|
|
|
2374
2771
|
return m.lastName
|
|
2375
2772
|
end function
|
|
2376
2773
|
end class
|
|
2377
|
-
`, testHelpers_spec_1.trim `
|
|
2774
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2378
2775
|
class Human
|
|
2776
|
+
sub new()
|
|
2777
|
+
end sub
|
|
2379
2778
|
public firstName as string
|
|
2380
2779
|
protected middleName as string
|
|
2381
2780
|
private lastName as string
|
|
@@ -2400,12 +2799,16 @@ describe('BrsFile', () => {
|
|
|
2400
2799
|
print "Hello Dog"
|
|
2401
2800
|
end sub
|
|
2402
2801
|
end class
|
|
2403
|
-
`, testHelpers_spec_1.trim `
|
|
2802
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2404
2803
|
class Animal
|
|
2804
|
+
sub new()
|
|
2805
|
+
end sub
|
|
2405
2806
|
public sub speak()
|
|
2406
2807
|
end sub
|
|
2407
2808
|
end class
|
|
2408
2809
|
class Dog extends Animal
|
|
2810
|
+
sub new()
|
|
2811
|
+
end sub
|
|
2409
2812
|
public override sub speak()
|
|
2410
2813
|
end sub
|
|
2411
2814
|
end class
|
|
@@ -2427,7 +2830,7 @@ describe('BrsFile', () => {
|
|
|
2427
2830
|
end sub
|
|
2428
2831
|
end class
|
|
2429
2832
|
end namespace
|
|
2430
|
-
`, testHelpers_spec_1.trim `
|
|
2833
|
+
`, (0, testHelpers_spec_1.trim) `
|
|
2431
2834
|
namespace NameA
|
|
2432
2835
|
class Human
|
|
2433
2836
|
sub new(name as string)
|
|
@@ -2445,7 +2848,7 @@ describe('BrsFile', () => {
|
|
|
2445
2848
|
});
|
|
2446
2849
|
describe('parser getter', () => {
|
|
2447
2850
|
it('recreates the parser when missing', () => {
|
|
2448
|
-
const file = program.
|
|
2851
|
+
const file = program.setFile('source/main.brs', `
|
|
2449
2852
|
sub main()
|
|
2450
2853
|
end sub
|
|
2451
2854
|
`);
|
|
@@ -2454,71 +2857,274 @@ describe('BrsFile', () => {
|
|
|
2454
2857
|
file['_parser'] = undefined;
|
|
2455
2858
|
//force the file to get a new instance of parser
|
|
2456
2859
|
const newParser = file.parser;
|
|
2457
|
-
chai_1.expect(newParser).to.exist.and.to.not.equal(parser);
|
|
2860
|
+
(0, chai_1.expect)(newParser).to.exist.and.to.not.equal(parser);
|
|
2458
2861
|
//reference shouldn't change in subsequent accesses
|
|
2459
|
-
chai_1.expect(file.parser).to.equal(newParser);
|
|
2862
|
+
(0, chai_1.expect)(file.parser).to.equal(newParser);
|
|
2460
2863
|
});
|
|
2461
2864
|
it('call parse when previously skipped', () => {
|
|
2462
|
-
program.
|
|
2865
|
+
program.setFile('source/main.d.bs', `'typedef
|
|
2463
2866
|
sub main()
|
|
2464
2867
|
end sub
|
|
2465
2868
|
`);
|
|
2466
|
-
const file = program.
|
|
2869
|
+
const file = program.setFile('source/main.brs', `'source
|
|
2467
2870
|
sub main()
|
|
2468
2871
|
end sub
|
|
2469
2872
|
`);
|
|
2470
2873
|
//no functions should be found since the parser was skipped
|
|
2471
|
-
chai_1.expect(file['_parser']).to.not.exist;
|
|
2874
|
+
(0, chai_1.expect)(file['_parser']).to.not.exist;
|
|
2472
2875
|
const stub = sinon.stub(file, 'parse').callThrough();
|
|
2473
2876
|
//`file.parser` is a getter, so that should force the parse to occur
|
|
2474
|
-
chai_1.expect(file.parser.references.functionStatements).to.be.lengthOf(1);
|
|
2475
|
-
chai_1.expect(stub.called).to.be.true;
|
|
2877
|
+
(0, chai_1.expect)(file.parser.references.functionStatements).to.be.lengthOf(1);
|
|
2878
|
+
(0, chai_1.expect)(stub.called).to.be.true;
|
|
2476
2879
|
//parse should have been called
|
|
2477
2880
|
});
|
|
2478
2881
|
});
|
|
2479
2882
|
describe('Plugins', () => {
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2883
|
+
let pluginFileName;
|
|
2884
|
+
let idx = 1;
|
|
2885
|
+
beforeEach(() => {
|
|
2886
|
+
pluginFileName = `plugin-${idx++}.js`;
|
|
2887
|
+
fsExtra.outputFileSync((0, util_1.standardizePath) `${tempDir}/plugins/${pluginFileName}`, `
|
|
2888
|
+
function plugin() {
|
|
2889
|
+
return {
|
|
2890
|
+
name: 'lower-file-name',
|
|
2891
|
+
afterFileParse: (evt) => {
|
|
2892
|
+
evt.file._customProp = true;
|
|
2893
|
+
}
|
|
2894
|
+
};
|
|
2895
|
+
}
|
|
2896
|
+
exports.default = plugin;
|
|
2897
|
+
`);
|
|
2898
|
+
});
|
|
2899
|
+
it('can load an absolute plugin which receives callbacks', () => {
|
|
2900
|
+
program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(tempDir, [
|
|
2901
|
+
(0, util_1.standardizePath) `${tempDir}/plugins/${pluginFileName}`
|
|
2902
|
+
]), new Logger_1.Logger());
|
|
2903
|
+
const file = program.setFile('source/MAIN.brs', '');
|
|
2904
|
+
(0, chai_1.expect)(file._customProp).to.exist;
|
|
2905
|
+
});
|
|
2906
|
+
it('can load a relative plugin which receives callbacks', () => {
|
|
2907
|
+
program.plugins = new PluginInterface_1.default(util_1.default.loadPlugins(tempDir, [
|
|
2908
|
+
`./plugins/${pluginFileName}`
|
|
2909
|
+
]), new Logger_1.Logger());
|
|
2910
|
+
const file = program.setFile('source/MAIN.brs', '');
|
|
2911
|
+
(0, chai_1.expect)(file._customProp).to.exist;
|
|
2912
|
+
});
|
|
2913
|
+
});
|
|
2914
|
+
describe('getSymbolTypeFromToken', () => {
|
|
2915
|
+
function checkSymbolLookups(file, funcExpr, lookups) {
|
|
2916
|
+
const mainScope = program.getScopesForFile(file)[0];
|
|
2917
|
+
mainScope.linkSymbolTable();
|
|
2918
|
+
for (const lookup of lookups) {
|
|
2919
|
+
const position = vscode_languageserver_1.Position.create(lookup.line, lookup.col);
|
|
2920
|
+
const token = file.parser.getTokenAt(position);
|
|
2921
|
+
const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
|
|
2922
|
+
const context = {
|
|
2923
|
+
file: file,
|
|
2924
|
+
scope: mainScope,
|
|
2925
|
+
position: position
|
|
2926
|
+
};
|
|
2927
|
+
(0, chai_1.expect)(symbol.expandedTokenText).to.equal(lookup.name);
|
|
2928
|
+
(0, chai_1.expect)(symbol.type.equals(lookup.type, context)).be.true;
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
it('gets simple types based on the containing function expression', () => {
|
|
2932
|
+
const file = program.setFile('source/main.bs', `
|
|
2933
|
+
sub doSomething(aInt as integer, aFloat as float, aStr as string, aBool as boolean, aObj as object)
|
|
2934
|
+
print aInt
|
|
2935
|
+
print aFloat
|
|
2936
|
+
print aStr
|
|
2937
|
+
print aBool
|
|
2938
|
+
print aObj
|
|
2939
|
+
end sub
|
|
2940
|
+
`);
|
|
2941
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
2942
|
+
const lookups = [
|
|
2943
|
+
{ line: 2, col: 28, name: 'aInt', type: new IntegerType_1.IntegerType() },
|
|
2944
|
+
{ line: 3, col: 28, name: 'aFloat', type: new FloatType_1.FloatType() },
|
|
2945
|
+
{ line: 4, col: 28, name: 'aStr', type: new StringType_1.StringType() },
|
|
2946
|
+
{ line: 5, col: 28, name: 'aBool', type: new BooleanType_1.BooleanType() },
|
|
2947
|
+
{ line: 6, col: 28, name: 'aObj', type: new ObjectType_1.ObjectType() }
|
|
2948
|
+
];
|
|
2949
|
+
checkSymbolLookups(file, funcExpr, lookups);
|
|
2950
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2951
|
+
});
|
|
2952
|
+
it('gets custom types based on the containing function expression', () => {
|
|
2953
|
+
const file = program.setFile('source/main.bs', `
|
|
2954
|
+
sub doSomething(klass as MyKlass)
|
|
2955
|
+
print klass
|
|
2487
2956
|
end sub
|
|
2488
2957
|
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2958
|
+
class MyKlass
|
|
2959
|
+
end class
|
|
2960
|
+
`);
|
|
2961
|
+
const mainScope = program.getScopesForFile(file)[0];
|
|
2962
|
+
mainScope.linkSymbolTable();
|
|
2963
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
2964
|
+
const token = file.parser.getTokenAt(vscode_languageserver_1.Position.create(2, 28));
|
|
2965
|
+
const symbol = file.getSymbolTypeFromToken(token, funcExpr, mainScope);
|
|
2966
|
+
(0, chai_1.expect)(symbol.expandedTokenText).to.equal('klass');
|
|
2967
|
+
const classStmt = file.parser.references.classStatements[0];
|
|
2968
|
+
(0, chai_1.expect)(classStmt.name.text).to.equal('MyKlass');
|
|
2969
|
+
(0, chai_1.expect)(symbol.type.isAssignableTo(classStmt.getThisBscType())).be.true;
|
|
2970
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2971
|
+
});
|
|
2972
|
+
it('gets types of properties of a klass', () => {
|
|
2973
|
+
const file = program.setFile('source/main.bs', `
|
|
2974
|
+
sub doSomething()
|
|
2975
|
+
klass = new MyKlass()
|
|
2976
|
+
print klass.name
|
|
2977
|
+
print klass.age
|
|
2978
|
+
' verify case insensitivity
|
|
2979
|
+
print KLASS.NAME
|
|
2980
|
+
print klass.AGE
|
|
2492
2981
|
end sub
|
|
2493
|
-
`, `
|
|
2494
|
-
sub main()
|
|
2495
|
-
sayHello(sub()
|
|
2496
|
-
\n end sub)
|
|
2497
|
-
\n end sub
|
|
2498
2982
|
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2983
|
+
class MyKlass
|
|
2984
|
+
name as string
|
|
2985
|
+
age as integer
|
|
2986
|
+
end class
|
|
2502
2987
|
`);
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
]
|
|
2508
|
-
|
|
2988
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
2989
|
+
const lookups = [
|
|
2990
|
+
{ line: 3, col: 35, name: 'MyKlass.name', type: new StringType_1.StringType() },
|
|
2991
|
+
{ line: 4, col: 35, name: 'MyKlass.age', type: new IntegerType_1.IntegerType() }
|
|
2992
|
+
];
|
|
2993
|
+
checkSymbolLookups(file, funcExpr, lookups);
|
|
2994
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2509
2995
|
});
|
|
2510
|
-
it('
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2996
|
+
it('gets types of properties of an object', () => {
|
|
2997
|
+
const file = program.setFile('source/main.bs', `
|
|
2998
|
+
sub doSomething()
|
|
2999
|
+
obj = { name: "Joe", age: 37}
|
|
3000
|
+
print obj.name
|
|
3001
|
+
print obj.age
|
|
3002
|
+
end sub
|
|
3003
|
+
`);
|
|
3004
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
3005
|
+
const lookups = [
|
|
3006
|
+
{ line: 3, col: 32, name: 'obj.name', type: new StringType_1.StringType() },
|
|
3007
|
+
{ line: 4, col: 32, name: 'obj.age', type: new IntegerType_1.IntegerType() }
|
|
3008
|
+
];
|
|
3009
|
+
checkSymbolLookups(file, funcExpr, lookups);
|
|
3010
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2515
3011
|
});
|
|
2516
|
-
it('
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
3012
|
+
it('gets return types of functions', () => {
|
|
3013
|
+
const file = program.setFile('source/main.bs', `
|
|
3014
|
+
sub doSomething()
|
|
3015
|
+
pi = makeKlass().getSelf().getPi()
|
|
3016
|
+
print pi
|
|
3017
|
+
end sub
|
|
3018
|
+
|
|
3019
|
+
function makeKlass() as MyKlass
|
|
3020
|
+
return new MyKlass()
|
|
3021
|
+
end function
|
|
3022
|
+
|
|
3023
|
+
class MyKlass
|
|
3024
|
+
function getPi() as float
|
|
3025
|
+
return 3.14
|
|
3026
|
+
end function
|
|
3027
|
+
|
|
3028
|
+
function getSelf() as MyKlass
|
|
3029
|
+
return m
|
|
3030
|
+
end function
|
|
3031
|
+
end class
|
|
3032
|
+
`);
|
|
3033
|
+
const mainScope = program.getScopesForFile(file)[0];
|
|
3034
|
+
mainScope.linkSymbolTable();
|
|
3035
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
3036
|
+
const klassMemberTable = file.parser.references.classStatements[0].memberTable;
|
|
3037
|
+
const lookups = [
|
|
3038
|
+
{ line: 2, col: 31, name: 'makeKlass', type: file.parser.references.functionExpressions[1].getFunctionType() },
|
|
3039
|
+
// The expanded text for this should probably be MyKlass.getSelf()
|
|
3040
|
+
{ line: 2, col: 41, name: 'MyKlass.MyKlass', type: klassMemberTable.getSymbol('getSelf')[0].type },
|
|
3041
|
+
{ line: 2, col: 51, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
|
|
3042
|
+
{ line: 3, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
|
|
3043
|
+
];
|
|
3044
|
+
checkSymbolLookups(file, funcExpr, lookups);
|
|
3045
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3046
|
+
});
|
|
3047
|
+
it('gets types of elements of arrays', () => {
|
|
3048
|
+
const file = program.setFile('source/main.bs', `
|
|
3049
|
+
sub doSomething(words as string[], klasses as MyKlass[])
|
|
3050
|
+
myWord = words[0]
|
|
3051
|
+
pi = klasses[0].getPi()
|
|
3052
|
+
print myWord
|
|
3053
|
+
print pi
|
|
3054
|
+
end sub
|
|
3055
|
+
|
|
3056
|
+
class MyKlass
|
|
3057
|
+
function getPi() as float
|
|
3058
|
+
return 3.14
|
|
3059
|
+
end function
|
|
3060
|
+
end class
|
|
3061
|
+
`);
|
|
3062
|
+
const mainScope = program.getScopesForFile(file)[0];
|
|
3063
|
+
mainScope.linkSymbolTable();
|
|
3064
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
3065
|
+
const klassMemberTable = file.parser.references.classStatements[0].memberTable;
|
|
3066
|
+
const lookups = [
|
|
3067
|
+
{ line: 2, col: 34, name: 'words', type: new ArrayType_1.ArrayType(new StringType_1.StringType()) },
|
|
3068
|
+
{ line: 3, col: 41, name: 'MyKlass.getPi', type: klassMemberTable.getSymbol('getPi')[0].type },
|
|
3069
|
+
{ line: 4, col: 28, name: 'myWord', type: new StringType_1.StringType() },
|
|
3070
|
+
{ line: 5, col: 28, name: 'pi', type: new FloatType_1.FloatType() }
|
|
3071
|
+
];
|
|
3072
|
+
checkSymbolLookups(file, funcExpr, lookups);
|
|
3073
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3074
|
+
});
|
|
3075
|
+
it('gets types of elements of arrays via square bracket reference', () => {
|
|
3076
|
+
const file = program.setFile('source/main.bs', `
|
|
3077
|
+
function printFirst(numbers as float[]) as float
|
|
3078
|
+
firstFloat = numbers[0]
|
|
3079
|
+
print firstFloat
|
|
3080
|
+
return firstFloat
|
|
3081
|
+
end function
|
|
3082
|
+
`);
|
|
3083
|
+
const mainScope = program.getScopesForFile(file)[0];
|
|
3084
|
+
mainScope.linkSymbolTable();
|
|
3085
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
3086
|
+
const lookups = [
|
|
3087
|
+
{ line: 2, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
|
|
3088
|
+
{ line: 3, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
|
|
3089
|
+
];
|
|
3090
|
+
checkSymbolLookups(file, funcExpr, lookups);
|
|
3091
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
3092
|
+
});
|
|
3093
|
+
it('gets types of elements of arrays after for each', () => {
|
|
3094
|
+
const file = program.setFile('source/main.bs', `
|
|
3095
|
+
function printAllReturnFirst(numbers as float[]) as float
|
|
3096
|
+
for each num in numbers
|
|
3097
|
+
print num
|
|
3098
|
+
end for
|
|
3099
|
+
|
|
3100
|
+
firstFloat = numbers[0]
|
|
3101
|
+
print firstFloat
|
|
3102
|
+
return firstFloat
|
|
3103
|
+
end function
|
|
3104
|
+
`);
|
|
3105
|
+
const mainScope = program.getScopesForFile(file)[0];
|
|
3106
|
+
mainScope.linkSymbolTable();
|
|
3107
|
+
const funcExpr = file.parser.references.functionExpressions[0];
|
|
3108
|
+
const lookups = [
|
|
3109
|
+
{ line: 6, col: 26, name: 'firstFloat', type: new FloatType_1.FloatType() },
|
|
3110
|
+
{ line: 7, col: 32, name: 'firstFloat', type: new FloatType_1.FloatType() }
|
|
3111
|
+
];
|
|
3112
|
+
checkSymbolLookups(file, funcExpr, lookups);
|
|
3113
|
+
(0, testHelpers_spec_1.expectZeroDiagnostics)(program);
|
|
2521
3114
|
});
|
|
2522
3115
|
});
|
|
3116
|
+
it('defaults to `dynamic` type for a complex expression', () => {
|
|
3117
|
+
const file = program.setFile('source/main.brs', `
|
|
3118
|
+
sub main()
|
|
3119
|
+
name = "cat"
|
|
3120
|
+
thing = m["key"](true)
|
|
3121
|
+
end sub
|
|
3122
|
+
`);
|
|
3123
|
+
program.validate();
|
|
3124
|
+
//sanity check
|
|
3125
|
+
(0, chai_1.expect)(file.parser.references.assignmentStatements[0].containingFunction.symbolTable.getSymbolType('name')).be.instanceof(StringType_1.StringType);
|
|
3126
|
+
//this complex expression should resolve to dynamic type when not known
|
|
3127
|
+
(0, chai_1.expect)(file.parser.references.assignmentStatements[0].containingFunction.symbolTable.getSymbolType('thing')).be.instanceof(DynamicType_1.DynamicType);
|
|
3128
|
+
});
|
|
2523
3129
|
});
|
|
2524
3130
|
//# sourceMappingURL=BrsFile.spec.js.map
|