brighterscript 1.0.0-alpha.23 → 1.0.0-alpha.25
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 +585 -218
- package/README.md +45 -139
- package/bsconfig.schema.json +41 -0
- package/dist/ActionPipeline.d.ts +10 -0
- package/dist/ActionPipeline.js +40 -0
- package/dist/ActionPipeline.js.map +1 -0
- package/dist/AstValidationSegmenter.d.ts +25 -0
- package/dist/AstValidationSegmenter.js +152 -0
- package/dist/AstValidationSegmenter.js.map +1 -0
- package/dist/BsConfig.d.ts +39 -4
- package/dist/BusyStatusTracker.d.ts +31 -0
- package/dist/BusyStatusTracker.js +83 -0
- package/dist/BusyStatusTracker.js.map +1 -0
- package/dist/Cache.js +3 -3
- package/dist/Cache.js.map +1 -1
- package/dist/CacheVerifier.d.ts +7 -0
- package/dist/CacheVerifier.js +20 -0
- package/dist/CacheVerifier.js.map +1 -0
- package/dist/CodeActionUtil.d.ts +3 -3
- package/dist/CodeActionUtil.js.map +1 -1
- package/dist/CommentFlagProcessor.d.ts +3 -2
- package/dist/CommentFlagProcessor.js +5 -4
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DependencyGraph.d.ts +3 -2
- package/dist/DependencyGraph.js +11 -10
- package/dist/DependencyGraph.js.map +1 -1
- package/dist/DiagnosticCollection.js +9 -5
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/DiagnosticFilterer.d.ts +1 -0
- package/dist/DiagnosticFilterer.js +5 -3
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +79 -15
- package/dist/DiagnosticMessages.js +134 -21
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
- package/dist/DiagnosticSeverityAdjuster.js +41 -0
- package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
- package/dist/FunctionScope.d.ts +28 -0
- package/dist/FunctionScope.js +52 -0
- package/dist/FunctionScope.js.map +1 -0
- package/dist/KeyedThrottler.d.ts +3 -3
- package/dist/KeyedThrottler.js +3 -3
- package/dist/KeyedThrottler.js.map +1 -1
- package/dist/LanguageServer.d.ts +23 -11
- package/dist/LanguageServer.js +222 -87
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +3 -2
- package/dist/Logger.js +11 -3
- package/dist/Logger.js.map +1 -1
- package/dist/PluginInterface.d.ts +21 -3
- package/dist/PluginInterface.js +74 -6
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +162 -81
- package/dist/Program.js +903 -732
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +22 -12
- package/dist/ProgramBuilder.js +132 -104
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +95 -134
- package/dist/Scope.js +477 -551
- package/dist/Scope.js.map +1 -1
- package/dist/Stopwatch.js +1 -1
- package/dist/Stopwatch.js.map +1 -1
- package/dist/SymbolTable.d.ts +95 -29
- package/dist/SymbolTable.js +256 -102
- package/dist/SymbolTable.js.map +1 -1
- package/dist/Throttler.d.ts +12 -0
- package/dist/Throttler.js +39 -0
- package/dist/Throttler.js.map +1 -1
- package/dist/Watcher.d.ts +0 -3
- package/dist/Watcher.js +0 -3
- package/dist/Watcher.js.map +1 -1
- package/dist/XmlScope.d.ts +4 -6
- package/dist/XmlScope.js +74 -68
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/CachedLookups.d.ts +48 -0
- package/dist/astUtils/CachedLookups.js +323 -0
- package/dist/astUtils/CachedLookups.js.map +1 -0
- package/dist/astUtils/{AstEditor.d.ts → Editor.d.ts} +9 -5
- package/dist/astUtils/{AstEditor.js → Editor.js} +10 -4
- package/dist/astUtils/Editor.js.map +1 -0
- package/dist/astUtils/{AstEditor.spec.js → Editor.spec.js} +68 -64
- package/dist/astUtils/Editor.spec.js.map +1 -0
- package/dist/astUtils/creators.d.ts +10 -10
- package/dist/astUtils/creators.js +26 -16
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/creators.spec.js +5 -5
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +132 -100
- package/dist/astUtils/reflection.js +225 -166
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +208 -126
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/stackedVisitor.spec.js +12 -12
- package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +54 -35
- package/dist/astUtils/visitors.js +29 -3
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +178 -33
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/astUtils/xml.d.ts +9 -9
- package/dist/astUtils/xml.js +9 -9
- package/dist/astUtils/xml.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +12 -2
- package/dist/bscPlugin/BscPlugin.js +41 -3
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
- package/dist/bscPlugin/CallExpressionInfo.js +131 -0
- package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
- package/dist/bscPlugin/FileWriter.d.ts +6 -0
- package/dist/bscPlugin/FileWriter.js +24 -0
- package/dist/bscPlugin/FileWriter.js.map +1 -0
- package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
- package/dist/bscPlugin/SignatureHelpUtil.js +135 -0
- package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +21 -12
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +86 -12
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +57 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js +544 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1909 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
- package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
- package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.d.ts +17 -0
- package/dist/bscPlugin/hover/HoverProcessor.js +188 -0
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +513 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +3 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +102 -29
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +167 -6
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
- package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
- package/dist/bscPlugin/serialize/BslibManager.js +40 -0
- package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
- package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
- package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
- package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +16 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +123 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +22 -1
- package/dist/bscPlugin/validation/BrsFileValidator.js +316 -29
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +264 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -0
- package/dist/bscPlugin/validation/ProgramValidator.d.ts +10 -0
- package/dist/bscPlugin/validation/ProgramValidator.js +32 -0
- package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +56 -8
- package/dist/bscPlugin/validation/ScopeValidator.js +514 -116
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +2454 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
- package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
- package/dist/cli.js +107 -8
- package/dist/cli.js.map +1 -1
- package/dist/deferred.d.ts +3 -3
- package/dist/deferred.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +8 -2
- package/dist/diagnosticUtils.js +47 -17
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +8 -10
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/AssetFile.d.ts +26 -0
- package/dist/files/AssetFile.js +26 -0
- package/dist/files/AssetFile.js.map +1 -0
- package/dist/files/BrsFile.Class.spec.js +529 -486
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +124 -112
- package/dist/files/BrsFile.js +819 -1131
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1869 -1277
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/BscFile.d.ts +104 -0
- package/dist/files/BscFile.js +16 -0
- package/dist/files/BscFile.js.map +1 -0
- package/dist/files/Factory.d.ts +25 -0
- package/dist/files/Factory.js +22 -0
- package/dist/files/Factory.js.map +1 -0
- package/dist/files/LazyFileData.d.ts +20 -0
- package/dist/files/LazyFileData.js +54 -0
- package/dist/files/LazyFileData.js.map +1 -0
- package/dist/files/LazyFileData.spec.d.ts +1 -0
- package/dist/files/LazyFileData.spec.js +27 -0
- package/dist/files/LazyFileData.spec.js.map +1 -0
- package/dist/files/XmlFile.d.ts +70 -32
- package/dist/files/XmlFile.js +106 -117
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +325 -262
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +49 -41
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.js +104 -40
- package/dist/files/tests/optionalChaning.spec.js.map +1 -1
- package/dist/globalCallables.js +16 -18
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.js +15 -2
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +440 -150
- package/dist/interfaces.js +27 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Character.spec.js +5 -5
- package/dist/lexer/Character.spec.js.map +1 -1
- package/dist/lexer/Lexer.d.ts +12 -5
- package/dist/lexer/Lexer.js +28 -13
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +187 -134
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/Token.d.ts +9 -1
- package/dist/lexer/Token.js +9 -1
- package/dist/lexer/Token.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +9 -0
- package/dist/lexer/TokenKind.js +30 -5
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/AstNode.d.ts +162 -0
- package/dist/parser/AstNode.js +225 -0
- package/dist/parser/AstNode.js.map +1 -0
- package/dist/parser/AstNode.spec.d.ts +1 -0
- package/dist/parser/AstNode.spec.js +165 -0
- package/dist/parser/AstNode.spec.js.map +1 -0
- package/dist/parser/BrsTranspileState.d.ts +4 -7
- package/dist/parser/BrsTranspileState.js +4 -12
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +126 -167
- package/dist/parser/Expression.js +524 -394
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +152 -146
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +45 -196
- package/dist/parser/Parser.js +470 -926
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.d.ts +3 -1
- package/dist/parser/Parser.spec.js +1034 -805
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +9 -8
- package/dist/parser/SGParser.js +10 -8
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +27 -38
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +98 -35
- package/dist/parser/SGTypes.js +169 -99
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/Statement.d.ts +208 -122
- package/dist/parser/Statement.js +599 -364
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +45 -21
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/TranspileState.d.ts +1 -1
- package/dist/parser/TranspileState.js +7 -12
- package/dist/parser/TranspileState.js.map +1 -1
- package/dist/parser/tests/Parser.spec.js +3 -2
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +33 -23
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +25 -20
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +96 -94
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +22 -16
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +8 -8
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +58 -21
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +61 -20
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +8 -8
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +129 -21
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +5 -5
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +36 -36
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +67 -22
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +9 -9
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +123 -81
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +12 -12
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +12 -12
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +10 -10
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/Relational.spec.js +13 -13
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +24 -24
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +221 -81
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +287 -105
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/TypeExpression.spec.js +127 -0
- package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/ConstStatement.spec.d.ts +1 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js +262 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Continue.spec.js +119 -0
- package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
- package/dist/parser/tests/statement/Declaration.spec.js +19 -19
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Dim.spec.js +22 -22
- package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.js +111 -300
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
- package/dist/parser/tests/statement/For.spec.js +9 -10
- package/dist/parser/tests/statement/For.spec.js.map +1 -1
- package/dist/parser/tests/statement/ForEach.spec.js +8 -9
- package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/statement/Function.spec.js +44 -35
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +5 -5
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +20 -20
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +30 -196
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.js +11 -11
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +16 -78
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +107 -90
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +14 -12
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +48 -35
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +6 -6
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/parser/tests/statement/Throw.spec.js +6 -6
- package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +18 -16
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +1 -1
- package/dist/preprocessor/Manifest.js +3 -3
- package/dist/preprocessor/Manifest.js.map +1 -1
- package/dist/preprocessor/Manifest.spec.js +8 -8
- package/dist/preprocessor/Manifest.spec.js.map +1 -1
- package/dist/preprocessor/Preprocessor.d.ts +5 -6
- package/dist/preprocessor/Preprocessor.js +15 -11
- package/dist/preprocessor/Preprocessor.js.map +1 -1
- package/dist/preprocessor/Preprocessor.spec.js +25 -25
- package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
- package/dist/preprocessor/PreprocessorParser.d.ts +1 -1
- package/dist/preprocessor/PreprocessorParser.js +7 -1
- package/dist/preprocessor/PreprocessorParser.js.map +1 -1
- package/dist/preprocessor/PreprocessorParser.spec.js +13 -13
- package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
- package/dist/roku-types/data.json +6544 -10519
- package/dist/roku-types/index.d.ts +662 -1934
- package/dist/types/ArrayType.d.ts +10 -9
- package/dist/types/ArrayType.js +65 -60
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +36 -68
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/AssociativeArrayType.d.ts +11 -0
- package/dist/types/AssociativeArrayType.js +52 -0
- package/dist/types/AssociativeArrayType.js.map +1 -0
- package/dist/types/BaseFunctionType.d.ts +9 -0
- package/dist/types/BaseFunctionType.js +25 -0
- package/dist/types/BaseFunctionType.js.map +1 -0
- package/dist/types/BooleanType.d.ts +8 -5
- package/dist/types/BooleanType.js +14 -7
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BooleanType.spec.js +10 -6
- package/dist/types/BooleanType.spec.js.map +1 -1
- package/dist/types/BscType.d.ts +32 -21
- package/dist/types/BscType.js +118 -21
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BscTypeKind.d.ts +25 -0
- package/dist/types/BscTypeKind.js +30 -0
- package/dist/types/BscTypeKind.js.map +1 -0
- package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
- package/dist/types/BuiltInInterfaceAdder.js +164 -0
- package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
- package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
- package/dist/types/BuiltInInterfaceAdder.spec.js +116 -0
- package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
- package/dist/types/ClassType.d.ts +17 -0
- package/dist/types/ClassType.js +58 -0
- package/dist/types/ClassType.js.map +1 -0
- package/dist/types/ClassType.spec.d.ts +1 -0
- package/dist/types/ClassType.spec.js +77 -0
- package/dist/types/ClassType.spec.js.map +1 -0
- package/dist/types/ComponentType.d.ts +26 -0
- package/dist/types/ComponentType.js +83 -0
- package/dist/types/ComponentType.js.map +1 -0
- package/dist/types/DoubleType.d.ts +8 -5
- package/dist/types/DoubleType.js +18 -16
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DoubleType.spec.js +12 -6
- package/dist/types/DoubleType.spec.js.map +1 -1
- package/dist/types/DynamicType.d.ts +10 -5
- package/dist/types/DynamicType.js +16 -4
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/DynamicType.spec.js +16 -5
- package/dist/types/DynamicType.spec.js.map +1 -1
- package/dist/types/EnumType.d.ts +30 -12
- package/dist/types/EnumType.js +43 -17
- package/dist/types/EnumType.js.map +1 -1
- package/dist/types/EnumType.spec.d.ts +1 -0
- package/dist/types/EnumType.spec.js +33 -0
- package/dist/types/EnumType.spec.js.map +1 -0
- package/dist/types/FloatType.d.ts +8 -5
- package/dist/types/FloatType.js +18 -16
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +4 -6
- package/dist/types/FloatType.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +13 -8
- package/dist/types/FunctionType.js +30 -14
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/InheritableType.d.ts +28 -0
- package/dist/types/InheritableType.js +152 -0
- package/dist/types/InheritableType.js.map +1 -0
- package/dist/types/IntegerType.d.ts +8 -5
- package/dist/types/IntegerType.js +18 -16
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/IntegerType.spec.js +8 -6
- package/dist/types/IntegerType.spec.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +12 -13
- package/dist/types/InterfaceType.js +20 -48
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.js +90 -56
- package/dist/types/InterfaceType.spec.js.map +1 -1
- package/dist/types/InvalidType.d.ts +7 -5
- package/dist/types/InvalidType.js +13 -7
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/InvalidType.spec.js +8 -6
- package/dist/types/InvalidType.spec.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +8 -5
- package/dist/types/LongIntegerType.js +17 -15
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/LongIntegerType.spec.js +10 -6
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/NamespaceType.d.ts +12 -0
- package/dist/types/NamespaceType.js +28 -0
- package/dist/types/NamespaceType.js.map +1 -0
- package/dist/types/ObjectType.d.ts +9 -8
- package/dist/types/ObjectType.js +21 -11
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ObjectType.spec.js +3 -3
- package/dist/types/ObjectType.spec.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +63 -0
- package/dist/types/ReferenceType.js +423 -0
- package/dist/types/ReferenceType.js.map +1 -0
- package/dist/types/ReferenceType.spec.d.ts +1 -0
- package/dist/types/ReferenceType.spec.js +137 -0
- package/dist/types/ReferenceType.spec.js.map +1 -0
- package/dist/types/StringType.d.ts +11 -5
- package/dist/types/StringType.js +18 -7
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/StringType.spec.js +3 -5
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +22 -17
- package/dist/types/TypedFunctionType.js +78 -60
- package/dist/types/TypedFunctionType.js.map +1 -1
- package/dist/types/TypedFunctionType.spec.js +105 -20
- package/dist/types/TypedFunctionType.spec.js.map +1 -1
- package/dist/types/UninitializedType.d.ts +8 -6
- package/dist/types/UninitializedType.js +13 -7
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/UnionType.d.ts +20 -0
- package/dist/types/UnionType.js +123 -0
- package/dist/types/UnionType.js.map +1 -0
- package/dist/types/UnionType.spec.d.ts +1 -0
- package/dist/types/UnionType.spec.js +130 -0
- package/dist/types/UnionType.spec.js.map +1 -0
- package/dist/types/VoidType.d.ts +8 -5
- package/dist/types/VoidType.js +14 -7
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/VoidType.spec.js +3 -3
- package/dist/types/VoidType.spec.js.map +1 -1
- package/dist/types/helper.spec.d.ts +1 -0
- package/dist/types/helper.spec.js +145 -0
- package/dist/types/helper.spec.js.map +1 -0
- package/dist/types/helpers.d.ts +19 -37
- package/dist/types/helpers.js +159 -99
- package/dist/types/helpers.js.map +1 -1
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.js +39 -0
- package/dist/types/index.js.map +1 -0
- package/dist/util.d.ts +167 -131
- package/dist/util.js +890 -350
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +7 -25
- package/dist/validators/ClassValidator.js +103 -194
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +165 -149
- package/dist/astUtils/AstEditor.js.map +0 -1
- package/dist/astUtils/AstEditor.spec.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +0 -8
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +0 -40
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -32
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
- package/dist/parser/SGTypes.spec.js +0 -351
- package/dist/parser/SGTypes.spec.js.map +0 -1
- package/dist/types/CustomType.d.ts +0 -12
- package/dist/types/CustomType.js +0 -44
- package/dist/types/CustomType.js.map +0 -1
- package/dist/types/LazyType.d.ts +0 -16
- package/dist/types/LazyType.js +0 -44
- package/dist/types/LazyType.js.map +0 -1
- /package/dist/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
- /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → completions/CompletionsProcessor.spec.d.ts} +0 -0
- /package/dist/{parser/SGTypes.spec.d.ts → bscPlugin/hover/HoverProcessor.spec.d.ts} +0 -0
package/dist/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.util = exports.standardizePath = exports.Util = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const fsExtra = require("fs-extra");
|
|
6
6
|
const jsonc_parser_1 = require("jsonc-parser");
|
|
@@ -13,9 +13,7 @@ const BooleanType_1 = require("./types/BooleanType");
|
|
|
13
13
|
const DoubleType_1 = require("./types/DoubleType");
|
|
14
14
|
const DynamicType_1 = require("./types/DynamicType");
|
|
15
15
|
const FloatType_1 = require("./types/FloatType");
|
|
16
|
-
const TypedFunctionType_1 = require("./types/TypedFunctionType");
|
|
17
16
|
const IntegerType_1 = require("./types/IntegerType");
|
|
18
|
-
const InvalidType_1 = require("./types/InvalidType");
|
|
19
17
|
const LongIntegerType_1 = require("./types/LongIntegerType");
|
|
20
18
|
const ObjectType_1 = require("./types/ObjectType");
|
|
21
19
|
const StringType_1 = require("./types/StringType");
|
|
@@ -26,16 +24,46 @@ const TokenKind_1 = require("./lexer/TokenKind");
|
|
|
26
24
|
const reflection_1 = require("./astUtils/reflection");
|
|
27
25
|
const visitors_1 = require("./astUtils/visitors");
|
|
28
26
|
const source_map_1 = require("source-map");
|
|
29
|
-
const
|
|
30
|
-
const
|
|
27
|
+
const requireRelative = require("require-relative");
|
|
28
|
+
const AstNode_1 = require("./parser/AstNode");
|
|
29
|
+
const creators_1 = require("./astUtils/creators");
|
|
31
30
|
const FunctionType_1 = require("./types/FunctionType");
|
|
31
|
+
const ArrayType_1 = require("./types/ArrayType");
|
|
32
|
+
const SymbolTable_1 = require("./SymbolTable");
|
|
33
|
+
const AssociativeArrayType_1 = require("./types/AssociativeArrayType");
|
|
34
|
+
const ComponentType_1 = require("./types/ComponentType");
|
|
35
|
+
const diagnosticUtils_1 = require("./diagnosticUtils");
|
|
36
|
+
const ReferenceType_1 = require("./types/ReferenceType");
|
|
37
|
+
const UnionType_1 = require("./types/UnionType");
|
|
32
38
|
class Util {
|
|
39
|
+
constructor() {
|
|
40
|
+
/**
|
|
41
|
+
* A cache of `Range` objects. The key is a 52bit integer created from the 4 range integers and leveraging bitshifting.
|
|
42
|
+
* The whole point of this cache is to reduce garbage collection churn, so we didn't want to use string concatenation for the key
|
|
43
|
+
*/
|
|
44
|
+
this.rangeCache = new Map();
|
|
45
|
+
/**
|
|
46
|
+
* A cache of `Position` objects. The key is a 26bit integer created from line and character and leveraging bitshifting
|
|
47
|
+
* The whole point of this cache is to reduce garbage collection churn, so we didn't want to use string concatenation for the key
|
|
48
|
+
*/
|
|
49
|
+
this.positionCache = new Map();
|
|
50
|
+
}
|
|
33
51
|
clearConsole() {
|
|
34
52
|
// process.stdout.write('\x1Bc');
|
|
35
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns the number of parent directories in the filPath
|
|
56
|
+
*/
|
|
57
|
+
getParentDirectoryCount(filePath) {
|
|
58
|
+
if (!filePath) {
|
|
59
|
+
return -1;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return filePath.replace(/^pkg:/, '').split(/[\\\/]/).length - 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
36
65
|
/**
|
|
37
66
|
* Determine if the file exists
|
|
38
|
-
* @param filePath
|
|
39
67
|
*/
|
|
40
68
|
async pathExists(filePath) {
|
|
41
69
|
if (!filePath) {
|
|
@@ -47,7 +75,6 @@ class Util {
|
|
|
47
75
|
}
|
|
48
76
|
/**
|
|
49
77
|
* Determine if the file exists
|
|
50
|
-
* @param filePath
|
|
51
78
|
*/
|
|
52
79
|
pathExistsSync(filePath) {
|
|
53
80
|
if (!filePath) {
|
|
@@ -61,18 +88,16 @@ class Util {
|
|
|
61
88
|
* Determine if this path is a directory
|
|
62
89
|
*/
|
|
63
90
|
isDirectorySync(dirPath) {
|
|
64
|
-
return fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
|
|
91
|
+
return dirPath !== undefined && fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
|
|
65
92
|
}
|
|
66
93
|
/**
|
|
67
94
|
* Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
|
|
68
95
|
*/
|
|
69
96
|
sanitizePkgPath(pkgPath) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
return pkgPath;
|
|
97
|
+
//convert all slashes to forwardslash
|
|
98
|
+
pkgPath = pkgPath.replace(/[\/\\]+/g, '/');
|
|
99
|
+
//ensure every path has the leading pkg:/
|
|
100
|
+
return 'pkg:/' + pkgPath.replace(/^pkg:\//i, '');
|
|
76
101
|
}
|
|
77
102
|
/**
|
|
78
103
|
* Determine if the given path starts with a protocol
|
|
@@ -80,9 +105,15 @@ class Util {
|
|
|
80
105
|
startsWithProtocol(path) {
|
|
81
106
|
return !!/^[-a-z]+:\//i.exec(path);
|
|
82
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
|
|
110
|
+
* @deprecated use `sanitizePkgPath instead. Will be removed in v1
|
|
111
|
+
*/
|
|
112
|
+
getRokuPkgPath(pkgPath) {
|
|
113
|
+
return this.sanitizePkgPath(pkgPath);
|
|
114
|
+
}
|
|
83
115
|
/**
|
|
84
116
|
* Given a path to a file/directory, replace all path separators with the current system's version.
|
|
85
|
-
* @param filePath
|
|
86
117
|
*/
|
|
87
118
|
pathSepNormalize(filePath, separator) {
|
|
88
119
|
if (!filePath) {
|
|
@@ -94,7 +125,7 @@ class Util {
|
|
|
94
125
|
/**
|
|
95
126
|
* Find the path to the config file.
|
|
96
127
|
* If the config file path doesn't exist
|
|
97
|
-
* @param
|
|
128
|
+
* @param cwd the current working directory where the search for configs should begin
|
|
98
129
|
*/
|
|
99
130
|
getConfigFilePath(cwd) {
|
|
100
131
|
cwd = cwd !== null && cwd !== void 0 ? cwd : process.cwd();
|
|
@@ -128,13 +159,13 @@ class Util {
|
|
|
128
159
|
colIndex++;
|
|
129
160
|
}
|
|
130
161
|
}
|
|
131
|
-
return
|
|
162
|
+
return exports.util.createRange(lineIndex, colIndex, lineIndex, colIndex + length);
|
|
132
163
|
}
|
|
133
164
|
/**
|
|
134
165
|
* Load the contents of a config file.
|
|
135
166
|
* If the file extends another config, this will load the base config as well.
|
|
136
|
-
* @param configFilePath
|
|
137
|
-
* @param parentProjectPaths
|
|
167
|
+
* @param configFilePath the relative or absolute path to a brighterscript config json file
|
|
168
|
+
* @param parentProjectPaths a list of parent config files. This is used by this method to recursively build the config list
|
|
138
169
|
*/
|
|
139
170
|
loadConfigFile(configFilePath, parentProjectPaths, cwd = process.cwd()) {
|
|
140
171
|
var _a;
|
|
@@ -203,7 +234,8 @@ class Util {
|
|
|
203
234
|
}
|
|
204
235
|
/**
|
|
205
236
|
* Convert relative paths to absolute paths, relative to the given directory. Also de-dupes the paths. Modifies the array in-place
|
|
206
|
-
* @param
|
|
237
|
+
* @param collection usually a bsconfig.
|
|
238
|
+
* @param key a key of the config to read paths from (usually this is `'plugins'` or `'require'`)
|
|
207
239
|
* @param relativeDir the path to the folder where the paths should be resolved relative to. This should be an absolute path
|
|
208
240
|
*/
|
|
209
241
|
resolvePathsRelativeTo(collection, key, relativeDir) {
|
|
@@ -221,8 +253,8 @@ class Util {
|
|
|
221
253
|
}
|
|
222
254
|
/**
|
|
223
255
|
* Do work within the scope of a changed current working directory
|
|
224
|
-
* @param targetCwd
|
|
225
|
-
* @param callback
|
|
256
|
+
* @param targetCwd the cwd where the work should be performed
|
|
257
|
+
* @param callback a function to call when the cwd has been changed to `targetCwd`
|
|
226
258
|
*/
|
|
227
259
|
cwdWork(targetCwd, callback) {
|
|
228
260
|
let originalCwd = process.cwd();
|
|
@@ -244,16 +276,20 @@ class Util {
|
|
|
244
276
|
throw err;
|
|
245
277
|
}
|
|
246
278
|
else {
|
|
279
|
+
//justification: `result` is set as long as `err` is not set and vice versa
|
|
247
280
|
return result;
|
|
248
281
|
}
|
|
249
282
|
}
|
|
250
283
|
/**
|
|
251
284
|
* Given a BsConfig object, start with defaults,
|
|
252
285
|
* merge with bsconfig.json and the provided options.
|
|
253
|
-
* @param config
|
|
286
|
+
* @param config a bsconfig object to use as the baseline for the resulting config
|
|
254
287
|
*/
|
|
255
288
|
normalizeAndResolveConfig(config) {
|
|
256
289
|
let result = this.normalizeConfig({});
|
|
290
|
+
if (config === null || config === void 0 ? void 0 : config.noProject) {
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
257
293
|
//if no options were provided, try to find a bsconfig.json file
|
|
258
294
|
if (!config || !config.project) {
|
|
259
295
|
result.project = this.getConfigFilePath(config === null || config === void 0 ? void 0 : config.cwd);
|
|
@@ -263,7 +299,7 @@ class Util {
|
|
|
263
299
|
result.project = config.project;
|
|
264
300
|
}
|
|
265
301
|
if (result.project) {
|
|
266
|
-
let configFile = this.loadConfigFile(result.project,
|
|
302
|
+
let configFile = this.loadConfigFile(result.project, undefined, config === null || config === void 0 ? void 0 : config.cwd);
|
|
267
303
|
result = Object.assign(result, configFile);
|
|
268
304
|
}
|
|
269
305
|
//override the defaults with the specified options
|
|
@@ -272,43 +308,59 @@ class Util {
|
|
|
272
308
|
}
|
|
273
309
|
/**
|
|
274
310
|
* Set defaults for any missing items
|
|
275
|
-
* @param config
|
|
311
|
+
* @param config a bsconfig object to use as the baseline for the resulting config
|
|
276
312
|
*/
|
|
277
313
|
normalizeConfig(config) {
|
|
278
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
279
|
-
config = config
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
config.createPackage = config.createPackage === false ? false : true;
|
|
285
|
-
let rootFolderName = path.basename(config.cwd);
|
|
286
|
-
config.outFile = (_c = config.outFile) !== null && _c !== void 0 ? _c : `./out/${rootFolderName}.zip`;
|
|
287
|
-
config.sourceMap = config.sourceMap === true;
|
|
288
|
-
config.username = (_d = config.username) !== null && _d !== void 0 ? _d : 'rokudev';
|
|
289
|
-
config.watch = config.watch === true ? true : false;
|
|
290
|
-
config.emitFullPaths = config.emitFullPaths === true ? true : false;
|
|
291
|
-
config.retainStagingFolder = config.retainStagingFolder === true ? true : false;
|
|
292
|
-
config.copyToStaging = config.copyToStaging === false ? false : true;
|
|
293
|
-
config.ignoreErrorCodes = (_e = config.ignoreErrorCodes) !== null && _e !== void 0 ? _e : [];
|
|
294
|
-
config.diagnosticFilters = (_f = config.diagnosticFilters) !== null && _f !== void 0 ? _f : [];
|
|
295
|
-
config.plugins = (_g = config.plugins) !== null && _g !== void 0 ? _g : [];
|
|
296
|
-
config.autoImportComponentScript = config.autoImportComponentScript === true ? true : false;
|
|
297
|
-
config.showDiagnosticsInConsole = config.showDiagnosticsInConsole === false ? false : true;
|
|
298
|
-
config.sourceRoot = config.sourceRoot ? standardizePath(config.sourceRoot) : undefined;
|
|
299
|
-
config.allowBrighterScriptInBrightScript = config.allowBrighterScriptInBrightScript === true ? true : false;
|
|
300
|
-
config.emitDefinitions = config.emitDefinitions === true ? true : false;
|
|
314
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
315
|
+
config = config !== null && config !== void 0 ? config : {};
|
|
316
|
+
const cwd = (_a = config.cwd) !== null && _a !== void 0 ? _a : process.cwd();
|
|
317
|
+
const rootFolderName = path.basename(cwd);
|
|
318
|
+
const retainStagingDir = ((_b = config.retainStagingDir) !== null && _b !== void 0 ? _b : config.retainStagingDir) === true ? true : false;
|
|
319
|
+
let logLevel = Logger_1.LogLevel.log;
|
|
301
320
|
if (typeof config.logLevel === 'string') {
|
|
302
|
-
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
321
|
+
logLevel = (_c = Logger_1.LogLevel[config.logLevel.toLowerCase()]) !== null && _c !== void 0 ? _c : Logger_1.LogLevel.log;
|
|
322
|
+
}
|
|
323
|
+
let bslibDestinationDir = (_d = config.bslibDestinationDir) !== null && _d !== void 0 ? _d : 'source';
|
|
324
|
+
if (bslibDestinationDir !== 'source') {
|
|
325
|
+
// strip leading and trailing slashes
|
|
326
|
+
bslibDestinationDir = bslibDestinationDir.replace(/^(\/*)(.*?)(\/*)$/, '$2');
|
|
327
|
+
}
|
|
328
|
+
const configWithDefaults = {
|
|
329
|
+
cwd: cwd,
|
|
330
|
+
deploy: config.deploy === true ? true : false,
|
|
331
|
+
//use default files array from rokuDeploy
|
|
332
|
+
files: (_e = config.files) !== null && _e !== void 0 ? _e : [...roku_deploy_1.DefaultFiles],
|
|
333
|
+
createPackage: config.createPackage === false ? false : true,
|
|
334
|
+
outFile: (_f = config.outFile) !== null && _f !== void 0 ? _f : `./out/${rootFolderName}.zip`,
|
|
335
|
+
sourceMap: config.sourceMap === true,
|
|
336
|
+
username: (_g = config.username) !== null && _g !== void 0 ? _g : 'rokudev',
|
|
337
|
+
watch: config.watch === true ? true : false,
|
|
338
|
+
emitFullPaths: config.emitFullPaths === true ? true : false,
|
|
339
|
+
retainStagingDir: retainStagingDir,
|
|
340
|
+
copyToStaging: config.copyToStaging === false ? false : true,
|
|
341
|
+
ignoreErrorCodes: (_h = config.ignoreErrorCodes) !== null && _h !== void 0 ? _h : [],
|
|
342
|
+
diagnosticSeverityOverrides: (_j = config.diagnosticSeverityOverrides) !== null && _j !== void 0 ? _j : {},
|
|
343
|
+
diagnosticFilters: (_k = config.diagnosticFilters) !== null && _k !== void 0 ? _k : [],
|
|
344
|
+
plugins: (_l = config.plugins) !== null && _l !== void 0 ? _l : [],
|
|
345
|
+
pruneEmptyCodeFiles: config.pruneEmptyCodeFiles === true ? true : false,
|
|
346
|
+
autoImportComponentScript: config.autoImportComponentScript === true ? true : false,
|
|
347
|
+
showDiagnosticsInConsole: config.showDiagnosticsInConsole === false ? false : true,
|
|
348
|
+
sourceRoot: config.sourceRoot ? standardizePath(config.sourceRoot) : undefined,
|
|
349
|
+
allowBrighterScriptInBrightScript: config.allowBrighterScriptInBrightScript === true ? true : false,
|
|
350
|
+
emitDefinitions: config.emitDefinitions === true ? true : false,
|
|
351
|
+
removeParameterTypes: config.removeParameterTypes === true ? true : false,
|
|
352
|
+
logLevel: logLevel,
|
|
353
|
+
bslibDestinationDir: bslibDestinationDir
|
|
354
|
+
};
|
|
355
|
+
//mutate `config` in case anyone is holding a reference to the incomplete one
|
|
356
|
+
const merged = Object.assign(config, configWithDefaults);
|
|
357
|
+
return merged;
|
|
306
358
|
}
|
|
307
359
|
/**
|
|
308
360
|
* Get the root directory from options.
|
|
309
361
|
* Falls back to options.cwd.
|
|
310
362
|
* Falls back to process.cwd
|
|
311
|
-
* @param options
|
|
363
|
+
* @param options a bsconfig object
|
|
312
364
|
*/
|
|
313
365
|
getRootDir(options) {
|
|
314
366
|
if (!options) {
|
|
@@ -320,19 +372,8 @@ class Util {
|
|
|
320
372
|
rootDir = path.resolve(cwd, rootDir);
|
|
321
373
|
return rootDir;
|
|
322
374
|
}
|
|
323
|
-
/**
|
|
324
|
-
* Format a string with placeholders replaced by argument indexes
|
|
325
|
-
* @param subject
|
|
326
|
-
* @param params
|
|
327
|
-
*/
|
|
328
|
-
stringFormat(subject, ...args) {
|
|
329
|
-
return subject.replace(/{(\d+)}/g, (match, num) => {
|
|
330
|
-
return typeof args[num] !== 'undefined' ? args[num] : match;
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
375
|
/**
|
|
334
376
|
* Given a list of callables as a dictionary indexed by their full name (namespace included, transpiled to underscore-separated.
|
|
335
|
-
* @param callables
|
|
336
377
|
*/
|
|
337
378
|
getCallableContainersByLowerName(callables) {
|
|
338
379
|
//find duplicate functions
|
|
@@ -352,32 +393,39 @@ class Util {
|
|
|
352
393
|
}
|
|
353
394
|
/**
|
|
354
395
|
* Split a file by newline characters (LF or CRLF)
|
|
355
|
-
* @param text
|
|
356
396
|
*/
|
|
357
397
|
getLines(text) {
|
|
358
398
|
return text.split(/\r?\n/);
|
|
359
399
|
}
|
|
360
400
|
/**
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
* @param targetPath a full pkgPath, or a path relative to the containing file
|
|
401
|
+
* Given an absolute path to a source file, and a target path,
|
|
402
|
+
* compute the pkg path for the target relative to the source file's location
|
|
364
403
|
*/
|
|
365
|
-
getPkgPathFromTarget(
|
|
404
|
+
getPkgPathFromTarget(containingFilePathAbsolute, targetPath) {
|
|
366
405
|
var _a;
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
406
|
+
// https://regex101.com/r/w7CG2N/1
|
|
407
|
+
const regexp = /^(?:pkg|libpkg):(\/)?/i;
|
|
408
|
+
const [fullScheme, slash] = (_a = regexp.exec(targetPath)) !== null && _a !== void 0 ? _a : [];
|
|
409
|
+
//if the target starts with 'pkg:' or 'libpkg:' then it's an absolute path. Return as is
|
|
410
|
+
if (slash) {
|
|
411
|
+
targetPath = targetPath.substring(fullScheme.length);
|
|
412
|
+
if (targetPath === '') {
|
|
413
|
+
return null;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
return path.normalize(targetPath);
|
|
417
|
+
}
|
|
371
418
|
}
|
|
372
|
-
//if the
|
|
373
|
-
if (
|
|
374
|
-
return
|
|
419
|
+
//if the path is exactly `pkg:` or `libpkg:`
|
|
420
|
+
if (targetPath === fullScheme && !slash) {
|
|
421
|
+
return null;
|
|
375
422
|
}
|
|
423
|
+
//remove the filename
|
|
424
|
+
let containingFolder = path.normalize(path.dirname(containingFilePathAbsolute));
|
|
376
425
|
//start with the containing folder, split by slash
|
|
377
|
-
|
|
378
|
-
let result = containingFolder.split(/[\\/]/);
|
|
426
|
+
let result = containingFolder.split(path.sep);
|
|
379
427
|
//split on slash
|
|
380
|
-
let targetParts = path.
|
|
428
|
+
let targetParts = path.normalize(targetPath).split(path.sep);
|
|
381
429
|
for (let part of targetParts) {
|
|
382
430
|
if (part === '' || part === '.') {
|
|
383
431
|
//do nothing, it means current directory
|
|
@@ -391,7 +439,7 @@ class Util {
|
|
|
391
439
|
result.push(part);
|
|
392
440
|
}
|
|
393
441
|
}
|
|
394
|
-
return result.join(
|
|
442
|
+
return result.join(path.sep);
|
|
395
443
|
}
|
|
396
444
|
/**
|
|
397
445
|
* Compute the relative path from the source file to the target file
|
|
@@ -444,9 +492,19 @@ class Util {
|
|
|
444
492
|
}
|
|
445
493
|
}
|
|
446
494
|
/**
|
|
447
|
-
*
|
|
495
|
+
* Do `a` and `b` overlap by at least one character. This returns false if they are at the edges. Here's some examples:
|
|
496
|
+
* ```
|
|
497
|
+
* | true | true | true | true | true | false | false | false | false |
|
|
498
|
+
* |------|------|------|------|------|-------|-------|-------|-------|
|
|
499
|
+
* | aa | aaa | aaa | aaa | a | aa | aa | a | a |
|
|
500
|
+
* | bbb | bb | bbb | b | bbb | bb | bb | b | a |
|
|
501
|
+
* ```
|
|
448
502
|
*/
|
|
449
503
|
rangesIntersect(a, b) {
|
|
504
|
+
//stop if the either range is misisng
|
|
505
|
+
if (!a || !b) {
|
|
506
|
+
return false;
|
|
507
|
+
}
|
|
450
508
|
// Check if `a` is before `b`
|
|
451
509
|
if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character <= b.start.character)) {
|
|
452
510
|
return false;
|
|
@@ -458,16 +516,43 @@ class Util {
|
|
|
458
516
|
// These ranges must intersect
|
|
459
517
|
return true;
|
|
460
518
|
}
|
|
519
|
+
/**
|
|
520
|
+
* Do `a` and `b` overlap by at least one character or touch at the edges
|
|
521
|
+
* ```
|
|
522
|
+
* | true | true | true | true | true | true | true | false | false |
|
|
523
|
+
* |------|------|------|------|------|-------|-------|-------|-------|
|
|
524
|
+
* | aa | aaa | aaa | aaa | a | aa | aa | a | a |
|
|
525
|
+
* | bbb | bb | bbb | b | bbb | bb | bb | b | a |
|
|
526
|
+
* ```
|
|
527
|
+
*/
|
|
528
|
+
rangesIntersectOrTouch(a, b) {
|
|
529
|
+
//stop if the either range is misisng
|
|
530
|
+
if (!a || !b) {
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
// Check if `a` is before `b`
|
|
534
|
+
if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character < b.start.character)) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
// Check if `b` is before `a`
|
|
538
|
+
if (b.end.line < a.start.line || (b.end.line === a.start.line && b.end.character < a.start.character)) {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
// These ranges must intersect
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
461
544
|
/**
|
|
462
545
|
* Test if `position` is in `range`. If the position is at the edges, will return true.
|
|
463
546
|
* Adapted from core vscode
|
|
464
|
-
* @param range
|
|
465
|
-
* @param position
|
|
466
547
|
*/
|
|
467
548
|
rangeContains(range, position) {
|
|
468
549
|
return this.comparePositionToRange(position, range) === 0;
|
|
469
550
|
}
|
|
470
551
|
comparePositionToRange(position, range) {
|
|
552
|
+
//stop if the either range is misisng
|
|
553
|
+
if (!position || !range) {
|
|
554
|
+
return 0;
|
|
555
|
+
}
|
|
471
556
|
if (position.line < range.start.line || (position.line === range.start.line && position.character < range.start.character)) {
|
|
472
557
|
return -1;
|
|
473
558
|
}
|
|
@@ -476,9 +561,67 @@ class Util {
|
|
|
476
561
|
}
|
|
477
562
|
return 0;
|
|
478
563
|
}
|
|
564
|
+
/**
|
|
565
|
+
* Combine all the documentation found before a token (i.e. comment tokens)
|
|
566
|
+
*/
|
|
567
|
+
getTokenDocumentation(tokens, token) {
|
|
568
|
+
const comments = [];
|
|
569
|
+
const idx = tokens === null || tokens === void 0 ? void 0 : tokens.indexOf(token);
|
|
570
|
+
if (!idx || idx === -1) {
|
|
571
|
+
return undefined;
|
|
572
|
+
}
|
|
573
|
+
for (let i = idx - 1; i >= 0; i--) {
|
|
574
|
+
const token = tokens[i];
|
|
575
|
+
//skip whitespace and newline chars
|
|
576
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
577
|
+
comments.push(token);
|
|
578
|
+
}
|
|
579
|
+
else if (token.kind === TokenKind_1.TokenKind.Newline || token.kind === TokenKind_1.TokenKind.Whitespace) {
|
|
580
|
+
//skip these tokens
|
|
581
|
+
continue;
|
|
582
|
+
//any other token means there are no more comments
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
if (comments.length > 0) {
|
|
589
|
+
return comments.reverse().map(x => x.text.replace(/^('|rem)/i, '').trim()).map(line => {
|
|
590
|
+
if (line.startsWith('@')) {
|
|
591
|
+
// Handle jsdoc/brightscriptdoc tags specially
|
|
592
|
+
// make sure they are on their own markdown line, and add italics
|
|
593
|
+
const firstSpaceIndex = line.indexOf(' ');
|
|
594
|
+
if (firstSpaceIndex === -1) {
|
|
595
|
+
return `\n_${line}_`;
|
|
596
|
+
}
|
|
597
|
+
const firstWord = line.substring(0, firstSpaceIndex);
|
|
598
|
+
return `\n_${firstWord}_ ${line.substring(firstSpaceIndex + 1)}`;
|
|
599
|
+
}
|
|
600
|
+
return line;
|
|
601
|
+
}).join('\n');
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Combine all the documentation for a node - uses the AstNode's leadingTrivia property
|
|
606
|
+
*/
|
|
607
|
+
getNodeDocumentation(node) {
|
|
608
|
+
if (!node) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const leadingTrivia = node.getLeadingTrivia();
|
|
612
|
+
return this.getTokenDocumentation(leadingTrivia, leadingTrivia[leadingTrivia.length - 1]);
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Prefixes a component name so it can be used as type in the symbol table, without polluting available symbols
|
|
616
|
+
*
|
|
617
|
+
* @param sgNodeName the Name of the component
|
|
618
|
+
* @returns the node name, prefixed with `roSGNode`
|
|
619
|
+
*/
|
|
620
|
+
getSgNodeTypeName(sgNodeName) {
|
|
621
|
+
return 'roSGNode' + sgNodeName;
|
|
622
|
+
}
|
|
479
623
|
/**
|
|
480
624
|
* Parse an xml file and get back a javascript object containing its results
|
|
481
|
-
* @param text
|
|
482
625
|
*/
|
|
483
626
|
parseXml(text) {
|
|
484
627
|
return new Promise((resolve, reject) => {
|
|
@@ -510,7 +653,6 @@ class Util {
|
|
|
510
653
|
}
|
|
511
654
|
/**
|
|
512
655
|
* Given a URI, convert that to a regular fs path
|
|
513
|
-
* @param uri
|
|
514
656
|
*/
|
|
515
657
|
uriToPath(uri) {
|
|
516
658
|
let parsedPath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
@@ -525,7 +667,6 @@ class Util {
|
|
|
525
667
|
}
|
|
526
668
|
/**
|
|
527
669
|
* Force the drive letter to lower case
|
|
528
|
-
* @param fullPath
|
|
529
670
|
*/
|
|
530
671
|
driveLetterToLower(fullPath) {
|
|
531
672
|
if (fullPath) {
|
|
@@ -540,6 +681,19 @@ class Util {
|
|
|
540
681
|
}
|
|
541
682
|
return fullPath;
|
|
542
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Replace the first instance of `search` in `subject` with `replacement`
|
|
686
|
+
*/
|
|
687
|
+
replaceCaseInsensitive(subject, search, replacement) {
|
|
688
|
+
let idx = subject.toLowerCase().indexOf(search.toLowerCase());
|
|
689
|
+
if (idx > -1) {
|
|
690
|
+
let result = subject.substring(0, idx) + replacement + subject.substring(idx + search.length);
|
|
691
|
+
return result;
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
return subject;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
543
697
|
/**
|
|
544
698
|
* Determine if two arrays containing primitive values are equal.
|
|
545
699
|
* This considers order and compares by equality.
|
|
@@ -557,14 +711,12 @@ class Util {
|
|
|
557
711
|
}
|
|
558
712
|
/**
|
|
559
713
|
* Given a file path, convert it to a URI string
|
|
560
|
-
* @param srcPath The absolute path to the source file on disk
|
|
561
714
|
*/
|
|
562
|
-
pathToUri(
|
|
563
|
-
return vscode_uri_1.URI.file(
|
|
715
|
+
pathToUri(filePath) {
|
|
716
|
+
return vscode_uri_1.URI.file(filePath).toString();
|
|
564
717
|
}
|
|
565
718
|
/**
|
|
566
719
|
* Get the outDir from options, taking into account cwd and absolute outFile paths
|
|
567
|
-
* @param options
|
|
568
720
|
*/
|
|
569
721
|
getOutDir(options) {
|
|
570
722
|
options = this.normalizeConfig(options);
|
|
@@ -586,8 +738,7 @@ class Util {
|
|
|
586
738
|
}
|
|
587
739
|
/**
|
|
588
740
|
* Given a path to a brs file, compute the path to a theoretical d.bs file.
|
|
589
|
-
* Only `.brs` files can have
|
|
590
|
-
* @param brsSrcPath The absolute path to the .brs source file on disk
|
|
741
|
+
* Only `.brs` files can have typedef path, so return undefined for everything else
|
|
591
742
|
*/
|
|
592
743
|
getTypedefPath(brsSrcPath) {
|
|
593
744
|
const typedefPath = brsSrcPath
|
|
@@ -602,24 +753,23 @@ class Util {
|
|
|
602
753
|
}
|
|
603
754
|
/**
|
|
604
755
|
* Determine whether this diagnostic should be supressed or not, based on brs comment-flags
|
|
605
|
-
* @param diagnostic
|
|
606
756
|
*/
|
|
607
757
|
diagnosticIsSuppressed(diagnostic) {
|
|
608
758
|
var _a, _b;
|
|
609
759
|
const diagnosticCode = typeof diagnostic.code === 'string' ? diagnostic.code.toLowerCase() : diagnostic.code;
|
|
610
760
|
for (let flag of (_b = (_a = diagnostic.file) === null || _a === void 0 ? void 0 : _a.commentFlags) !== null && _b !== void 0 ? _b : []) {
|
|
611
761
|
//this diagnostic is affected by this flag
|
|
612
|
-
if (this.rangeContains(flag.affectedRange, diagnostic.range.start)) {
|
|
762
|
+
if (diagnostic.range && this.rangeContains(flag.affectedRange, diagnostic.range.start)) {
|
|
613
763
|
//if the flag acts upon this diagnostic's code
|
|
614
|
-
if (flag.codes === null || flag.codes.includes(diagnosticCode)) {
|
|
764
|
+
if (flag.codes === null || (diagnosticCode !== undefined && flag.codes.includes(diagnosticCode))) {
|
|
615
765
|
return true;
|
|
616
766
|
}
|
|
617
767
|
}
|
|
618
768
|
}
|
|
769
|
+
return false;
|
|
619
770
|
}
|
|
620
771
|
/**
|
|
621
|
-
* Walks up the chain
|
|
622
|
-
* @param currentPath
|
|
772
|
+
* Walks up the chain to find the closest bsconfig.json file
|
|
623
773
|
*/
|
|
624
774
|
async findClosestConfigFile(currentPath) {
|
|
625
775
|
//make the path absolute
|
|
@@ -645,7 +795,7 @@ class Util {
|
|
|
645
795
|
}
|
|
646
796
|
/**
|
|
647
797
|
* Set a timeout for the specified milliseconds, and resolve the promise once the timeout is finished.
|
|
648
|
-
* @param milliseconds
|
|
798
|
+
* @param milliseconds the minimum number of milliseconds to sleep for
|
|
649
799
|
*/
|
|
650
800
|
sleep(milliseconds) {
|
|
651
801
|
return new Promise((resolve) => {
|
|
@@ -660,11 +810,11 @@ class Util {
|
|
|
660
810
|
}
|
|
661
811
|
/**
|
|
662
812
|
* Given an array, map and then flatten
|
|
663
|
-
* @param
|
|
664
|
-
* @param
|
|
813
|
+
* @param array the array to flatMap over
|
|
814
|
+
* @param callback a function that is called for every array item
|
|
665
815
|
*/
|
|
666
|
-
flatMap(array,
|
|
667
|
-
return Array.prototype.concat.apply([], array.map(
|
|
816
|
+
flatMap(array, callback) {
|
|
817
|
+
return Array.prototype.concat.apply([], array.map(callback));
|
|
668
818
|
}
|
|
669
819
|
/**
|
|
670
820
|
* Determines if the position is greater than the range. This means
|
|
@@ -708,8 +858,6 @@ class Util {
|
|
|
708
858
|
}
|
|
709
859
|
/**
|
|
710
860
|
* If the two items have lines that touch
|
|
711
|
-
* @param first
|
|
712
|
-
* @param second
|
|
713
861
|
*/
|
|
714
862
|
linesTouch(first, second) {
|
|
715
863
|
if (first && second && (first.range.start.line === second.range.start.line ||
|
|
@@ -739,7 +887,8 @@ class Util {
|
|
|
739
887
|
*/
|
|
740
888
|
getScriptImportAtPosition(scriptImports, position) {
|
|
741
889
|
let scriptImport = scriptImports.find((x) => {
|
|
742
|
-
return x.filePathRange
|
|
890
|
+
return x.filePathRange &&
|
|
891
|
+
x.filePathRange.start.line === position.line &&
|
|
743
892
|
//column between start and end
|
|
744
893
|
position.character >= x.filePathRange.start.character &&
|
|
745
894
|
position.character <= x.filePathRange.end.character;
|
|
@@ -783,38 +932,41 @@ class Util {
|
|
|
783
932
|
rangeLines.push(lines[i]);
|
|
784
933
|
}
|
|
785
934
|
const lastLine = rangeLines.pop();
|
|
786
|
-
|
|
935
|
+
if (lastLine !== undefined) {
|
|
936
|
+
rangeLines.push(lastLine.substring(0, endCharacter));
|
|
937
|
+
}
|
|
787
938
|
return rangeLines.join('\n');
|
|
788
939
|
}
|
|
789
940
|
/**
|
|
790
|
-
* Helper for creating `
|
|
941
|
+
* Helper for creating `Location` objects. Prefer using this function because vscode-languageserver's `Location.create()` is significantly slower at scale
|
|
791
942
|
*/
|
|
792
|
-
|
|
943
|
+
createLocation(uri, range) {
|
|
793
944
|
return {
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
character: startCharacter
|
|
797
|
-
},
|
|
798
|
-
end: {
|
|
799
|
-
line: endLine,
|
|
800
|
-
character: endCharacter
|
|
801
|
-
}
|
|
945
|
+
uri: uri,
|
|
946
|
+
range: range
|
|
802
947
|
};
|
|
803
948
|
}
|
|
949
|
+
/**
|
|
950
|
+
* Helper for creating `Range` objects. Prefer using this function because vscode-languageserver's `Range.create()` is significantly slower
|
|
951
|
+
*/
|
|
952
|
+
createRange(startLine, startCharacter, endLine, endCharacter) {
|
|
953
|
+
// eslint-disable-next-line no-bitwise
|
|
954
|
+
const key = (startLine << 39) + (startCharacter << 26) + (endLine << 13) + endCharacter;
|
|
955
|
+
let range = this.rangeCache.get(key);
|
|
956
|
+
if (!range) {
|
|
957
|
+
range = {
|
|
958
|
+
start: this.createPosition(startLine, startCharacter),
|
|
959
|
+
end: this.createPosition(endLine, endCharacter)
|
|
960
|
+
};
|
|
961
|
+
this.rangeCache.set(key, range);
|
|
962
|
+
}
|
|
963
|
+
return range;
|
|
964
|
+
}
|
|
804
965
|
/**
|
|
805
966
|
* Create a `Range` from two `Position`s
|
|
806
967
|
*/
|
|
807
968
|
createRangeFromPositions(startPosition, endPosition) {
|
|
808
|
-
return
|
|
809
|
-
start: {
|
|
810
|
-
line: startPosition.line,
|
|
811
|
-
character: startPosition.character
|
|
812
|
-
},
|
|
813
|
-
end: {
|
|
814
|
-
line: endPosition.line,
|
|
815
|
-
character: endPosition.character
|
|
816
|
-
}
|
|
817
|
-
};
|
|
969
|
+
return this.createRange(startPosition.line, startPosition.character, endPosition.line, endPosition.character);
|
|
818
970
|
}
|
|
819
971
|
/**
|
|
820
972
|
* Given a list of ranges, create a range that starts with the first non-null lefthand range, and ends with the first non-null
|
|
@@ -844,7 +996,8 @@ class Util {
|
|
|
844
996
|
}
|
|
845
997
|
}
|
|
846
998
|
if (leftmostRange) {
|
|
847
|
-
|
|
999
|
+
//if we don't have a rightmost range, use the leftmost range for both the start and end
|
|
1000
|
+
return this.createRangeFromPositions(leftmostRange.start, rightmostRange ? rightmostRange.end : leftmostRange.end);
|
|
848
1001
|
}
|
|
849
1002
|
else {
|
|
850
1003
|
return undefined;
|
|
@@ -854,10 +1007,17 @@ class Util {
|
|
|
854
1007
|
* Create a `Position` object. Prefer this over `Position.create` for performance reasons
|
|
855
1008
|
*/
|
|
856
1009
|
createPosition(line, character) {
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1010
|
+
// eslint-disable-next-line no-bitwise
|
|
1011
|
+
const key = (line << 13) + character;
|
|
1012
|
+
let position = this.positionCache.get(key);
|
|
1013
|
+
if (!position) {
|
|
1014
|
+
position = {
|
|
1015
|
+
line: line,
|
|
1016
|
+
character: character
|
|
1017
|
+
};
|
|
1018
|
+
this.positionCache.set(key, position);
|
|
1019
|
+
}
|
|
1020
|
+
return position;
|
|
861
1021
|
}
|
|
862
1022
|
/**
|
|
863
1023
|
* Convert a list of tokens into a string, including their leading whitespace
|
|
@@ -865,8 +1025,7 @@ class Util {
|
|
|
865
1025
|
tokensToString(tokens) {
|
|
866
1026
|
let result = '';
|
|
867
1027
|
//skip iterating the final token
|
|
868
|
-
for (let
|
|
869
|
-
let token = tokens[i];
|
|
1028
|
+
for (let token of tokens) {
|
|
870
1029
|
result += token.leadingWhitespace + token.text;
|
|
871
1030
|
}
|
|
872
1031
|
return result;
|
|
@@ -874,39 +1033,36 @@ class Util {
|
|
|
874
1033
|
/**
|
|
875
1034
|
* Convert a token into a BscType
|
|
876
1035
|
*/
|
|
877
|
-
tokenToBscType(token
|
|
878
|
-
if (!token) {
|
|
879
|
-
return new DynamicType_1.DynamicType();
|
|
880
|
-
}
|
|
1036
|
+
tokenToBscType(token) {
|
|
881
1037
|
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
882
1038
|
switch (token.kind) {
|
|
883
1039
|
case TokenKind_1.TokenKind.Boolean:
|
|
884
1040
|
return new BooleanType_1.BooleanType(token.text);
|
|
885
1041
|
case TokenKind_1.TokenKind.True:
|
|
886
1042
|
case TokenKind_1.TokenKind.False:
|
|
887
|
-
return
|
|
1043
|
+
return BooleanType_1.BooleanType.instance;
|
|
888
1044
|
case TokenKind_1.TokenKind.Double:
|
|
889
1045
|
return new DoubleType_1.DoubleType(token.text);
|
|
890
1046
|
case TokenKind_1.TokenKind.DoubleLiteral:
|
|
891
|
-
return
|
|
1047
|
+
return DoubleType_1.DoubleType.instance;
|
|
892
1048
|
case TokenKind_1.TokenKind.Dynamic:
|
|
893
1049
|
return new DynamicType_1.DynamicType(token.text);
|
|
894
1050
|
case TokenKind_1.TokenKind.Float:
|
|
895
1051
|
return new FloatType_1.FloatType(token.text);
|
|
896
1052
|
case TokenKind_1.TokenKind.FloatLiteral:
|
|
897
|
-
return
|
|
1053
|
+
return FloatType_1.FloatType.instance;
|
|
898
1054
|
case TokenKind_1.TokenKind.Function:
|
|
899
|
-
return new FunctionType_1.FunctionType();
|
|
1055
|
+
return new FunctionType_1.FunctionType(token.text);
|
|
900
1056
|
case TokenKind_1.TokenKind.Integer:
|
|
901
1057
|
return new IntegerType_1.IntegerType(token.text);
|
|
902
1058
|
case TokenKind_1.TokenKind.IntegerLiteral:
|
|
903
|
-
return
|
|
1059
|
+
return IntegerType_1.IntegerType.instance;
|
|
904
1060
|
case TokenKind_1.TokenKind.Invalid:
|
|
905
|
-
return new
|
|
1061
|
+
return DynamicType_1.DynamicType.instance; // TODO: use InvalidType better new InvalidType(token.text);
|
|
906
1062
|
case TokenKind_1.TokenKind.LongInteger:
|
|
907
1063
|
return new LongIntegerType_1.LongIntegerType(token.text);
|
|
908
1064
|
case TokenKind_1.TokenKind.LongIntegerLiteral:
|
|
909
|
-
return
|
|
1065
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
910
1066
|
case TokenKind_1.TokenKind.Object:
|
|
911
1067
|
return new ObjectType_1.ObjectType(token.text);
|
|
912
1068
|
case TokenKind_1.TokenKind.String:
|
|
@@ -915,59 +1071,303 @@ class Util {
|
|
|
915
1071
|
case TokenKind_1.TokenKind.TemplateStringExpressionBegin:
|
|
916
1072
|
case TokenKind_1.TokenKind.TemplateStringExpressionEnd:
|
|
917
1073
|
case TokenKind_1.TokenKind.TemplateStringQuasi:
|
|
918
|
-
return
|
|
1074
|
+
return StringType_1.StringType.instance;
|
|
919
1075
|
case TokenKind_1.TokenKind.Void:
|
|
920
1076
|
return new VoidType_1.VoidType(token.text);
|
|
921
1077
|
case TokenKind_1.TokenKind.Identifier:
|
|
922
|
-
|
|
923
|
-
let typeClass;
|
|
924
|
-
switch (typeText) {
|
|
1078
|
+
switch (token.text.toLowerCase()) {
|
|
925
1079
|
case 'boolean':
|
|
926
|
-
|
|
927
|
-
break;
|
|
1080
|
+
return new BooleanType_1.BooleanType(token.text);
|
|
928
1081
|
case 'double':
|
|
929
|
-
|
|
930
|
-
|
|
1082
|
+
return new DoubleType_1.DoubleType(token.text);
|
|
1083
|
+
case 'dynamic':
|
|
1084
|
+
return new DynamicType_1.DynamicType(token.text);
|
|
931
1085
|
case 'float':
|
|
932
|
-
|
|
933
|
-
break;
|
|
1086
|
+
return new FloatType_1.FloatType(token.text);
|
|
934
1087
|
case 'function':
|
|
935
|
-
|
|
936
|
-
break;
|
|
1088
|
+
return new FunctionType_1.FunctionType(token.text);
|
|
937
1089
|
case 'integer':
|
|
938
|
-
|
|
939
|
-
break;
|
|
1090
|
+
return new IntegerType_1.IntegerType(token.text);
|
|
940
1091
|
case 'invalid':
|
|
941
|
-
|
|
942
|
-
break;
|
|
1092
|
+
return DynamicType_1.DynamicType.instance; // TODO: use InvalidType better new InvalidType(token.text);
|
|
943
1093
|
case 'longinteger':
|
|
944
|
-
|
|
945
|
-
break;
|
|
1094
|
+
return new LongIntegerType_1.LongIntegerType(token.text);
|
|
946
1095
|
case 'object':
|
|
947
|
-
|
|
948
|
-
break;
|
|
1096
|
+
return new ObjectType_1.ObjectType(token.text);
|
|
949
1097
|
case 'string':
|
|
950
|
-
|
|
951
|
-
break;
|
|
1098
|
+
return new StringType_1.StringType(token.text);
|
|
952
1099
|
case 'void':
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1100
|
+
return new VoidType_1.VoidType(token.text);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Deciphers the correct types for fields based on docs
|
|
1106
|
+
* https://developer.roku.com/en-ca/docs/references/scenegraph/xml-elements/interface.md
|
|
1107
|
+
* @param typeDescriptor the type descriptor from the docs
|
|
1108
|
+
* @returns {BscType} the known type, or dynamic
|
|
1109
|
+
*/
|
|
1110
|
+
getNodeFieldType(typeDescriptor, lookupTable) {
|
|
1111
|
+
const typeDescriptorLower = typeDescriptor.toLowerCase().trim();
|
|
1112
|
+
const bscType = this.tokenToBscType((0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeDescriptorLower));
|
|
1113
|
+
if (bscType) {
|
|
1114
|
+
return bscType;
|
|
1115
|
+
}
|
|
1116
|
+
function getRect2dType() {
|
|
1117
|
+
const rect2dType = new AssociativeArrayType_1.AssociativeArrayType();
|
|
1118
|
+
rect2dType.addMember('height', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
|
|
1119
|
+
rect2dType.addMember('width', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
|
|
1120
|
+
rect2dType.addMember('x', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
|
|
1121
|
+
rect2dType.addMember('y', {}, FloatType_1.FloatType.instance, SymbolTable_1.SymbolTypeFlag.runtime);
|
|
1122
|
+
return rect2dType;
|
|
1123
|
+
}
|
|
1124
|
+
function getColorType() {
|
|
1125
|
+
return (0, UnionType_1.unionTypeFactory)([IntegerType_1.IntegerType.instance, StringType_1.StringType.instance]);
|
|
1126
|
+
}
|
|
1127
|
+
if (typeDescriptorLower.startsWith('array of ')) {
|
|
1128
|
+
let arrayOfTypeName = typeDescriptorLower.substring(9); //cut off beginning 'array of'
|
|
1129
|
+
if (arrayOfTypeName.endsWith('s')) {
|
|
1130
|
+
// remove "s" in "floats", etc.
|
|
1131
|
+
arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
|
|
1132
|
+
}
|
|
1133
|
+
if (arrayOfTypeName.endsWith('\'')) {
|
|
1134
|
+
// remove "'" in "float's", etc.
|
|
1135
|
+
arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
|
|
1136
|
+
}
|
|
1137
|
+
let arrayType = this.getNodeFieldType(arrayOfTypeName, lookupTable);
|
|
1138
|
+
return new ArrayType_1.ArrayType(arrayType);
|
|
1139
|
+
}
|
|
1140
|
+
else if (typeDescriptorLower.startsWith('option ')) {
|
|
1141
|
+
const actualTypeName = typeDescriptorLower.substring('option '.length); //cut off beginning 'option '
|
|
1142
|
+
return this.getNodeFieldType(actualTypeName, lookupTable);
|
|
1143
|
+
}
|
|
1144
|
+
else if (typeDescriptorLower.startsWith('value ')) {
|
|
1145
|
+
const actualTypeName = typeDescriptorLower.substring('value '.length); //cut off beginning 'value '
|
|
1146
|
+
return this.getNodeFieldType(actualTypeName, lookupTable);
|
|
1147
|
+
}
|
|
1148
|
+
else if (typeDescriptorLower === 'uri') {
|
|
1149
|
+
return StringType_1.StringType.instance;
|
|
1150
|
+
}
|
|
1151
|
+
else if (typeDescriptorLower === 'color') {
|
|
1152
|
+
return getColorType();
|
|
1153
|
+
}
|
|
1154
|
+
else if (typeDescriptorLower === 'vector2d' || typeDescriptorLower === 'floatarray') {
|
|
1155
|
+
return new ArrayType_1.ArrayType(FloatType_1.FloatType.instance);
|
|
1156
|
+
}
|
|
1157
|
+
else if (typeDescriptorLower === 'vector2darray') {
|
|
1158
|
+
return new ArrayType_1.ArrayType(new ArrayType_1.ArrayType(FloatType_1.FloatType.instance));
|
|
1159
|
+
}
|
|
1160
|
+
else if (typeDescriptorLower === 'intarray') {
|
|
1161
|
+
return new ArrayType_1.ArrayType(IntegerType_1.IntegerType.instance);
|
|
1162
|
+
}
|
|
1163
|
+
else if (typeDescriptorLower === 'colorarray') {
|
|
1164
|
+
return new ArrayType_1.ArrayType(getColorType());
|
|
1165
|
+
}
|
|
1166
|
+
else if (typeDescriptorLower === 'boolarray') {
|
|
1167
|
+
return new ArrayType_1.ArrayType(BooleanType_1.BooleanType.instance);
|
|
1168
|
+
}
|
|
1169
|
+
else if (typeDescriptorLower === 'stringarray' || typeDescriptorLower === 'strarray') {
|
|
1170
|
+
return new ArrayType_1.ArrayType(StringType_1.StringType.instance);
|
|
1171
|
+
}
|
|
1172
|
+
else if (typeDescriptorLower === 'int') {
|
|
1173
|
+
return IntegerType_1.IntegerType.instance;
|
|
1174
|
+
}
|
|
1175
|
+
else if (typeDescriptorLower === 'time') {
|
|
1176
|
+
return DoubleType_1.DoubleType.instance;
|
|
1177
|
+
}
|
|
1178
|
+
else if (typeDescriptorLower === 'str') {
|
|
1179
|
+
return StringType_1.StringType.instance;
|
|
1180
|
+
}
|
|
1181
|
+
else if (typeDescriptorLower === 'bool') {
|
|
1182
|
+
return BooleanType_1.BooleanType.instance;
|
|
1183
|
+
}
|
|
1184
|
+
else if (typeDescriptorLower === 'array') {
|
|
1185
|
+
return new ArrayType_1.ArrayType();
|
|
1186
|
+
}
|
|
1187
|
+
else if (typeDescriptorLower === 'assocarray' || typeDescriptorLower === 'associative array' || typeDescriptorLower === 'associativearray') {
|
|
1188
|
+
return new AssociativeArrayType_1.AssociativeArrayType();
|
|
1189
|
+
}
|
|
1190
|
+
else if (typeDescriptorLower === 'node') {
|
|
1191
|
+
return ComponentType_1.ComponentType.instance;
|
|
1192
|
+
}
|
|
1193
|
+
else if (typeDescriptorLower === 'nodearray') {
|
|
1194
|
+
return new ArrayType_1.ArrayType(ComponentType_1.ComponentType.instance);
|
|
1195
|
+
}
|
|
1196
|
+
else if (typeDescriptorLower === 'rect2d') {
|
|
1197
|
+
return getRect2dType();
|
|
1198
|
+
}
|
|
1199
|
+
else if (typeDescriptorLower === 'rect2darray') {
|
|
1200
|
+
return new ArrayType_1.ArrayType(getRect2dType());
|
|
1201
|
+
}
|
|
1202
|
+
else if (lookupTable) {
|
|
1203
|
+
//try doing a lookup
|
|
1204
|
+
return lookupTable.getSymbolType(typeDescriptorLower, { flags: SymbolTable_1.SymbolTypeFlag.typetime });
|
|
1205
|
+
}
|
|
1206
|
+
// TODO: Handle 'rect2d', 'rect2dArray',
|
|
1207
|
+
return DynamicType_1.DynamicType.instance;
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Return the type of the result of a binary operator
|
|
1211
|
+
* Note: compound assignments (eg. +=) internally use a binary expression, so that's why TokenKind.PlusEqual, etc. are here too
|
|
1212
|
+
*/
|
|
1213
|
+
binaryOperatorResultType(leftType, operator, rightType) {
|
|
1214
|
+
if (((0, reflection_1.isAnyReferenceType)(leftType) && !leftType.isResolvable()) ||
|
|
1215
|
+
((0, reflection_1.isAnyReferenceType)(rightType) && !rightType.isResolvable())) {
|
|
1216
|
+
return new ReferenceType_1.BinaryOperatorReferenceType(leftType, operator, rightType, (lhs, op, rhs) => {
|
|
1217
|
+
return this.binaryOperatorResultType(lhs, op, rhs);
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1220
|
+
if ((0, reflection_1.isEnumMemberType)(leftType)) {
|
|
1221
|
+
leftType = leftType.underlyingType;
|
|
1222
|
+
}
|
|
1223
|
+
if ((0, reflection_1.isEnumMemberType)(rightType)) {
|
|
1224
|
+
rightType = rightType.underlyingType;
|
|
1225
|
+
}
|
|
1226
|
+
let hasDouble = (0, reflection_1.isDoubleType)(leftType) || (0, reflection_1.isDoubleType)(rightType);
|
|
1227
|
+
let hasFloat = (0, reflection_1.isFloatType)(leftType) || (0, reflection_1.isFloatType)(rightType);
|
|
1228
|
+
let hasLongInteger = (0, reflection_1.isLongIntegerType)(leftType) || (0, reflection_1.isLongIntegerType)(rightType);
|
|
1229
|
+
let hasInvalid = (0, reflection_1.isInvalidType)(leftType) || (0, reflection_1.isInvalidType)(rightType);
|
|
1230
|
+
let hasDynamic = (0, reflection_1.isDynamicType)(leftType) || (0, reflection_1.isDynamicType)(rightType);
|
|
1231
|
+
let bothNumbers = (0, reflection_1.isNumberType)(leftType) && (0, reflection_1.isNumberType)(rightType);
|
|
1232
|
+
let bothStrings = (0, reflection_1.isStringType)(leftType) && (0, reflection_1.isStringType)(rightType);
|
|
1233
|
+
let eitherBooleanOrNum = ((0, reflection_1.isNumberType)(leftType) || (0, reflection_1.isBooleanType)(leftType)) && ((0, reflection_1.isNumberType)(rightType) || (0, reflection_1.isBooleanType)(rightType));
|
|
1234
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
1235
|
+
switch (operator.kind) {
|
|
1236
|
+
// Math operators
|
|
1237
|
+
case TokenKind_1.TokenKind.Plus:
|
|
1238
|
+
case TokenKind_1.TokenKind.PlusEqual:
|
|
1239
|
+
if (bothStrings) {
|
|
1240
|
+
// "string" + "string" is the only binary expression allowed with strings
|
|
1241
|
+
return StringType_1.StringType.instance;
|
|
1242
|
+
}
|
|
1243
|
+
// eslint-disable-next-line no-fallthrough
|
|
1244
|
+
case TokenKind_1.TokenKind.Minus:
|
|
1245
|
+
case TokenKind_1.TokenKind.MinusEqual:
|
|
1246
|
+
case TokenKind_1.TokenKind.Star:
|
|
1247
|
+
case TokenKind_1.TokenKind.StarEqual:
|
|
1248
|
+
case TokenKind_1.TokenKind.Mod:
|
|
1249
|
+
if (bothNumbers) {
|
|
1250
|
+
if (hasDouble) {
|
|
1251
|
+
return DoubleType_1.DoubleType.instance;
|
|
1252
|
+
}
|
|
1253
|
+
else if (hasFloat) {
|
|
1254
|
+
return FloatType_1.FloatType.instance;
|
|
1255
|
+
}
|
|
1256
|
+
else if (hasLongInteger) {
|
|
1257
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1258
|
+
}
|
|
1259
|
+
return IntegerType_1.IntegerType.instance;
|
|
1260
|
+
}
|
|
1261
|
+
break;
|
|
1262
|
+
case TokenKind_1.TokenKind.Forwardslash:
|
|
1263
|
+
case TokenKind_1.TokenKind.ForwardslashEqual:
|
|
1264
|
+
if (bothNumbers) {
|
|
1265
|
+
if (hasDouble) {
|
|
1266
|
+
return DoubleType_1.DoubleType.instance;
|
|
1267
|
+
}
|
|
1268
|
+
else if (hasFloat) {
|
|
1269
|
+
return FloatType_1.FloatType.instance;
|
|
1270
|
+
}
|
|
1271
|
+
else if (hasLongInteger) {
|
|
1272
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1273
|
+
}
|
|
1274
|
+
return FloatType_1.FloatType.instance;
|
|
1275
|
+
}
|
|
1276
|
+
break;
|
|
1277
|
+
case TokenKind_1.TokenKind.Backslash:
|
|
1278
|
+
case TokenKind_1.TokenKind.BackslashEqual:
|
|
1279
|
+
if (bothNumbers) {
|
|
1280
|
+
if (hasLongInteger) {
|
|
1281
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1282
|
+
}
|
|
1283
|
+
return IntegerType_1.IntegerType.instance;
|
|
1284
|
+
}
|
|
1285
|
+
break;
|
|
1286
|
+
case TokenKind_1.TokenKind.Caret:
|
|
1287
|
+
if (bothNumbers) {
|
|
1288
|
+
if (hasDouble || hasLongInteger) {
|
|
1289
|
+
return DoubleType_1.DoubleType.instance;
|
|
1290
|
+
}
|
|
1291
|
+
else if (hasFloat) {
|
|
1292
|
+
return FloatType_1.FloatType.instance;
|
|
1293
|
+
}
|
|
1294
|
+
return IntegerType_1.IntegerType.instance;
|
|
1295
|
+
}
|
|
1296
|
+
break;
|
|
1297
|
+
// Bitshift operators
|
|
1298
|
+
case TokenKind_1.TokenKind.LeftShift:
|
|
1299
|
+
case TokenKind_1.TokenKind.LeftShiftEqual:
|
|
1300
|
+
case TokenKind_1.TokenKind.RightShift:
|
|
1301
|
+
case TokenKind_1.TokenKind.RightShiftEqual:
|
|
1302
|
+
if (bothNumbers) {
|
|
1303
|
+
if (hasLongInteger) {
|
|
1304
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1305
|
+
}
|
|
1306
|
+
// Bitshifts are allowed with non-integer numerics
|
|
1307
|
+
// but will always truncate to ints
|
|
1308
|
+
return IntegerType_1.IntegerType.instance;
|
|
1309
|
+
}
|
|
1310
|
+
break;
|
|
1311
|
+
// Comparison operators
|
|
1312
|
+
// All comparison operators result in boolean
|
|
1313
|
+
case TokenKind_1.TokenKind.Equal:
|
|
1314
|
+
case TokenKind_1.TokenKind.LessGreater:
|
|
1315
|
+
// = and <> can accept invalid / dynamic
|
|
1316
|
+
if (hasDynamic || hasInvalid || bothStrings || eitherBooleanOrNum) {
|
|
1317
|
+
return BooleanType_1.BooleanType.instance;
|
|
958
1318
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1319
|
+
break;
|
|
1320
|
+
case TokenKind_1.TokenKind.Greater:
|
|
1321
|
+
case TokenKind_1.TokenKind.Less:
|
|
1322
|
+
case TokenKind_1.TokenKind.GreaterEqual:
|
|
1323
|
+
case TokenKind_1.TokenKind.LessEqual:
|
|
1324
|
+
if (bothStrings || bothNumbers) {
|
|
1325
|
+
return BooleanType_1.BooleanType.instance;
|
|
964
1326
|
}
|
|
965
|
-
|
|
1327
|
+
break;
|
|
1328
|
+
// Logical operators
|
|
1329
|
+
case TokenKind_1.TokenKind.Or:
|
|
1330
|
+
case TokenKind_1.TokenKind.And:
|
|
1331
|
+
if (eitherBooleanOrNum) {
|
|
1332
|
+
return BooleanType_1.BooleanType.instance;
|
|
1333
|
+
}
|
|
1334
|
+
break;
|
|
966
1335
|
}
|
|
1336
|
+
return DynamicType_1.DynamicType.instance;
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Return the type of the result of a binary operator
|
|
1340
|
+
*/
|
|
1341
|
+
unaryOperatorResultType(operator, exprType) {
|
|
1342
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
1343
|
+
switch (operator.kind) {
|
|
1344
|
+
// Math operators
|
|
1345
|
+
case TokenKind_1.TokenKind.Minus:
|
|
1346
|
+
if ((0, reflection_1.isNumberType)(exprType)) {
|
|
1347
|
+
// a negative number will be the same type, eg, double->double, int->int, etc.
|
|
1348
|
+
return exprType;
|
|
1349
|
+
}
|
|
1350
|
+
break;
|
|
1351
|
+
case TokenKind_1.TokenKind.Not:
|
|
1352
|
+
if ((0, reflection_1.isBooleanType)(exprType)) {
|
|
1353
|
+
return BooleanType_1.BooleanType.instance;
|
|
1354
|
+
}
|
|
1355
|
+
else if ((0, reflection_1.isNumberType)(exprType)) {
|
|
1356
|
+
//numbers can be "notted"
|
|
1357
|
+
// by default they go to ints, except longints, which stay that way
|
|
1358
|
+
if ((0, reflection_1.isLongIntegerType)(exprType)) {
|
|
1359
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1360
|
+
}
|
|
1361
|
+
return IntegerType_1.IntegerType.instance;
|
|
1362
|
+
}
|
|
1363
|
+
break;
|
|
1364
|
+
}
|
|
1365
|
+
return DynamicType_1.DynamicType.instance;
|
|
967
1366
|
}
|
|
968
1367
|
/**
|
|
969
1368
|
* Get the extension for the given file path. Basically the part after the final dot, except for
|
|
970
1369
|
* `d.bs` which is treated as single extension
|
|
1370
|
+
* @returns the file extension (i.e. ".d.bs", ".bs", ".brs", ".xml", ".jpg", etc...)
|
|
971
1371
|
*/
|
|
972
1372
|
getExtension(filePath) {
|
|
973
1373
|
filePath = filePath.toLowerCase();
|
|
@@ -975,10 +1375,7 @@ class Util {
|
|
|
975
1375
|
return '.d.bs';
|
|
976
1376
|
}
|
|
977
1377
|
else {
|
|
978
|
-
|
|
979
|
-
if (idx > -1) {
|
|
980
|
-
return filePath.substring(idx);
|
|
981
|
-
}
|
|
1378
|
+
return path.extname(filePath).toLowerCase();
|
|
982
1379
|
}
|
|
983
1380
|
}
|
|
984
1381
|
/**
|
|
@@ -989,7 +1386,7 @@ class Util {
|
|
|
989
1386
|
return pathOrModules.reduce((acc, pathOrModule) => {
|
|
990
1387
|
if (typeof pathOrModule === 'string') {
|
|
991
1388
|
try {
|
|
992
|
-
const loaded =
|
|
1389
|
+
const loaded = requireRelative(pathOrModule, cwd);
|
|
993
1390
|
const theExport = loaded.default ? loaded.default : loaded;
|
|
994
1391
|
let plugin;
|
|
995
1392
|
// legacy plugins returned a plugin object. If we find that, then add a warning
|
|
@@ -1001,6 +1398,10 @@ class Util {
|
|
|
1001
1398
|
else if (typeof theExport === 'function') {
|
|
1002
1399
|
plugin = theExport();
|
|
1003
1400
|
}
|
|
1401
|
+
else {
|
|
1402
|
+
//this should never happen; somehow an invalid plugin has made it into here
|
|
1403
|
+
throw new Error(`TILT: Encountered an invalid plugin: ${String(plugin)}`);
|
|
1404
|
+
}
|
|
1004
1405
|
if (!plugin.name) {
|
|
1005
1406
|
plugin.name = pathOrModule;
|
|
1006
1407
|
}
|
|
@@ -1018,23 +1419,6 @@ class Util {
|
|
|
1018
1419
|
return acc;
|
|
1019
1420
|
}, []);
|
|
1020
1421
|
}
|
|
1021
|
-
resolveRequire(cwd, pathOrModule) {
|
|
1022
|
-
let target = pathOrModule;
|
|
1023
|
-
if (!path.isAbsolute(pathOrModule)) {
|
|
1024
|
-
const localPath = path.resolve(cwd, pathOrModule);
|
|
1025
|
-
if (fs.existsSync(localPath)) {
|
|
1026
|
-
target = localPath;
|
|
1027
|
-
}
|
|
1028
|
-
else {
|
|
1029
|
-
const modulePath = path.resolve(cwd, 'node_modules', pathOrModule);
|
|
1030
|
-
if (fs.existsSync(modulePath)) {
|
|
1031
|
-
target = modulePath;
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
// eslint-disable-next-line
|
|
1036
|
-
return require(target);
|
|
1037
|
-
}
|
|
1038
1422
|
/**
|
|
1039
1423
|
* Gathers expressions, variables, and unique names from an expression.
|
|
1040
1424
|
* This is mostly used for the ternary expression
|
|
@@ -1061,6 +1445,10 @@ class Util {
|
|
|
1061
1445
|
expressionWalker(expression);
|
|
1062
1446
|
return { expressions: expressions, varExpressions: variableExpressions, uniqueVarNames: [...uniqueVarNames] };
|
|
1063
1447
|
}
|
|
1448
|
+
concatAnnotationLeadingTrivia(stmt, otherTrivia) {
|
|
1449
|
+
var _a, _b;
|
|
1450
|
+
return [...((_b = (_a = stmt.annotations) === null || _a === void 0 ? void 0 : _a.map(anno => anno.getLeadingTrivia()).flat()) !== null && _b !== void 0 ? _b : []), ...otherTrivia];
|
|
1451
|
+
}
|
|
1064
1452
|
/**
|
|
1065
1453
|
* Create a SourceNode that maps every line to itself. Useful for creating maps for files
|
|
1066
1454
|
* that haven't changed at all, but we still need the map
|
|
@@ -1075,39 +1463,6 @@ class Util {
|
|
|
1075
1463
|
}
|
|
1076
1464
|
return new source_map_1.SourceNode(null, null, source, chunks);
|
|
1077
1465
|
}
|
|
1078
|
-
/**
|
|
1079
|
-
* Creates a new SGAttribute object, but keeps the existing Range references (since those should be immutable)
|
|
1080
|
-
*/
|
|
1081
|
-
cloneSGAttribute(attr, value) {
|
|
1082
|
-
return new SGTypes_1.SGAttribute({ text: attr.tokens.key.text, range: attr.range }, { text: '=' }, { text: '"' }, { text: value, range: attr.tokens.value.range }, { text: '"' });
|
|
1083
|
-
}
|
|
1084
|
-
/**
|
|
1085
|
-
* Shorthand for creating a new source node
|
|
1086
|
-
*/
|
|
1087
|
-
sourceNode(source, locatable, code) {
|
|
1088
|
-
if (code !== undefined) {
|
|
1089
|
-
const node = new source_map_1.SourceNode(null, null, source, code);
|
|
1090
|
-
if (locatable.range) {
|
|
1091
|
-
//convert 0-based Range line to 1-based SourceNode line
|
|
1092
|
-
node.line = locatable.range.start.line + 1;
|
|
1093
|
-
//SourceNode columns are 0-based so no conversion necessary
|
|
1094
|
-
node.column = locatable.range.start.character;
|
|
1095
|
-
}
|
|
1096
|
-
return node;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
/**
|
|
1100
|
-
* Remove leading simple protocols from a path (if present)
|
|
1101
|
-
*/
|
|
1102
|
-
removeProtocol(pkgPath) {
|
|
1103
|
-
let match = /^[-a-z_]+:\//.exec(pkgPath);
|
|
1104
|
-
if (match) {
|
|
1105
|
-
return pkgPath.substring(match[0].length);
|
|
1106
|
-
}
|
|
1107
|
-
else {
|
|
1108
|
-
return pkgPath;
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
1466
|
/**
|
|
1112
1467
|
* Converts a path into a standardized format (drive letter to lower, remove extra slashes, use single slash type, resolve relative parts, etc...)
|
|
1113
1468
|
*/
|
|
@@ -1115,111 +1470,57 @@ class Util {
|
|
|
1115
1470
|
return exports.util.driveLetterToLower((0, roku_deploy_1.standardizePath)(thePath));
|
|
1116
1471
|
}
|
|
1117
1472
|
/**
|
|
1118
|
-
*
|
|
1473
|
+
* Given a Diagnostic or BsDiagnostic, return a deep clone of the diagnostic.
|
|
1474
|
+
* @param diagnostic the diagnostic to clone
|
|
1475
|
+
* @param relatedInformationFallbackLocation a default location to use for all `relatedInformation` entries that are missing a location
|
|
1119
1476
|
*/
|
|
1120
|
-
|
|
1121
|
-
//copy bslib to the output directory
|
|
1122
|
-
await fsExtra.ensureDir(standardizePath(`${stagingDir}/source`));
|
|
1123
|
-
// eslint-disable-next-line
|
|
1124
|
-
const bslib = require('@rokucommunity/bslib');
|
|
1125
|
-
let source = bslib.source;
|
|
1126
|
-
//apply the `bslib_` prefix to the functions
|
|
1127
|
-
let match;
|
|
1128
|
-
const positions = [];
|
|
1129
|
-
const regexp = /^(\s*(?:function|sub)\s+)([a-z0-9_]+)/mg;
|
|
1130
|
-
// eslint-disable-next-line no-cond-assign
|
|
1131
|
-
while (match = regexp.exec(source)) {
|
|
1132
|
-
positions.push(match.index + match[1].length);
|
|
1133
|
-
}
|
|
1134
|
-
for (let i = positions.length - 1; i >= 0; i--) {
|
|
1135
|
-
const position = positions[i];
|
|
1136
|
-
source = source.slice(0, position) + 'bslib_' + source.slice(position);
|
|
1137
|
-
}
|
|
1138
|
-
await fsExtra.writeFile(`${stagingDir}/source/bslib.brs`, source);
|
|
1139
|
-
}
|
|
1140
|
-
/**
|
|
1141
|
-
* Given a Diagnostic or BsDiagnostic, return a copy of the diagnostic
|
|
1142
|
-
*/
|
|
1143
|
-
toDiagnostic(diagnostic) {
|
|
1477
|
+
toDiagnostic(diagnostic, relatedInformationFallbackLocation) {
|
|
1144
1478
|
var _a;
|
|
1479
|
+
let relatedInformation = (_a = diagnostic.relatedInformation) !== null && _a !== void 0 ? _a : [];
|
|
1480
|
+
if (relatedInformation.length > diagnosticUtils_1.MAX_RELATED_INFOS_COUNT) {
|
|
1481
|
+
const relatedInfoLength = relatedInformation.length;
|
|
1482
|
+
relatedInformation = relatedInformation.slice(0, diagnosticUtils_1.MAX_RELATED_INFOS_COUNT);
|
|
1483
|
+
relatedInformation.push({
|
|
1484
|
+
message: `...and ${relatedInfoLength - diagnosticUtils_1.MAX_RELATED_INFOS_COUNT} more`,
|
|
1485
|
+
location: exports.util.createLocation(' ', exports.util.createRange(0, 0, 0, 0))
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1145
1488
|
return {
|
|
1146
1489
|
severity: diagnostic.severity,
|
|
1147
1490
|
range: diagnostic.range,
|
|
1148
1491
|
message: diagnostic.message,
|
|
1149
|
-
relatedInformation:
|
|
1492
|
+
relatedInformation: relatedInformation.map(x => {
|
|
1150
1493
|
//clone related information just in case a plugin added circular ref info here
|
|
1151
|
-
|
|
1152
|
-
|
|
1494
|
+
const clone = Object.assign({}, x);
|
|
1495
|
+
if (!clone.location) {
|
|
1496
|
+
// use the fallback location if available
|
|
1497
|
+
if (relatedInformationFallbackLocation) {
|
|
1498
|
+
clone.location = exports.util.createLocation(relatedInformationFallbackLocation, diagnostic.range);
|
|
1499
|
+
}
|
|
1500
|
+
else {
|
|
1501
|
+
//remove this related information so it doesn't bring crash the language server
|
|
1502
|
+
return undefined;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
return clone;
|
|
1506
|
+
//filter out null relatedInformation items
|
|
1507
|
+
}).filter((x) => Boolean(x)),
|
|
1153
1508
|
code: diagnostic.code,
|
|
1154
1509
|
source: 'brs'
|
|
1155
1510
|
};
|
|
1156
1511
|
}
|
|
1157
1512
|
/**
|
|
1158
|
-
*
|
|
1159
|
-
* @param
|
|
1160
|
-
* @
|
|
1161
|
-
*/
|
|
1162
|
-
getMinMaxParamCount(params) {
|
|
1163
|
-
//get min/max parameter count for callable
|
|
1164
|
-
let minParams = 0;
|
|
1165
|
-
let maxParams = 0;
|
|
1166
|
-
let continueCheckingForRequired = true;
|
|
1167
|
-
for (let param of params) {
|
|
1168
|
-
maxParams++;
|
|
1169
|
-
//optional parameters must come last, so we can assume that minParams won't increase once we hit
|
|
1170
|
-
//the first isOptional
|
|
1171
|
-
if (continueCheckingForRequired && !param.isOptional) {
|
|
1172
|
-
minParams++;
|
|
1173
|
-
}
|
|
1174
|
-
else {
|
|
1175
|
-
continueCheckingForRequired = false;
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
return { min: minParams, max: maxParams };
|
|
1179
|
-
}
|
|
1180
|
-
/**
|
|
1181
|
-
* Gets the minimum and maximum number of allowed params for ALL functions with the name of the function call
|
|
1182
|
-
* @param callablesByLowerName The map of callable containers
|
|
1183
|
-
* @param expCall function call expression to use for the name
|
|
1184
|
-
* @returns the minimum and maximum number of allowed params
|
|
1513
|
+
* Get the first locatable item found at the specified position
|
|
1514
|
+
* @param locatables an array of items that have a `range` property
|
|
1515
|
+
* @param position the position that the locatable must contain
|
|
1185
1516
|
*/
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
for (const callableContainer of callablesWithThisName) {
|
|
1191
|
-
let specificParamCount = exports.util.getMinMaxParamCount(callableContainer.callable.params);
|
|
1192
|
-
if (specificParamCount.max > paramCount.max) {
|
|
1193
|
-
paramCount.max = specificParamCount.max;
|
|
1194
|
-
}
|
|
1195
|
-
if (specificParamCount.min < paramCount.min) {
|
|
1196
|
-
paramCount.min = specificParamCount.min;
|
|
1197
|
-
}
|
|
1517
|
+
getFirstLocatableAt(locatables, position) {
|
|
1518
|
+
for (let token of locatables) {
|
|
1519
|
+
if (exports.util.rangeContains(token.range, position)) {
|
|
1520
|
+
return token;
|
|
1198
1521
|
}
|
|
1199
|
-
return paramCount;
|
|
1200
1522
|
}
|
|
1201
1523
|
}
|
|
1202
|
-
/**
|
|
1203
|
-
* Finds the array of callables from a container map, based on the name of the function call
|
|
1204
|
-
* If the callable was called in a function in a namespace, functions in that namespace are preferred
|
|
1205
|
-
* @param callablesByLowerName The map of callable containers
|
|
1206
|
-
* @param expCall function call expression to use for the name
|
|
1207
|
-
* @return an array with callable containers - could be empty if nothing was found
|
|
1208
|
-
*/
|
|
1209
|
-
getCallableContainersByName(callablesByLowerName, expCall) {
|
|
1210
|
-
let callablesWithThisName = [];
|
|
1211
|
-
const lowerName = expCall.name.text.toLowerCase();
|
|
1212
|
-
if (expCall.functionExpression.namespaceName) {
|
|
1213
|
-
// prefer namespaced function
|
|
1214
|
-
const potentialNamespacedCallable = expCall.functionExpression.namespaceName.getName(Parser_1.ParseMode.BrightScript).toLowerCase() + '_' + lowerName;
|
|
1215
|
-
callablesWithThisName = callablesByLowerName.get(potentialNamespacedCallable.toLowerCase());
|
|
1216
|
-
}
|
|
1217
|
-
if (!callablesWithThisName || callablesWithThisName.length === 0) {
|
|
1218
|
-
// just try it as is
|
|
1219
|
-
callablesWithThisName = callablesByLowerName.get(lowerName);
|
|
1220
|
-
}
|
|
1221
|
-
return callablesWithThisName;
|
|
1222
|
-
}
|
|
1223
1524
|
/**
|
|
1224
1525
|
* Sort an array of objects that have a Range
|
|
1225
1526
|
*/
|
|
@@ -1265,8 +1566,7 @@ class Util {
|
|
|
1265
1566
|
const chunks = text.split(separator);
|
|
1266
1567
|
const result = [];
|
|
1267
1568
|
let offset = 0;
|
|
1268
|
-
for (let
|
|
1269
|
-
const chunk = chunks[i];
|
|
1569
|
+
for (let chunk of chunks) {
|
|
1270
1570
|
//only keep nonzero chunks
|
|
1271
1571
|
if (chunk.length > 0) {
|
|
1272
1572
|
result.push({
|
|
@@ -1278,52 +1578,140 @@ class Util {
|
|
|
1278
1578
|
}
|
|
1279
1579
|
return result;
|
|
1280
1580
|
}
|
|
1281
|
-
|
|
1581
|
+
/**
|
|
1282
1582
|
* Wrap the given code in a markdown code fence (with the language)
|
|
1283
1583
|
*/
|
|
1284
1584
|
mdFence(code, language = '') {
|
|
1285
1585
|
return '```' + language + '\n' + code + '\n```';
|
|
1286
1586
|
}
|
|
1287
1587
|
/**
|
|
1288
|
-
*
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1291
|
-
* @return a callable containers that matches the call
|
|
1588
|
+
* Gets each part of the dotted get.
|
|
1589
|
+
* @param node any ast expression
|
|
1590
|
+
* @returns an array of the parts of the dotted get. If not fully a dotted get, then returns undefined
|
|
1292
1591
|
*/
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1592
|
+
getAllDottedGetParts(node) {
|
|
1593
|
+
//this is a hot function and has been optimized. Don't rewrite unless necessary
|
|
1594
|
+
const parts = [];
|
|
1595
|
+
let nextPart = node;
|
|
1596
|
+
loop: while (nextPart) {
|
|
1597
|
+
switch (nextPart === null || nextPart === void 0 ? void 0 : nextPart.kind) {
|
|
1598
|
+
case AstNode_1.AstNodeKind.AssignmentStatement:
|
|
1599
|
+
return [node.name];
|
|
1600
|
+
case AstNode_1.AstNodeKind.DottedGetExpression:
|
|
1601
|
+
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
|
|
1602
|
+
nextPart = nextPart.obj;
|
|
1603
|
+
continue;
|
|
1604
|
+
case AstNode_1.AstNodeKind.CallExpression:
|
|
1605
|
+
nextPart = nextPart.callee;
|
|
1606
|
+
continue;
|
|
1607
|
+
case AstNode_1.AstNodeKind.TypeExpression:
|
|
1608
|
+
nextPart = nextPart.expression;
|
|
1609
|
+
continue;
|
|
1610
|
+
case AstNode_1.AstNodeKind.VariableExpression:
|
|
1611
|
+
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
|
|
1612
|
+
break loop;
|
|
1613
|
+
case AstNode_1.AstNodeKind.LiteralExpression:
|
|
1614
|
+
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.token);
|
|
1615
|
+
break loop;
|
|
1616
|
+
case AstNode_1.AstNodeKind.IndexedGetExpression:
|
|
1617
|
+
nextPart = nextPart.obj;
|
|
1618
|
+
continue;
|
|
1619
|
+
case AstNode_1.AstNodeKind.FunctionParameterExpression:
|
|
1620
|
+
return [nextPart.name];
|
|
1621
|
+
case AstNode_1.AstNodeKind.GroupingExpression:
|
|
1622
|
+
parts.push((0, creators_1.createIdentifier)('()', nextPart.range));
|
|
1623
|
+
break loop;
|
|
1624
|
+
default:
|
|
1625
|
+
//we found a non-DottedGet expression, so return because this whole operation is invalid.
|
|
1626
|
+
return undefined;
|
|
1301
1627
|
}
|
|
1302
1628
|
}
|
|
1629
|
+
return parts.reverse();
|
|
1303
1630
|
}
|
|
1304
1631
|
/**
|
|
1305
|
-
*
|
|
1306
|
-
*
|
|
1307
|
-
* @returns an array of the parts of the dotted get. If not fully a dotted get, then returns undefined
|
|
1632
|
+
* Given an expression, return all the DottedGet name parts as a string.
|
|
1633
|
+
* Mostly used to convert namespaced item full names to a strings
|
|
1308
1634
|
*/
|
|
1309
|
-
|
|
1310
|
-
|
|
1635
|
+
getAllDottedGetPartsAsString(node, parseMode = Parser_1.ParseMode.BrighterScript) {
|
|
1636
|
+
var _a, _b;
|
|
1637
|
+
//this is a hot function and has been optimized. Don't rewrite unless necessary
|
|
1638
|
+
/* eslint-disable no-var */
|
|
1639
|
+
var sep = parseMode === Parser_1.ParseMode.BrighterScript ? '.' : '_';
|
|
1640
|
+
const parts = (_a = this.getAllDottedGetParts(node)) !== null && _a !== void 0 ? _a : [];
|
|
1641
|
+
var result = (_b = parts[0]) === null || _b === void 0 ? void 0 : _b.text;
|
|
1642
|
+
for (var i = 1; i < parts.length; i++) {
|
|
1643
|
+
result += sep + parts[i].text;
|
|
1644
|
+
}
|
|
1645
|
+
return result;
|
|
1646
|
+
/* eslint-enable no-var */
|
|
1647
|
+
}
|
|
1648
|
+
stringJoin(strings, separator) {
|
|
1649
|
+
var _a;
|
|
1650
|
+
// eslint-disable-next-line no-var
|
|
1651
|
+
var result = (_a = strings[0]) !== null && _a !== void 0 ? _a : '';
|
|
1652
|
+
// eslint-disable-next-line no-var
|
|
1653
|
+
for (var i = 1; i < strings.length; i++) {
|
|
1654
|
+
result += separator + strings[i];
|
|
1655
|
+
}
|
|
1656
|
+
return result;
|
|
1657
|
+
}
|
|
1658
|
+
/**
|
|
1659
|
+
* Break an expression into each part.
|
|
1660
|
+
*/
|
|
1661
|
+
splitExpression(expression) {
|
|
1662
|
+
const parts = [expression];
|
|
1311
1663
|
let nextPart = expression;
|
|
1312
1664
|
while (nextPart) {
|
|
1313
|
-
if ((0, reflection_1.isDottedGetExpression)(nextPart)) {
|
|
1314
|
-
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
|
|
1665
|
+
if ((0, reflection_1.isDottedGetExpression)(nextPart) || (0, reflection_1.isIndexedGetExpression)(nextPart) || (0, reflection_1.isXmlAttributeGetExpression)(nextPart)) {
|
|
1315
1666
|
nextPart = nextPart.obj;
|
|
1316
1667
|
}
|
|
1317
|
-
else if ((0, reflection_1.
|
|
1668
|
+
else if ((0, reflection_1.isCallExpression)(nextPart) || (0, reflection_1.isCallfuncExpression)(nextPart)) {
|
|
1669
|
+
nextPart = nextPart.callee;
|
|
1670
|
+
}
|
|
1671
|
+
else if ((0, reflection_1.isTypeExpression)(nextPart)) {
|
|
1318
1672
|
nextPart = nextPart.expression;
|
|
1319
1673
|
}
|
|
1320
|
-
else
|
|
1321
|
-
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.name);
|
|
1674
|
+
else {
|
|
1322
1675
|
break;
|
|
1323
1676
|
}
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1677
|
+
parts.unshift(nextPart);
|
|
1678
|
+
}
|
|
1679
|
+
return parts;
|
|
1680
|
+
}
|
|
1681
|
+
/**
|
|
1682
|
+
* Break an expression into each part, and return any VariableExpression or DottedGet expresisons from left-to-right.
|
|
1683
|
+
*/
|
|
1684
|
+
getDottedGetPath(expression) {
|
|
1685
|
+
let parts = [];
|
|
1686
|
+
let nextPart = expression;
|
|
1687
|
+
loop: while (nextPart) {
|
|
1688
|
+
switch (nextPart === null || nextPart === void 0 ? void 0 : nextPart.kind) {
|
|
1689
|
+
case AstNode_1.AstNodeKind.DottedGetExpression:
|
|
1690
|
+
parts.push(nextPart);
|
|
1691
|
+
nextPart = nextPart.obj;
|
|
1692
|
+
continue;
|
|
1693
|
+
case AstNode_1.AstNodeKind.IndexedGetExpression:
|
|
1694
|
+
case AstNode_1.AstNodeKind.XmlAttributeGetExpression:
|
|
1695
|
+
nextPart = nextPart.obj;
|
|
1696
|
+
parts = [];
|
|
1697
|
+
continue;
|
|
1698
|
+
case AstNode_1.AstNodeKind.CallExpression:
|
|
1699
|
+
case AstNode_1.AstNodeKind.CallfuncExpression:
|
|
1700
|
+
nextPart = nextPart.callee;
|
|
1701
|
+
parts = [];
|
|
1702
|
+
continue;
|
|
1703
|
+
case AstNode_1.AstNodeKind.NewExpression:
|
|
1704
|
+
nextPart = nextPart.call.callee;
|
|
1705
|
+
parts = [];
|
|
1706
|
+
continue;
|
|
1707
|
+
case AstNode_1.AstNodeKind.TypeExpression:
|
|
1708
|
+
nextPart = nextPart.expression;
|
|
1709
|
+
continue;
|
|
1710
|
+
case AstNode_1.AstNodeKind.VariableExpression:
|
|
1711
|
+
parts.push(nextPart);
|
|
1712
|
+
break loop;
|
|
1713
|
+
default:
|
|
1714
|
+
return [];
|
|
1327
1715
|
}
|
|
1328
1716
|
}
|
|
1329
1717
|
return parts.reverse();
|
|
@@ -1347,6 +1735,159 @@ class Util {
|
|
|
1347
1735
|
var _a, _b, _c, _d;
|
|
1348
1736
|
return `${(_a = range === null || range === void 0 ? void 0 : range.start) === null || _a === void 0 ? void 0 : _a.line}:${(_b = range === null || range === void 0 ? void 0 : range.start) === null || _b === void 0 ? void 0 : _b.character}-${(_c = range === null || range === void 0 ? void 0 : range.end) === null || _c === void 0 ? void 0 : _c.line}:${(_d = range === null || range === void 0 ? void 0 : range.end) === null || _d === void 0 ? void 0 : _d.character}`;
|
|
1349
1737
|
}
|
|
1738
|
+
validateTooDeepFile(file) {
|
|
1739
|
+
var _a;
|
|
1740
|
+
//find any files nested too deep
|
|
1741
|
+
let destPath = (_a = file === null || file === void 0 ? void 0 : file.destPath) === null || _a === void 0 ? void 0 : _a.toString();
|
|
1742
|
+
let rootFolder = destPath === null || destPath === void 0 ? void 0 : destPath.replace(/^pkg:/, '').split(/[\\\/]/)[0].toLowerCase();
|
|
1743
|
+
if ((0, reflection_1.isBrsFile)(file) && rootFolder !== 'source') {
|
|
1744
|
+
return;
|
|
1745
|
+
}
|
|
1746
|
+
if ((0, reflection_1.isXmlFile)(file) && rootFolder !== 'components') {
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
let fileDepth = this.getParentDirectoryCount(destPath);
|
|
1750
|
+
if (fileDepth >= 8) {
|
|
1751
|
+
file.addDiagnostics([Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.detectedTooDeepFileSource(fileDepth)), { file: file, range: this.createRange(0, 0, 0, Number.MAX_VALUE) })]);
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* Find the index of the last item in the array that matches.
|
|
1756
|
+
*/
|
|
1757
|
+
findLastIndex(array, matcher) {
|
|
1758
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
1759
|
+
if (matcher(array[i])) {
|
|
1760
|
+
return i;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
processTypeChain(typeChain) {
|
|
1765
|
+
var _a, _b, _c, _d;
|
|
1766
|
+
let fullChainName = '';
|
|
1767
|
+
let fullErrorName = '';
|
|
1768
|
+
let itemName = '';
|
|
1769
|
+
let previousTypeName = '';
|
|
1770
|
+
let parentTypeName = '';
|
|
1771
|
+
let errorRange;
|
|
1772
|
+
let containsDynamic = false;
|
|
1773
|
+
for (let i = 0; i < typeChain.length; i++) {
|
|
1774
|
+
const chainItem = typeChain[i];
|
|
1775
|
+
const dotSep = (_b = (_a = chainItem.separatorToken) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '.';
|
|
1776
|
+
if (i > 0) {
|
|
1777
|
+
fullChainName += dotSep;
|
|
1778
|
+
}
|
|
1779
|
+
fullChainName += chainItem.name;
|
|
1780
|
+
parentTypeName = previousTypeName;
|
|
1781
|
+
fullErrorName = previousTypeName ? `${previousTypeName}${dotSep}${chainItem.name}` : chainItem.name;
|
|
1782
|
+
previousTypeName = (_d = (_c = chainItem.type) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '';
|
|
1783
|
+
itemName = chainItem.name;
|
|
1784
|
+
containsDynamic = containsDynamic || ((0, reflection_1.isDynamicType)(chainItem.type) && !(0, reflection_1.isAnyReferenceType)(chainItem.type));
|
|
1785
|
+
if (!chainItem.isResolved) {
|
|
1786
|
+
errorRange = chainItem.range;
|
|
1787
|
+
break;
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
return {
|
|
1791
|
+
itemName: itemName,
|
|
1792
|
+
itemParentTypeName: parentTypeName,
|
|
1793
|
+
fullNameOfItem: fullErrorName,
|
|
1794
|
+
fullChainName: fullChainName,
|
|
1795
|
+
range: errorRange,
|
|
1796
|
+
containsDynamic: containsDynamic
|
|
1797
|
+
};
|
|
1798
|
+
}
|
|
1799
|
+
isInTypeExpression(expression) {
|
|
1800
|
+
//TODO: this is much faster than node.findAncestor(), but may need to be updated for "complicated" type expressions
|
|
1801
|
+
if ((0, reflection_1.isTypeExpression)(expression) ||
|
|
1802
|
+
(0, reflection_1.isTypeExpression)(expression.parent) ||
|
|
1803
|
+
(0, reflection_1.isTypedArrayExpression)(expression) ||
|
|
1804
|
+
(0, reflection_1.isTypedArrayExpression)(expression.parent)) {
|
|
1805
|
+
return true;
|
|
1806
|
+
}
|
|
1807
|
+
if ((0, reflection_1.isBinaryExpression)(expression.parent)) {
|
|
1808
|
+
let currentExpr = expression.parent;
|
|
1809
|
+
while ((0, reflection_1.isBinaryExpression)(currentExpr) && currentExpr.operator.kind === TokenKind_1.TokenKind.Or) {
|
|
1810
|
+
currentExpr = currentExpr.parent;
|
|
1811
|
+
}
|
|
1812
|
+
return (0, reflection_1.isTypeExpression)(currentExpr) || (0, reflection_1.isTypedArrayExpression)(currentExpr);
|
|
1813
|
+
}
|
|
1814
|
+
return false;
|
|
1815
|
+
}
|
|
1816
|
+
setContainsUnresolvedSymbol(symbolLowerNameSet, symbol) {
|
|
1817
|
+
var _a, _b;
|
|
1818
|
+
const possibleOriginalSymbolNamesLower = [];
|
|
1819
|
+
let nameSoFar = '';
|
|
1820
|
+
for (const tce of symbol.typeChain) {
|
|
1821
|
+
if (nameSoFar.length > 0) {
|
|
1822
|
+
nameSoFar += '.';
|
|
1823
|
+
}
|
|
1824
|
+
nameSoFar += tce.name.toLowerCase();
|
|
1825
|
+
possibleOriginalSymbolNamesLower.push(nameSoFar);
|
|
1826
|
+
}
|
|
1827
|
+
const possibleNamespace = (_b = (_a = symbol.containingNamespaces) === null || _a === void 0 ? void 0 : _a.join('.')) !== null && _b !== void 0 ? _b : '';
|
|
1828
|
+
for (const possibleNameLower of possibleOriginalSymbolNamesLower) {
|
|
1829
|
+
if (symbolLowerNameSet.has(possibleNameLower)) {
|
|
1830
|
+
return true;
|
|
1831
|
+
}
|
|
1832
|
+
if (possibleNamespace) {
|
|
1833
|
+
const fullName = possibleNamespace + '.' + possibleNameLower;
|
|
1834
|
+
if (symbolLowerNameSet.has(fullName.toLowerCase())) {
|
|
1835
|
+
return true;
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
return false;
|
|
1840
|
+
}
|
|
1841
|
+
truncate(options) {
|
|
1842
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1843
|
+
let leadingText = options.leadingText;
|
|
1844
|
+
let items = (_a = options === null || options === void 0 ? void 0 : options.items) !== null && _a !== void 0 ? _a : [];
|
|
1845
|
+
let trailingText = (_b = options === null || options === void 0 ? void 0 : options.trailingText) !== null && _b !== void 0 ? _b : '';
|
|
1846
|
+
let maxLength = (_c = options === null || options === void 0 ? void 0 : options.maxLength) !== null && _c !== void 0 ? _c : 160;
|
|
1847
|
+
let itemSeparator = (_d = options === null || options === void 0 ? void 0 : options.itemSeparator) !== null && _d !== void 0 ? _d : ', ';
|
|
1848
|
+
let partBuilder = (_e = options === null || options === void 0 ? void 0 : options.partBuilder) !== null && _e !== void 0 ? _e : ((x) => x.toString());
|
|
1849
|
+
let parts = [];
|
|
1850
|
+
let length = leadingText.length + ((_f = trailingText === null || trailingText === void 0 ? void 0 : trailingText.length) !== null && _f !== void 0 ? _f : 0);
|
|
1851
|
+
//calculate the max number of items we could fit in the given space
|
|
1852
|
+
for (let i = 0; i < items.length; i++) {
|
|
1853
|
+
let part = partBuilder(items[i]);
|
|
1854
|
+
if (i > 0) {
|
|
1855
|
+
part = itemSeparator + part;
|
|
1856
|
+
}
|
|
1857
|
+
parts.push(part);
|
|
1858
|
+
length += part.length;
|
|
1859
|
+
//exit the loop if we've maxed out our length
|
|
1860
|
+
if (length >= maxLength) {
|
|
1861
|
+
break;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
let message;
|
|
1865
|
+
//we have enough space to include all the parts
|
|
1866
|
+
if (parts.length >= items.length) {
|
|
1867
|
+
message = leadingText + parts.join('') + trailingText;
|
|
1868
|
+
//we require truncation
|
|
1869
|
+
}
|
|
1870
|
+
else {
|
|
1871
|
+
//account for truncation message length including max possible "more" items digits, trailing text length, and the separator between last item and trailing text
|
|
1872
|
+
length = leadingText.length + `...and ${items.length} more`.length + itemSeparator.length + ((_g = trailingText === null || trailingText === void 0 ? void 0 : trailingText.length) !== null && _g !== void 0 ? _g : 0);
|
|
1873
|
+
message = leadingText;
|
|
1874
|
+
for (let i = 0; i < parts.length; i++) {
|
|
1875
|
+
//always include at least 2 items. if this part would overflow the max, then skip it and finalize the message
|
|
1876
|
+
if (i > 1 && length + parts[i].length > maxLength) {
|
|
1877
|
+
message += itemSeparator + `...and ${items.length - i} more` + trailingText;
|
|
1878
|
+
return message;
|
|
1879
|
+
}
|
|
1880
|
+
else {
|
|
1881
|
+
message += parts[i];
|
|
1882
|
+
length += parts[i].length;
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
return message;
|
|
1887
|
+
}
|
|
1888
|
+
getAstNodeFriendlyName(node) {
|
|
1889
|
+
return node === null || node === void 0 ? void 0 : node.kind.replace(/Statement|Expression/g, '');
|
|
1890
|
+
}
|
|
1350
1891
|
}
|
|
1351
1892
|
exports.Util = Util;
|
|
1352
1893
|
/**
|
|
@@ -1363,5 +1904,4 @@ function standardizePath(stringParts, ...expressions) {
|
|
|
1363
1904
|
exports.standardizePath = standardizePath;
|
|
1364
1905
|
exports.util = new Util();
|
|
1365
1906
|
exports.default = exports.util;
|
|
1366
|
-
exports.MAX_PARAM_COUNT = 32;
|
|
1367
1907
|
//# sourceMappingURL=util.js.map
|