brighterscript 1.0.0-alpha.5 → 1.0.0-alpha.51
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/README.md +79 -138
- package/bsconfig.schema.json +196 -5
- 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 +45 -0
- package/dist/AstValidationSegmenter.js +322 -0
- package/dist/AstValidationSegmenter.js.map +1 -0
- package/dist/BsConfig.d.ts +161 -43
- package/dist/BusyStatusTracker.d.ts +61 -0
- package/dist/BusyStatusTracker.js +148 -0
- package/dist/BusyStatusTracker.js.map +1 -0
- package/dist/Cache.d.ts +3 -8
- package/dist/Cache.js +9 -14
- 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 +29 -4
- package/dist/CodeActionUtil.js +22 -5
- package/dist/CodeActionUtil.js.map +1 -1
- package/dist/CommentFlagProcessor.d.ts +20 -15
- package/dist/CommentFlagProcessor.js +143 -58
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/CrossScopeValidator.d.ts +68 -0
- package/dist/CrossScopeValidator.js +650 -0
- package/dist/CrossScopeValidator.js.map +1 -0
- package/dist/DependencyGraph.d.ts +8 -3
- package/dist/DependencyGraph.js +49 -16
- package/dist/DependencyGraph.js.map +1 -1
- package/dist/DiagnosticCollection.d.ts +21 -5
- package/dist/DiagnosticCollection.js +77 -24
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/DiagnosticFilterer.d.ts +27 -6
- package/dist/DiagnosticFilterer.js +273 -60
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticManager.d.ts +83 -0
- package/dist/DiagnosticManager.js +422 -0
- package/dist/DiagnosticManager.js.map +1 -0
- package/dist/DiagnosticMessages.d.ts +602 -196
- package/dist/DiagnosticMessages.js +926 -342
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
- package/dist/DiagnosticSeverityAdjuster.js +45 -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 +136 -104
- package/dist/LanguageServer.js +577 -741
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +17 -13
- package/dist/Logger.js +64 -34
- package/dist/Logger.js.map +1 -1
- package/dist/PluginInterface.d.ts +32 -10
- package/dist/PluginInterface.js +117 -7
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +302 -98
- package/dist/Program.js +1613 -726
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +39 -22
- package/dist/ProgramBuilder.js +245 -179
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +227 -106
- package/dist/Scope.js +609 -557
- package/dist/Scope.js.map +1 -1
- package/dist/ScopeNamespaceLookup.d.ts +73 -0
- package/dist/ScopeNamespaceLookup.js +242 -0
- package/dist/ScopeNamespaceLookup.js.map +1 -0
- package/dist/SemanticTokenUtils.js +5 -1
- package/dist/SemanticTokenUtils.js.map +1 -1
- package/dist/Stopwatch.d.ts +4 -0
- package/dist/Stopwatch.js +8 -1
- package/dist/Stopwatch.js.map +1 -1
- package/dist/SymbolTable.d.ts +145 -26
- package/dist/SymbolTable.js +575 -64
- package/dist/SymbolTable.js.map +1 -1
- package/dist/SymbolTypeFlag.d.ts +9 -0
- package/dist/SymbolTypeFlag.js +14 -0
- package/dist/SymbolTypeFlag.js.map +1 -0
- 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 +5 -15
- package/dist/XmlScope.js +34 -90
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/CachedLookups.d.ts +50 -0
- package/dist/astUtils/CachedLookups.js +337 -0
- package/dist/astUtils/CachedLookups.js.map +1 -0
- package/dist/astUtils/Editor.d.ts +69 -0
- package/dist/astUtils/Editor.js +245 -0
- package/dist/astUtils/Editor.js.map +1 -0
- package/dist/astUtils/creators.d.ts +54 -19
- package/dist/astUtils/creators.js +242 -42
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +199 -85
- package/dist/astUtils/reflection.js +518 -145
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/stackedVisitor.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +117 -53
- package/dist/astUtils/visitors.js +95 -15
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/xml.d.ts +9 -8
- package/dist/astUtils/xml.js +12 -7
- package/dist/astUtils/xml.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +26 -4
- package/dist/bscPlugin/BscPlugin.js +96 -4
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
- package/dist/bscPlugin/CallExpressionInfo.js +142 -0
- package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
- package/dist/bscPlugin/FileWriter.d.ts +19 -0
- package/dist/bscPlugin/FileWriter.js +79 -0
- package/dist/bscPlugin/FileWriter.js.map +1 -0
- package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
- package/dist/bscPlugin/SignatureHelpUtil.js +137 -0
- package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +109 -7
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +676 -26
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.d.ts +17 -0
- package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.js +66 -0
- package/dist/bscPlugin/codeActions/FixAllCodeActionsProcessor.js.map +1 -0
- package/dist/bscPlugin/codeActions/codeActionHelpers.d.ts +18 -0
- package/dist/bscPlugin/codeActions/codeActionHelpers.js +31 -0
- package/dist/bscPlugin/codeActions/codeActionHelpers.js.map +1 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +65 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js +633 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
- package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
- package/dist/bscPlugin/definition/DefinitionProvider.js +220 -0
- package/dist/bscPlugin/definition/DefinitionProvider.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 +18 -0
- package/dist/bscPlugin/hover/HoverProcessor.js +238 -0
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
- package/dist/bscPlugin/references/ReferencesProvider.d.ts +12 -0
- package/dist/bscPlugin/references/ReferencesProvider.js +57 -0
- package/dist/bscPlugin/references/ReferencesProvider.js.map +1 -0
- package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.d.ts +7 -0
- package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.js +77 -0
- package/dist/bscPlugin/selectionRanges/SelectionRangesProcessor.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +14 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +164 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -0
- package/dist/bscPlugin/serialize/BslibManager.d.ts +12 -0
- package/dist/bscPlugin/serialize/BslibManager.js +46 -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 +80 -0
- package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.d.ts +7 -0
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js +22 -0
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.js.map +1 -0
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.d.ts +7 -0
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js +26 -0
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.js.map +1 -0
- package/dist/bscPlugin/symbols/symbolUtils.d.ts +5 -0
- package/dist/bscPlugin/symbols/symbolUtils.js +141 -0
- package/dist/bscPlugin/symbols/symbolUtils.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +34 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +504 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.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/BrsFileAfterValidator.d.ts +7 -0
- package/dist/bscPlugin/validation/BrsFileAfterValidator.js +18 -0
- package/dist/bscPlugin/validation/BrsFileAfterValidator.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +51 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js +714 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ProgramValidator.d.ts +11 -0
- package/dist/bscPlugin/validation/ProgramValidator.js +33 -0
- package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +158 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +1481 -0
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
- package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js +50 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
- package/dist/cli.js +140 -28
- package/dist/cli.js.map +1 -1
- package/dist/common/Sequencer.d.ts +53 -0
- package/dist/common/Sequencer.js +233 -0
- package/dist/common/Sequencer.js.map +1 -0
- package/dist/deferred.d.ts +5 -3
- package/dist/deferred.js +10 -0
- package/dist/deferred.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +61 -4
- package/dist/diagnosticUtils.js +285 -25
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.d.ts +2 -2
- package/dist/examples/plugins/removePrint.js +8 -12
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/AssetFile.d.ts +24 -0
- package/dist/files/AssetFile.js +25 -0
- package/dist/files/AssetFile.js.map +1 -0
- package/dist/files/BrsFile.d.ts +161 -87
- package/dist/files/BrsFile.js +919 -936
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BscFile.d.ts +102 -0
- package/dist/files/BscFile.js +15 -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 +21 -0
- package/dist/files/LazyFileData.js +54 -0
- package/dist/files/LazyFileData.js.map +1 -0
- package/dist/files/XmlFile.d.ts +80 -41
- package/dist/files/XmlFile.js +162 -137
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/globalCallables.d.ts +3 -1
- package/dist/globalCallables.js +424 -184
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +32 -4
- package/dist/index.js +54 -7
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +987 -125
- package/dist/interfaces.js +21 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Lexer.d.ts +51 -12
- package/dist/lexer/Lexer.js +214 -65
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Token.d.ts +27 -11
- package/dist/lexer/Token.js +10 -2
- package/dist/lexer/Token.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +48 -2
- package/dist/lexer/TokenKind.js +167 -10
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/logging.d.ts +14 -0
- package/dist/logging.js +29 -0
- package/dist/logging.js.map +1 -0
- package/dist/lsp/ActionQueue.d.ts +35 -0
- package/dist/lsp/ActionQueue.js +115 -0
- package/dist/lsp/ActionQueue.js.map +1 -0
- package/dist/lsp/DocumentManager.d.ts +63 -0
- package/dist/lsp/DocumentManager.js +122 -0
- package/dist/lsp/DocumentManager.js.map +1 -0
- package/dist/lsp/LspProject.d.ts +287 -0
- package/dist/lsp/LspProject.js +3 -0
- package/dist/lsp/LspProject.js.map +1 -0
- package/dist/lsp/PathFilterer.d.ts +75 -0
- package/dist/lsp/PathFilterer.js +196 -0
- package/dist/lsp/PathFilterer.js.map +1 -0
- package/dist/lsp/Project.d.ts +200 -0
- package/dist/lsp/Project.js +562 -0
- package/dist/lsp/Project.js.map +1 -0
- package/dist/lsp/ProjectManager.d.ts +288 -0
- package/dist/lsp/ProjectManager.js +967 -0
- package/dist/lsp/ProjectManager.js.map +1 -0
- package/dist/lsp/ReaderWriterManager.d.ts +21 -0
- package/dist/lsp/ReaderWriterManager.js +60 -0
- package/dist/lsp/ReaderWriterManager.js.map +1 -0
- package/dist/lsp/worker/MessageHandler.d.ts +99 -0
- package/dist/lsp/worker/MessageHandler.js +138 -0
- package/dist/lsp/worker/MessageHandler.js.map +1 -0
- package/dist/lsp/worker/WorkerPool.d.ts +38 -0
- package/dist/lsp/worker/WorkerPool.js +78 -0
- package/dist/lsp/worker/WorkerPool.js.map +1 -0
- package/dist/lsp/worker/WorkerThreadProject.d.ts +168 -0
- package/dist/lsp/worker/WorkerThreadProject.js +205 -0
- package/dist/lsp/worker/WorkerThreadProject.js.map +1 -0
- package/dist/lsp/worker/WorkerThreadProjectRunner.d.ts +15 -0
- package/dist/lsp/worker/WorkerThreadProjectRunner.js +58 -0
- package/dist/lsp/worker/WorkerThreadProjectRunner.js.map +1 -0
- package/dist/lsp/worker/run.js +14 -0
- package/dist/lsp/worker/run.js.map +1 -0
- package/dist/parser/AstNode.d.ts +205 -0
- package/dist/parser/AstNode.js +305 -0
- package/dist/parser/AstNode.js.map +1 -0
- package/dist/parser/BrightScriptDocParser.d.ts +56 -0
- package/dist/parser/BrightScriptDocParser.js +294 -0
- package/dist/parser/BrightScriptDocParser.js.map +1 -0
- package/dist/parser/BrsTranspileState.d.ts +22 -3
- package/dist/parser/BrsTranspileState.js +19 -0
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +601 -220
- package/dist/parser/Expression.js +1516 -502
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.d.ts +137 -121
- package/dist/parser/Parser.js +1808 -982
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/SGParser.d.ts +30 -13
- package/dist/parser/SGParser.js +94 -56
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +134 -46
- package/dist/parser/SGTypes.js +206 -115
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/Statement.d.ts +854 -267
- package/dist/parser/Statement.js +2416 -621
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/TranspileState.d.ts +30 -14
- package/dist/parser/TranspileState.js +124 -27
- package/dist/parser/TranspileState.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +6 -6
- package/dist/preprocessor/Manifest.js +17 -38
- package/dist/preprocessor/Manifest.js.map +1 -1
- package/dist/roku-types/data.json +20554 -0
- package/dist/roku-types/index.d.ts +5726 -0
- package/dist/roku-types/index.js +11 -0
- package/dist/roku-types/index.js.map +1 -0
- package/dist/types/ArrayType.d.ts +12 -5
- package/dist/types/ArrayType.js +95 -25
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/AssociativeArrayType.d.ts +15 -0
- package/dist/types/AssociativeArrayType.js +64 -0
- package/dist/types/AssociativeArrayType.js.map +1 -0
- package/dist/types/BaseFunctionType.d.ts +10 -0
- package/dist/types/BaseFunctionType.js +26 -0
- package/dist/types/BaseFunctionType.js.map +1 -0
- package/dist/types/BooleanType.d.ts +9 -5
- package/dist/types/BooleanType.js +19 -8
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BscType.d.ts +41 -3
- package/dist/types/BscType.js +152 -0
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BscTypeKind.d.ts +28 -0
- package/dist/types/BscTypeKind.js +33 -0
- package/dist/types/BscTypeKind.js.map +1 -0
- package/dist/types/BuiltInInterfaceAdder.d.ts +28 -0
- package/dist/types/BuiltInInterfaceAdder.js +212 -0
- package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
- package/dist/types/CallFuncableType.d.ts +24 -0
- package/dist/types/CallFuncableType.js +91 -0
- package/dist/types/CallFuncableType.js.map +1 -0
- package/dist/types/ClassType.d.ts +17 -0
- package/dist/types/ClassType.js +63 -0
- package/dist/types/ClassType.js.map +1 -0
- package/dist/types/ComponentType.d.ts +22 -0
- package/dist/types/ComponentType.js +110 -0
- package/dist/types/ComponentType.js.map +1 -0
- package/dist/types/DoubleType.d.ts +10 -5
- package/dist/types/DoubleType.js +21 -17
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DynamicType.d.ts +13 -5
- package/dist/types/DynamicType.js +26 -5
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/EnumType.d.ts +42 -0
- package/dist/types/EnumType.js +101 -0
- package/dist/types/EnumType.js.map +1 -0
- package/dist/types/FloatType.d.ts +10 -5
- package/dist/types/FloatType.js +21 -17
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FunctionType.d.ts +8 -22
- package/dist/types/FunctionType.js +25 -63
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/InheritableType.d.ts +29 -0
- package/dist/types/InheritableType.js +173 -0
- package/dist/types/InheritableType.js.map +1 -0
- package/dist/types/InlineInterfaceType.d.ts +5 -0
- package/dist/types/InlineInterfaceType.js +17 -0
- package/dist/types/InlineInterfaceType.js.map +1 -0
- package/dist/types/IntegerType.d.ts +10 -5
- package/dist/types/IntegerType.js +21 -17
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +14 -6
- package/dist/types/InterfaceType.js +30 -15
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/IntersectionType.d.ts +29 -0
- package/dist/types/IntersectionType.js +256 -0
- package/dist/types/IntersectionType.js.map +1 -0
- package/dist/types/InvalidType.d.ts +10 -5
- package/dist/types/InvalidType.js +21 -9
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +10 -5
- package/dist/types/LongIntegerType.js +21 -17
- package/dist/types/LongIntegerType.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 +12 -5
- package/dist/types/ObjectType.js +25 -8
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +123 -0
- package/dist/types/ReferenceType.js +726 -0
- package/dist/types/ReferenceType.js.map +1 -0
- package/dist/types/StringType.d.ts +12 -5
- package/dist/types/StringType.js +23 -8
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/TypeStatementType.d.ts +19 -0
- package/dist/types/TypeStatementType.js +56 -0
- package/dist/types/TypeStatementType.js.map +1 -0
- package/dist/types/TypedFunctionType.d.ts +34 -0
- package/dist/types/TypedFunctionType.js +157 -0
- package/dist/types/TypedFunctionType.js.map +1 -0
- package/dist/types/UninitializedType.d.ts +11 -6
- package/dist/types/UninitializedType.js +20 -11
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/UnionType.d.ts +27 -0
- package/dist/types/UnionType.js +196 -0
- package/dist/types/UnionType.js.map +1 -0
- package/dist/types/VoidType.d.ts +11 -5
- package/dist/types/VoidType.js +22 -8
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/helpers.d.ts +51 -0
- package/dist/types/helpers.js +329 -0
- package/dist/types/helpers.js.map +1 -0
- 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/types/roFunctionType.d.ts +11 -0
- package/dist/types/roFunctionType.js +37 -0
- package/dist/types/roFunctionType.js.map +1 -0
- package/dist/util.d.ts +325 -185
- package/dist/util.js +2135 -568
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +9 -15
- package/dist/validators/ClassValidator.js +93 -138
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +183 -138
- package/CHANGELOG.md +0 -1188
- package/dist/astUtils/creators.spec.js +0 -21
- package/dist/astUtils/creators.spec.js.map +0 -1
- package/dist/astUtils/index.d.ts +0 -7
- package/dist/astUtils/index.js +0 -26
- package/dist/astUtils/index.js.map +0 -1
- package/dist/astUtils/reflection.spec.d.ts +0 -1
- package/dist/astUtils/reflection.spec.js +0 -292
- package/dist/astUtils/reflection.spec.js.map +0 -1
- package/dist/astUtils/stackedVisitor.spec.d.ts +0 -1
- package/dist/astUtils/stackedVisitor.spec.js +0 -79
- package/dist/astUtils/stackedVisitor.spec.js.map +0 -1
- package/dist/astUtils/visitors.spec.d.ts +0 -1
- package/dist/astUtils/visitors.spec.js +0 -854
- package/dist/astUtils/visitors.spec.js.map +0 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +0 -194
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.d.ts +0 -7
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js +0 -63
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.js.map +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts +0 -1
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js +0 -45
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.spec.js.map +0 -1
- package/dist/files/BrsFile.Class.spec.d.ts +0 -1
- package/dist/files/BrsFile.Class.spec.js +0 -1081
- package/dist/files/BrsFile.Class.spec.js.map +0 -1
- package/dist/files/BrsFile.spec.d.ts +0 -1
- package/dist/files/BrsFile.spec.js +0 -2524
- package/dist/files/BrsFile.spec.js.map +0 -1
- package/dist/files/XmlFile.spec.d.ts +0 -1
- package/dist/files/XmlFile.spec.js +0 -1065
- package/dist/files/XmlFile.spec.js.map +0 -1
- package/dist/files/tests/imports.spec.d.ts +0 -1
- package/dist/files/tests/imports.spec.js +0 -241
- package/dist/files/tests/imports.spec.js.map +0 -1
- package/dist/lexer/Character.spec.d.ts +0 -1
- package/dist/lexer/Character.spec.js +0 -27
- package/dist/lexer/Character.spec.js.map +0 -1
- package/dist/lexer/Lexer.spec.d.ts +0 -1
- package/dist/lexer/Lexer.spec.js +0 -1101
- package/dist/lexer/Lexer.spec.js.map +0 -1
- package/dist/lexer/index.d.ts +0 -3
- package/dist/lexer/index.js +0 -17
- package/dist/lexer/index.js.map +0 -1
- package/dist/parser/Parser.Class.spec.d.ts +0 -1
- package/dist/parser/Parser.Class.spec.js +0 -390
- package/dist/parser/Parser.Class.spec.js.map +0 -1
- package/dist/parser/Parser.spec.d.ts +0 -4
- package/dist/parser/Parser.spec.js +0 -1216
- package/dist/parser/Parser.spec.js.map +0 -1
- package/dist/parser/SGParser.spec.d.ts +0 -1
- package/dist/parser/SGParser.spec.js +0 -145
- package/dist/parser/SGParser.spec.js.map +0 -1
- package/dist/parser/SGTypes.spec.d.ts +0 -1
- package/dist/parser/SGTypes.spec.js +0 -351
- package/dist/parser/SGTypes.spec.js.map +0 -1
- package/dist/parser/Statement.spec.d.ts +0 -1
- package/dist/parser/Statement.spec.js +0 -94
- package/dist/parser/Statement.spec.js.map +0 -1
- package/dist/parser/index.d.ts +0 -3
- package/dist/parser/index.js +0 -16
- package/dist/parser/index.js.map +0 -1
- package/dist/parser/tests/Parser.spec.d.ts +0 -18
- package/dist/parser/tests/Parser.spec.js +0 -35
- package/dist/parser/tests/Parser.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/For.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/For.spec.js +0 -161
- package/dist/parser/tests/controlFlow/For.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +0 -106
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/If.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/If.spec.js +0 -551
- package/dist/parser/tests/controlFlow/If.spec.js.map +0 -1
- package/dist/parser/tests/controlFlow/While.spec.d.ts +0 -1
- package/dist/parser/tests/controlFlow/While.spec.js +0 -107
- package/dist/parser/tests/controlFlow/While.spec.js.map +0 -1
- package/dist/parser/tests/expression/Additive.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Additive.spec.js +0 -99
- package/dist/parser/tests/expression/Additive.spec.js.map +0 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.d.ts +0 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +0 -254
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +0 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.d.ts +0 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +0 -266
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +0 -1
- package/dist/parser/tests/expression/Boolean.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Boolean.spec.js +0 -83
- package/dist/parser/tests/expression/Boolean.spec.js.map +0 -1
- package/dist/parser/tests/expression/Call.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Call.spec.js +0 -134
- package/dist/parser/tests/expression/Call.spec.js.map +0 -1
- package/dist/parser/tests/expression/Exponential.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Exponential.spec.js +0 -37
- package/dist/parser/tests/expression/Exponential.spec.js.map +0 -1
- package/dist/parser/tests/expression/Function.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Function.spec.js +0 -403
- package/dist/parser/tests/expression/Function.spec.js.map +0 -1
- package/dist/parser/tests/expression/Indexing.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Indexing.spec.js +0 -219
- package/dist/parser/tests/expression/Indexing.spec.js.map +0 -1
- package/dist/parser/tests/expression/Multiplicative.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +0 -67
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +0 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +0 -201
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.d.ts +0 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +0 -105
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +0 -1
- package/dist/parser/tests/expression/Primary.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Primary.spec.js +0 -149
- package/dist/parser/tests/expression/Primary.spec.js.map +0 -1
- package/dist/parser/tests/expression/Relational.spec.d.ts +0 -1
- package/dist/parser/tests/expression/Relational.spec.js +0 -83
- package/dist/parser/tests/expression/Relational.spec.js.map +0 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +0 -201
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +0 -202
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +0 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.d.ts +0 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +0 -323
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +0 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.d.ts +0 -1
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +0 -79
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +0 -1
- package/dist/parser/tests/statement/Declaration.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Declaration.spec.js +0 -108
- package/dist/parser/tests/statement/Declaration.spec.js.map +0 -1
- package/dist/parser/tests/statement/Dim.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Dim.spec.js +0 -73
- package/dist/parser/tests/statement/Dim.spec.js.map +0 -1
- package/dist/parser/tests/statement/Function.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Function.spec.js +0 -332
- package/dist/parser/tests/statement/Function.spec.js.map +0 -1
- package/dist/parser/tests/statement/Goto.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Goto.spec.js +0 -50
- package/dist/parser/tests/statement/Goto.spec.js.map +0 -1
- package/dist/parser/tests/statement/Increment.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Increment.spec.js +0 -117
- package/dist/parser/tests/statement/Increment.spec.js.map +0 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.js +0 -74
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/Misc.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Misc.spec.js +0 -333
- package/dist/parser/tests/statement/Misc.spec.js.map +0 -1
- package/dist/parser/tests/statement/PrintStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +0 -181
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.d.ts +0 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +0 -94
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +0 -1
- package/dist/parser/tests/statement/Set.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Set.spec.js +0 -218
- package/dist/parser/tests/statement/Set.spec.js.map +0 -1
- package/dist/parser/tests/statement/Stop.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Stop.spec.js +0 -37
- package/dist/parser/tests/statement/Stop.spec.js.map +0 -1
- package/dist/parser/tests/statement/Throw.spec.d.ts +0 -1
- package/dist/parser/tests/statement/Throw.spec.js +0 -35
- package/dist/parser/tests/statement/Throw.spec.js.map +0 -1
- package/dist/parser/tests/statement/TryCatch.spec.d.ts +0 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +0 -140
- package/dist/parser/tests/statement/TryCatch.spec.js.map +0 -1
- package/dist/preprocessor/Chunk.d.ts +0 -82
- package/dist/preprocessor/Chunk.js +0 -77
- package/dist/preprocessor/Chunk.js.map +0 -1
- package/dist/preprocessor/Manifest.spec.d.ts +0 -0
- package/dist/preprocessor/Manifest.spec.js +0 -105
- package/dist/preprocessor/Manifest.spec.js.map +0 -1
- package/dist/preprocessor/Preprocessor.d.ts +0 -60
- package/dist/preprocessor/Preprocessor.js +0 -156
- package/dist/preprocessor/Preprocessor.js.map +0 -1
- package/dist/preprocessor/Preprocessor.spec.d.ts +0 -1
- package/dist/preprocessor/Preprocessor.spec.js +0 -152
- package/dist/preprocessor/Preprocessor.spec.js.map +0 -1
- package/dist/preprocessor/PreprocessorParser.d.ts +0 -61
- package/dist/preprocessor/PreprocessorParser.js +0 -194
- package/dist/preprocessor/PreprocessorParser.js.map +0 -1
- package/dist/preprocessor/PreprocessorParser.spec.d.ts +0 -1
- package/dist/preprocessor/PreprocessorParser.spec.js +0 -116
- package/dist/preprocessor/PreprocessorParser.spec.js.map +0 -1
- package/dist/preprocessor/index.d.ts +0 -3
- package/dist/preprocessor/index.js +0 -16
- package/dist/preprocessor/index.js.map +0 -1
- package/dist/types/ArrayType.spec.d.ts +0 -1
- package/dist/types/ArrayType.spec.js +0 -30
- package/dist/types/ArrayType.spec.js.map +0 -1
- package/dist/types/BooleanType.spec.d.ts +0 -1
- package/dist/types/BooleanType.spec.js +0 -12
- package/dist/types/BooleanType.spec.js.map +0 -1
- package/dist/types/CustomType.d.ts +0 -10
- package/dist/types/CustomType.js +0 -35
- package/dist/types/CustomType.js.map +0 -1
- package/dist/types/DoubleType.spec.d.ts +0 -1
- package/dist/types/DoubleType.spec.js +0 -12
- package/dist/types/DoubleType.spec.js.map +0 -1
- package/dist/types/DynamicType.spec.d.ts +0 -1
- package/dist/types/DynamicType.spec.js +0 -12
- package/dist/types/DynamicType.spec.js.map +0 -1
- package/dist/types/FloatType.spec.d.ts +0 -1
- package/dist/types/FloatType.spec.js +0 -12
- package/dist/types/FloatType.spec.js.map +0 -1
- package/dist/types/FunctionType.spec.d.ts +0 -1
- package/dist/types/FunctionType.spec.js +0 -29
- package/dist/types/FunctionType.spec.js.map +0 -1
- package/dist/types/IntegerType.spec.d.ts +0 -1
- package/dist/types/IntegerType.spec.js +0 -12
- package/dist/types/IntegerType.spec.js.map +0 -1
- package/dist/types/InvalidType.spec.d.ts +0 -1
- package/dist/types/InvalidType.spec.js +0 -12
- package/dist/types/InvalidType.spec.js.map +0 -1
- package/dist/types/LazyType.d.ts +0 -15
- package/dist/types/LazyType.js +0 -32
- package/dist/types/LazyType.js.map +0 -1
- package/dist/types/LongIntegerType.spec.d.ts +0 -1
- package/dist/types/LongIntegerType.spec.js +0 -12
- package/dist/types/LongIntegerType.spec.js.map +0 -1
- package/dist/types/ObjectType.spec.d.ts +0 -1
- package/dist/types/ObjectType.spec.js +0 -12
- package/dist/types/ObjectType.spec.js.map +0 -1
- package/dist/types/StringType.spec.d.ts +0 -1
- package/dist/types/StringType.spec.js +0 -12
- package/dist/types/StringType.spec.js.map +0 -1
- package/dist/types/VoidType.spec.d.ts +0 -1
- package/dist/types/VoidType.spec.js +0 -12
- package/dist/types/VoidType.spec.js.map +0 -1
- /package/dist/{astUtils/creators.spec.d.ts → lsp/worker/run.d.ts} +0 -0
package/dist/util.js
CHANGED
|
@@ -5,35 +5,74 @@ const fs = require("fs");
|
|
|
5
5
|
const fsExtra = require("fs-extra");
|
|
6
6
|
const jsonc_parser_1 = require("jsonc-parser");
|
|
7
7
|
const path = require("path");
|
|
8
|
-
const
|
|
8
|
+
const roku_deploy_1 = require("roku-deploy");
|
|
9
|
+
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
9
10
|
const vscode_uri_1 = require("vscode-uri");
|
|
10
|
-
const xml2js = require("xml2js");
|
|
11
11
|
const DiagnosticMessages_1 = require("./DiagnosticMessages");
|
|
12
|
+
const interfaces_1 = require("./interfaces");
|
|
12
13
|
const BooleanType_1 = require("./types/BooleanType");
|
|
13
14
|
const DoubleType_1 = require("./types/DoubleType");
|
|
14
15
|
const DynamicType_1 = require("./types/DynamicType");
|
|
15
16
|
const FloatType_1 = require("./types/FloatType");
|
|
16
|
-
const FunctionType_1 = require("./types/FunctionType");
|
|
17
17
|
const IntegerType_1 = require("./types/IntegerType");
|
|
18
|
-
const InvalidType_1 = require("./types/InvalidType");
|
|
19
18
|
const LongIntegerType_1 = require("./types/LongIntegerType");
|
|
20
19
|
const ObjectType_1 = require("./types/ObjectType");
|
|
21
20
|
const StringType_1 = require("./types/StringType");
|
|
22
21
|
const VoidType_1 = require("./types/VoidType");
|
|
23
22
|
const Parser_1 = require("./parser/Parser");
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
const
|
|
23
|
+
const logging_1 = require("./logging");
|
|
24
|
+
const Token_1 = require("./lexer/Token");
|
|
25
|
+
const TokenKind_1 = require("./lexer/TokenKind");
|
|
26
|
+
const reflection_1 = require("./astUtils/reflection");
|
|
27
|
+
const visitors_1 = require("./astUtils/visitors");
|
|
28
28
|
const source_map_1 = require("source-map");
|
|
29
|
-
const
|
|
29
|
+
const requireRelative = require("require-relative");
|
|
30
|
+
const AstNode_1 = require("./parser/AstNode");
|
|
31
|
+
const creators_1 = require("./astUtils/creators");
|
|
32
|
+
const diagnosticUtils_1 = require("./diagnosticUtils");
|
|
33
|
+
const UnionType_1 = require("./types/UnionType");
|
|
34
|
+
const ArrayType_1 = require("./types/ArrayType");
|
|
35
|
+
const ReferenceType_1 = require("./types/ReferenceType");
|
|
36
|
+
const AssociativeArrayType_1 = require("./types/AssociativeArrayType");
|
|
37
|
+
const ComponentType_1 = require("./types/ComponentType");
|
|
38
|
+
const FunctionType_1 = require("./types/FunctionType");
|
|
39
|
+
const helpers_1 = require("./types/helpers");
|
|
40
|
+
const InvalidType_1 = require("./types/InvalidType");
|
|
41
|
+
const types_1 = require("./types");
|
|
42
|
+
const IntersectionType_1 = require("./types/IntersectionType");
|
|
30
43
|
class Util {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.isWindows = process.platform === 'win32';
|
|
46
|
+
this.standardizePathCache = new Map();
|
|
47
|
+
this.pathToURICache = new Map();
|
|
48
|
+
}
|
|
31
49
|
clearConsole() {
|
|
32
50
|
// process.stdout.write('\x1Bc');
|
|
33
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Get the version of brighterscript
|
|
54
|
+
*/
|
|
55
|
+
getBrighterScriptVersion() {
|
|
56
|
+
try {
|
|
57
|
+
return fsExtra.readJsonSync(`${__dirname}/../package.json`).version;
|
|
58
|
+
}
|
|
59
|
+
catch (_a) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns the number of parent directories in the filPath
|
|
65
|
+
*/
|
|
66
|
+
getParentDirectoryCount(filePath) {
|
|
67
|
+
if (!filePath) {
|
|
68
|
+
return -1;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
return filePath.replace(/^pkg:/, '').split(/[\\\/]/).length - 1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
34
74
|
/**
|
|
35
75
|
* Determine if the file exists
|
|
36
|
-
* @param filePath
|
|
37
76
|
*/
|
|
38
77
|
async pathExists(filePath) {
|
|
39
78
|
if (!filePath) {
|
|
@@ -45,7 +84,6 @@ class Util {
|
|
|
45
84
|
}
|
|
46
85
|
/**
|
|
47
86
|
* Determine if the file exists
|
|
48
|
-
* @param filePath
|
|
49
87
|
*/
|
|
50
88
|
pathExistsSync(filePath) {
|
|
51
89
|
if (!filePath) {
|
|
@@ -59,40 +97,39 @@ class Util {
|
|
|
59
97
|
* Determine if this path is a directory
|
|
60
98
|
*/
|
|
61
99
|
isDirectorySync(dirPath) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
sanitizePkgPath(pkgPath) {
|
|
68
|
-
pkgPath = pkgPath.replace(/\\/g, '/');
|
|
69
|
-
//if there's no protocol, assume it's supposed to start with `pkg:/`
|
|
70
|
-
if (!this.startsWithProtocol(pkgPath)) {
|
|
71
|
-
pkgPath = 'pkg:/' + pkgPath;
|
|
100
|
+
try {
|
|
101
|
+
return dirPath !== undefined && fs.existsSync(dirPath) && fs.lstatSync(dirPath).isDirectory();
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
return false;
|
|
72
105
|
}
|
|
73
|
-
return pkgPath;
|
|
74
106
|
}
|
|
75
107
|
/**
|
|
76
|
-
*
|
|
108
|
+
* Read a file from disk. If a failure occurrs, simply return undefined
|
|
109
|
+
* @param filePath path to the file
|
|
110
|
+
* @returns the string contents, or undefined if the file doesn't exist
|
|
77
111
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
112
|
+
readFileSync(filePath) {
|
|
113
|
+
try {
|
|
114
|
+
return fsExtra.readFileSync(filePath);
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
80
119
|
}
|
|
81
120
|
/**
|
|
82
|
-
* Given a path
|
|
83
|
-
* @param filePath
|
|
121
|
+
* Given a pkg path of any kind, transform it to a roku-specific pkg path (i.e. "pkg:/some/path.brs")
|
|
84
122
|
*/
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return filePath.replace(/[\\/]+/g, separator);
|
|
123
|
+
sanitizePkgPath(pkgPath) {
|
|
124
|
+
//convert all slashes to forwardslash
|
|
125
|
+
pkgPath = pkgPath.replace(/[\/\\]+/g, '/');
|
|
126
|
+
//ensure every path has the leading pkg:/
|
|
127
|
+
return 'pkg:/' + pkgPath.replace(/^pkg:\//i, '');
|
|
91
128
|
}
|
|
92
129
|
/**
|
|
93
130
|
* Find the path to the config file.
|
|
94
131
|
* If the config file path doesn't exist
|
|
95
|
-
* @param
|
|
132
|
+
* @param cwd the current working directory where the search for configs should begin
|
|
96
133
|
*/
|
|
97
134
|
getConfigFilePath(cwd) {
|
|
98
135
|
cwd = cwd !== null && cwd !== void 0 ? cwd : process.cwd();
|
|
@@ -126,15 +163,16 @@ class Util {
|
|
|
126
163
|
colIndex++;
|
|
127
164
|
}
|
|
128
165
|
}
|
|
129
|
-
return
|
|
166
|
+
return exports.util.createRange(lineIndex, colIndex, lineIndex, colIndex + length);
|
|
130
167
|
}
|
|
131
168
|
/**
|
|
132
169
|
* Load the contents of a config file.
|
|
133
170
|
* If the file extends another config, this will load the base config as well.
|
|
134
|
-
* @param configFilePath
|
|
135
|
-
* @param parentProjectPaths
|
|
171
|
+
* @param configFilePath the relative or absolute path to a brighterscript config json file
|
|
172
|
+
* @param parentProjectPaths a list of parent config files. This is used by this method to recursively build the config list
|
|
136
173
|
*/
|
|
137
174
|
loadConfigFile(configFilePath, parentProjectPaths, cwd = process.cwd()) {
|
|
175
|
+
var _a;
|
|
138
176
|
if (configFilePath) {
|
|
139
177
|
//if the config file path starts with question mark, then it's optional. return undefined if it doesn't exist
|
|
140
178
|
if (configFilePath.startsWith('?')) {
|
|
@@ -155,16 +193,24 @@ class Util {
|
|
|
155
193
|
//load the project file
|
|
156
194
|
let projectFileContents = fsExtra.readFileSync(configFilePath).toString();
|
|
157
195
|
let parseErrors = [];
|
|
158
|
-
let projectConfig = jsonc_parser_1.parse(projectFileContents, parseErrors
|
|
196
|
+
let projectConfig = (_a = (0, jsonc_parser_1.parse)(projectFileContents, parseErrors, {
|
|
197
|
+
allowEmptyContent: true,
|
|
198
|
+
allowTrailingComma: true,
|
|
199
|
+
disallowComments: false
|
|
200
|
+
})) !== null && _a !== void 0 ? _a : {};
|
|
159
201
|
if (parseErrors.length > 0) {
|
|
160
202
|
let err = parseErrors[0];
|
|
161
|
-
let diagnostic = Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.
|
|
162
|
-
|
|
163
|
-
|
|
203
|
+
let diagnostic = Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.syntaxError(`Syntax errors in bsconfig.json: ${(0, jsonc_parser_1.printParseErrorCode)(parseErrors[0].error)}`)), { location: {
|
|
204
|
+
uri: this.pathToUri(configFilePath),
|
|
205
|
+
range: this.getRangeFromOffsetLength(projectFileContents, err.offset, err.length)
|
|
206
|
+
} });
|
|
164
207
|
throw diagnostic; //eslint-disable-line @typescript-eslint/no-throw-literal
|
|
165
208
|
}
|
|
166
|
-
this.resolvePluginPaths(projectConfig, configFilePath);
|
|
167
209
|
let projectFileCwd = path.dirname(configFilePath);
|
|
210
|
+
//`plugins` paths should be relative to the current bsconfig
|
|
211
|
+
this.resolvePathsRelativeTo(projectConfig, 'plugins', projectFileCwd);
|
|
212
|
+
//`require` paths should be relative to cwd
|
|
213
|
+
exports.util.resolvePathsRelativeTo(projectConfig, 'require', projectFileCwd);
|
|
168
214
|
let result;
|
|
169
215
|
//if the project has a base file, load it
|
|
170
216
|
if (projectConfig && typeof projectConfig.extends === 'string') {
|
|
@@ -179,75 +225,50 @@ class Util {
|
|
|
179
225
|
result._ancestors = parentProjectPaths;
|
|
180
226
|
}
|
|
181
227
|
//make any paths in the config absolute (relative to the CURRENT config file)
|
|
182
|
-
if (result.outFile) {
|
|
183
|
-
result.outFile = path.resolve(projectFileCwd, result.outFile);
|
|
184
|
-
}
|
|
185
228
|
if (result.rootDir) {
|
|
186
229
|
result.rootDir = path.resolve(projectFileCwd, result.rootDir);
|
|
187
230
|
}
|
|
231
|
+
if (result.outDir) {
|
|
232
|
+
result.outDir = path.resolve(projectFileCwd, result.outDir);
|
|
233
|
+
}
|
|
188
234
|
if (result.cwd) {
|
|
189
235
|
result.cwd = path.resolve(projectFileCwd, result.cwd);
|
|
190
236
|
}
|
|
237
|
+
if (result.sourceRoot && result.resolveSourceRoot) {
|
|
238
|
+
result.sourceRoot = path.resolve(projectFileCwd, result.sourceRoot);
|
|
239
|
+
}
|
|
191
240
|
return result;
|
|
192
241
|
}
|
|
193
242
|
}
|
|
194
243
|
/**
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
* @param config
|
|
198
|
-
* @param
|
|
244
|
+
* Convert relative paths to absolute paths, relative to the given directory. Also de-dupes the paths. Modifies the array in-place
|
|
245
|
+
* @param collection usually a bsconfig.
|
|
246
|
+
* @param key a key of the config to read paths from (usually this is `'plugins'` or `'require'`)
|
|
247
|
+
* @param relativeDir the path to the folder where the paths should be resolved relative to. This should be an absolute path
|
|
199
248
|
*/
|
|
200
|
-
|
|
249
|
+
resolvePathsRelativeTo(collection, key, relativeDir) {
|
|
201
250
|
var _a;
|
|
202
|
-
if (
|
|
203
|
-
|
|
204
|
-
const exists = {};
|
|
205
|
-
config.plugins = config.plugins.map(p => {
|
|
206
|
-
return (p === null || p === void 0 ? void 0 : p.startsWith('.')) ? path.resolve(relPath, p) : p;
|
|
207
|
-
}).filter(p => {
|
|
208
|
-
if (!p || exists[p]) {
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
|
-
exists[p] = true;
|
|
212
|
-
return true;
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Do work within the scope of a changed current working directory
|
|
218
|
-
* @param targetCwd
|
|
219
|
-
* @param callback
|
|
220
|
-
*/
|
|
221
|
-
cwdWork(targetCwd, callback) {
|
|
222
|
-
let originalCwd = process.cwd();
|
|
223
|
-
if (targetCwd) {
|
|
224
|
-
process.chdir(targetCwd);
|
|
225
|
-
}
|
|
226
|
-
let result;
|
|
227
|
-
let err;
|
|
228
|
-
try {
|
|
229
|
-
result = callback();
|
|
230
|
-
}
|
|
231
|
-
catch (e) {
|
|
232
|
-
err = e;
|
|
233
|
-
}
|
|
234
|
-
if (targetCwd) {
|
|
235
|
-
process.chdir(originalCwd);
|
|
251
|
+
if (!collection[key]) {
|
|
252
|
+
return;
|
|
236
253
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
254
|
+
const result = new Set();
|
|
255
|
+
for (const p of (_a = collection[key]) !== null && _a !== void 0 ? _a : []) {
|
|
256
|
+
if (p) {
|
|
257
|
+
result.add((p === null || p === void 0 ? void 0 : p.startsWith('.')) ? path.resolve(relativeDir, p) : p);
|
|
258
|
+
}
|
|
242
259
|
}
|
|
260
|
+
collection[key] = [...result];
|
|
243
261
|
}
|
|
244
262
|
/**
|
|
245
263
|
* Given a BsConfig object, start with defaults,
|
|
246
264
|
* merge with bsconfig.json and the provided options.
|
|
247
|
-
* @param config
|
|
265
|
+
* @param config a bsconfig object to use as the baseline for the resulting config
|
|
248
266
|
*/
|
|
249
267
|
normalizeAndResolveConfig(config) {
|
|
250
|
-
let result = this.normalizeConfig({});
|
|
268
|
+
let result = this.normalizeConfig(Object.assign({}, config));
|
|
269
|
+
if (config === null || config === void 0 ? void 0 : config.noProject) {
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
251
272
|
//if no options were provided, try to find a bsconfig.json file
|
|
252
273
|
if (!config || !config.project) {
|
|
253
274
|
result.project = this.getConfigFilePath(config === null || config === void 0 ? void 0 : config.cwd);
|
|
@@ -257,7 +278,7 @@ class Util {
|
|
|
257
278
|
result.project = config.project;
|
|
258
279
|
}
|
|
259
280
|
if (result.project) {
|
|
260
|
-
let configFile = this.loadConfigFile(result.project,
|
|
281
|
+
let configFile = this.loadConfigFile(result.project, undefined, config === null || config === void 0 ? void 0 : config.cwd);
|
|
261
282
|
result = Object.assign(result, configFile);
|
|
262
283
|
}
|
|
263
284
|
//override the defaults with the specified options
|
|
@@ -266,42 +287,81 @@ class Util {
|
|
|
266
287
|
}
|
|
267
288
|
/**
|
|
268
289
|
* Set defaults for any missing items
|
|
269
|
-
* @param config
|
|
290
|
+
* @param config a bsconfig object to use as the baseline for the resulting config
|
|
270
291
|
*/
|
|
271
292
|
normalizeConfig(config) {
|
|
272
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
273
|
-
config = config
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
config.files = (_a = config.files) !== null && _a !== void 0 ? _a : rokuDeploy.getOptions().files;
|
|
277
|
-
config.createPackage = config.createPackage === false ? false : true;
|
|
278
|
-
let rootFolderName = path.basename(process.cwd());
|
|
279
|
-
config.outFile = (_b = config.outFile) !== null && _b !== void 0 ? _b : `./out/${rootFolderName}.zip`;
|
|
280
|
-
config.sourceMap = config.sourceMap === true;
|
|
281
|
-
config.username = (_c = config.username) !== null && _c !== void 0 ? _c : 'rokudev';
|
|
282
|
-
config.watch = config.watch === true ? true : false;
|
|
283
|
-
config.emitFullPaths = config.emitFullPaths === true ? true : false;
|
|
284
|
-
config.retainStagingFolder = config.retainStagingFolder === true ? true : false;
|
|
285
|
-
config.copyToStaging = config.copyToStaging === false ? false : true;
|
|
286
|
-
config.ignoreErrorCodes = (_d = config.ignoreErrorCodes) !== null && _d !== void 0 ? _d : [];
|
|
287
|
-
config.diagnosticFilters = (_e = config.diagnosticFilters) !== null && _e !== void 0 ? _e : [];
|
|
288
|
-
config.plugins = (_f = config.plugins) !== null && _f !== void 0 ? _f : [];
|
|
289
|
-
config.autoImportComponentScript = config.autoImportComponentScript === true ? true : false;
|
|
290
|
-
config.showDiagnosticsInConsole = config.showDiagnosticsInConsole === false ? false : true;
|
|
291
|
-
config.sourceRoot = config.sourceRoot ? standardizePath(config.sourceRoot) : undefined;
|
|
292
|
-
config.cwd = (_g = config.cwd) !== null && _g !== void 0 ? _g : process.cwd();
|
|
293
|
-
config.emitDefinitions = config.emitDefinitions === true ? true : false;
|
|
293
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
294
|
+
config = config !== null && config !== void 0 ? config : {};
|
|
295
|
+
const cwd = (_a = config.cwd) !== null && _a !== void 0 ? _a : process.cwd();
|
|
296
|
+
let logLevel = logging_1.LogLevel.log;
|
|
294
297
|
if (typeof config.logLevel === 'string') {
|
|
295
|
-
|
|
298
|
+
logLevel = (_b = logging_1.LogLevel[config.logLevel.toLowerCase()]) !== null && _b !== void 0 ? _b : logging_1.LogLevel.log;
|
|
299
|
+
}
|
|
300
|
+
let bslibDestinationDir = (_c = config.bslibDestinationDir) !== null && _c !== void 0 ? _c : 'source';
|
|
301
|
+
if (bslibDestinationDir !== 'source') {
|
|
302
|
+
// strip leading and trailing slashes
|
|
303
|
+
bslibDestinationDir = bslibDestinationDir.replace(/^(\/*)(.*?)(\/*)$/, '$2');
|
|
304
|
+
}
|
|
305
|
+
let noEmit;
|
|
306
|
+
if ('noEmit' in config) {
|
|
307
|
+
noEmit = config.noEmit;
|
|
296
308
|
}
|
|
297
|
-
|
|
298
|
-
|
|
309
|
+
else if ('copyToStaging' in config) {
|
|
310
|
+
noEmit = !config.copyToStaging; //invert the old value
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
noEmit = false; //default case
|
|
314
|
+
}
|
|
315
|
+
let outDir;
|
|
316
|
+
if ('outDir' in config) {
|
|
317
|
+
outDir = (_d = config.outDir) !== null && _d !== void 0 ? _d : './out';
|
|
318
|
+
}
|
|
319
|
+
else if ('stagingFolderPath' in config) {
|
|
320
|
+
outDir = config.stagingFolderPath;
|
|
321
|
+
}
|
|
322
|
+
else if ('stagingDir' in config) {
|
|
323
|
+
outDir = config.stagingDir;
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
outDir = './out'; //default case
|
|
327
|
+
}
|
|
328
|
+
const configWithDefaults = {
|
|
329
|
+
cwd: cwd,
|
|
330
|
+
//use default files array from rokuDeploy
|
|
331
|
+
files: (_e = config.files) !== null && _e !== void 0 ? _e : [...roku_deploy_1.DefaultFiles],
|
|
332
|
+
outDir: outDir,
|
|
333
|
+
sourceMap: config.sourceMap === true,
|
|
334
|
+
relativeSourceMaps: config.relativeSourceMaps === true,
|
|
335
|
+
watch: config.watch === true ? true : false,
|
|
336
|
+
emitFullPaths: config.emitFullPaths === true ? true : false,
|
|
337
|
+
noEmit: noEmit,
|
|
338
|
+
ignoreErrorCodes: (_f = config.ignoreErrorCodes) !== null && _f !== void 0 ? _f : [],
|
|
339
|
+
diagnosticSeverityOverrides: (_g = config.diagnosticSeverityOverrides) !== null && _g !== void 0 ? _g : {},
|
|
340
|
+
diagnosticFilters: (_h = config.diagnosticFilters) !== null && _h !== void 0 ? _h : [],
|
|
341
|
+
diagnosticFiltersV0Compatibility: config.diagnosticFiltersV0Compatibility === true ? true : false,
|
|
342
|
+
plugins: (_j = config.plugins) !== null && _j !== void 0 ? _j : [],
|
|
343
|
+
pruneEmptyCodeFiles: config.pruneEmptyCodeFiles === true ? true : false,
|
|
344
|
+
autoImportComponentScript: config.autoImportComponentScript === true ? true : false,
|
|
345
|
+
showDiagnosticsInConsole: config.showDiagnosticsInConsole === false ? false : true,
|
|
346
|
+
sourceRoot: config.sourceRoot ? standardizePath(config.sourceRoot) : undefined,
|
|
347
|
+
resolveSourceRoot: config.resolveSourceRoot === true ? true : false,
|
|
348
|
+
allowBrighterScriptInBrightScript: config.allowBrighterScriptInBrightScript === true ? true : false,
|
|
349
|
+
emitDefinitions: config.emitDefinitions === true ? true : false,
|
|
350
|
+
removeParameterTypes: config.removeParameterTypes === true ? true : false,
|
|
351
|
+
logLevel: logLevel,
|
|
352
|
+
bslibDestinationDir: bslibDestinationDir,
|
|
353
|
+
legacyCallfuncHandling: config.legacyCallfuncHandling === true ? true : false,
|
|
354
|
+
validate: config.validate === false ? false : true
|
|
355
|
+
};
|
|
356
|
+
//mutate `config` in case anyone is holding a reference to the incomplete one
|
|
357
|
+
const merged = Object.assign(config, configWithDefaults);
|
|
358
|
+
return merged;
|
|
299
359
|
}
|
|
300
360
|
/**
|
|
301
361
|
* Get the root directory from options.
|
|
302
362
|
* Falls back to options.cwd.
|
|
303
363
|
* Falls back to process.cwd
|
|
304
|
-
* @param options
|
|
364
|
+
* @param options a bsconfig object
|
|
305
365
|
*/
|
|
306
366
|
getRootDir(options) {
|
|
307
367
|
if (!options) {
|
|
@@ -313,19 +373,8 @@ class Util {
|
|
|
313
373
|
rootDir = path.resolve(cwd, rootDir);
|
|
314
374
|
return rootDir;
|
|
315
375
|
}
|
|
316
|
-
/**
|
|
317
|
-
* Format a string with placeholders replaced by argument indexes
|
|
318
|
-
* @param subject
|
|
319
|
-
* @param params
|
|
320
|
-
*/
|
|
321
|
-
stringFormat(subject, ...args) {
|
|
322
|
-
return subject.replace(/{(\d+)}/g, (match, num) => {
|
|
323
|
-
return typeof args[num] !== 'undefined' ? args[num] : match;
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
376
|
/**
|
|
327
377
|
* Given a list of callables as a dictionary indexed by their full name (namespace included, transpiled to underscore-separated.
|
|
328
|
-
* @param callables
|
|
329
378
|
*/
|
|
330
379
|
getCallableContainersByLowerName(callables) {
|
|
331
380
|
//find duplicate functions
|
|
@@ -344,33 +393,34 @@ class Util {
|
|
|
344
393
|
return result;
|
|
345
394
|
}
|
|
346
395
|
/**
|
|
347
|
-
*
|
|
348
|
-
*
|
|
396
|
+
* Given an absolute path to a source file, and a target path,
|
|
397
|
+
* compute the pkg path for the target relative to the source file's location
|
|
349
398
|
*/
|
|
350
|
-
|
|
351
|
-
return text.split(/\r?\n/);
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Compute the pkg path for the target relative to the source file's location
|
|
355
|
-
* @param sourcePkgPath The pkgPath of the file that contains the target path
|
|
356
|
-
* @param targetPath a full pkgPath, or a path relative to the containing file
|
|
357
|
-
*/
|
|
358
|
-
getPkgPathFromTarget(sourcePkgPath, targetPath) {
|
|
399
|
+
getPkgPathFromTarget(containingFilePathAbsolute, targetPath) {
|
|
359
400
|
var _a;
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
401
|
+
// https://regex101.com/r/w7CG2N/1
|
|
402
|
+
const regexp = /^(?:pkg|libpkg):(\/)?/i;
|
|
403
|
+
const [fullScheme, slash] = (_a = regexp.exec(targetPath)) !== null && _a !== void 0 ? _a : [];
|
|
404
|
+
//if the target starts with 'pkg:' or 'libpkg:' then it's an absolute path. Return as is
|
|
405
|
+
if (slash) {
|
|
406
|
+
targetPath = targetPath.substring(fullScheme.length);
|
|
407
|
+
if (targetPath === '') {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
return path.normalize(targetPath);
|
|
412
|
+
}
|
|
364
413
|
}
|
|
365
|
-
//if the
|
|
366
|
-
if (
|
|
367
|
-
return
|
|
414
|
+
//if the path is exactly `pkg:` or `libpkg:`
|
|
415
|
+
if (targetPath === fullScheme && !slash) {
|
|
416
|
+
return null;
|
|
368
417
|
}
|
|
418
|
+
//remove the filename
|
|
419
|
+
let containingFolder = path.normalize(path.dirname(containingFilePathAbsolute));
|
|
369
420
|
//start with the containing folder, split by slash
|
|
370
|
-
|
|
371
|
-
let result = containingFolder.split(/[\\/]/);
|
|
421
|
+
let result = containingFolder.split(path.sep);
|
|
372
422
|
//split on slash
|
|
373
|
-
let targetParts = path.
|
|
423
|
+
let targetParts = path.normalize(targetPath).split(path.sep);
|
|
374
424
|
for (let part of targetParts) {
|
|
375
425
|
if (part === '' || part === '.') {
|
|
376
426
|
//do nothing, it means current directory
|
|
@@ -384,19 +434,41 @@ class Util {
|
|
|
384
434
|
result.push(part);
|
|
385
435
|
}
|
|
386
436
|
}
|
|
387
|
-
return result.join(
|
|
437
|
+
return result.join(path.sep);
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Compute the replacement text for a file-path string (used in `import` statements and XML `<script uri>` attributes)
|
|
441
|
+
* when the target file is being renamed. Preserves the original path style: `pkg:/...` stays `pkg:/...`,
|
|
442
|
+
* relative paths stay relative (recomputed from the containing file's pkg path).
|
|
443
|
+
*
|
|
444
|
+
* @param originalText the path string as it appears in source (no surrounding quotes)
|
|
445
|
+
* @param containingFilePkgPath pkg path of the file containing the reference
|
|
446
|
+
* @param newTargetPkgPath pkg path of the renamed file (path-separator agnostic)
|
|
447
|
+
* @returns the new path string, or `null` if the original style is unsupported
|
|
448
|
+
*/
|
|
449
|
+
computeRenamedReferencePath(originalText, containingFilePkgPath, newTargetPkgPath) {
|
|
450
|
+
if (!originalText) {
|
|
451
|
+
return null;
|
|
452
|
+
}
|
|
453
|
+
const newPkgPathForwardSlash = path.normalize(newTargetPkgPath).split(path.sep).join('/');
|
|
454
|
+
const schemeMatch = /^(pkg|libpkg):\//i.exec(originalText);
|
|
455
|
+
if (schemeMatch) {
|
|
456
|
+
return `${schemeMatch[1]}:/${newPkgPathForwardSlash}`;
|
|
457
|
+
}
|
|
458
|
+
const relative = this.getRelativePath(containingFilePkgPath, newTargetPkgPath);
|
|
459
|
+
return relative.split(path.sep).join('/');
|
|
388
460
|
}
|
|
389
461
|
/**
|
|
390
462
|
* Compute the relative path from the source file to the target file
|
|
391
|
-
* @param
|
|
392
|
-
* @param
|
|
463
|
+
* @param pkgSrcPath - the absolute path to the source, where cwd is the package location
|
|
464
|
+
* @param pkgTargetPath - the absolute path to the target, where cwd is the package location
|
|
393
465
|
*/
|
|
394
|
-
getRelativePath(
|
|
395
|
-
|
|
396
|
-
|
|
466
|
+
getRelativePath(pkgSrcPath, pkgTargetPath) {
|
|
467
|
+
pkgSrcPath = path.normalize(pkgSrcPath);
|
|
468
|
+
pkgTargetPath = path.normalize(pkgTargetPath);
|
|
397
469
|
//break by path separator
|
|
398
|
-
let sourceParts =
|
|
399
|
-
let targetParts =
|
|
470
|
+
let sourceParts = pkgSrcPath.split(path.sep);
|
|
471
|
+
let targetParts = pkgTargetPath.split(path.sep);
|
|
400
472
|
let commonParts = [];
|
|
401
473
|
//find their common root
|
|
402
474
|
for (let i = 0; i < targetParts.length; i++) {
|
|
@@ -419,16 +491,26 @@ class Util {
|
|
|
419
491
|
resultParts = [...resultParts, ...targetParts];
|
|
420
492
|
return path.join(...resultParts);
|
|
421
493
|
}
|
|
494
|
+
getImportPackagePath(srcPath, pkgTargetPath) {
|
|
495
|
+
const srcExt = this.getExtension(srcPath);
|
|
496
|
+
const lowerSrcExt = srcExt.toLowerCase();
|
|
497
|
+
const lowerTargetExt = this.getExtension(pkgTargetPath).toLowerCase();
|
|
498
|
+
if (lowerSrcExt === '.bs' && lowerTargetExt === '.brs') {
|
|
499
|
+
// if source is .bs, use that as the import extenstion
|
|
500
|
+
return pkgTargetPath.substring(0, pkgTargetPath.length - lowerTargetExt.length) + srcExt;
|
|
501
|
+
}
|
|
502
|
+
return pkgTargetPath;
|
|
503
|
+
}
|
|
422
504
|
/**
|
|
423
505
|
* Walks left in a DottedGetExpression and returns a VariableExpression if found, or undefined if not found
|
|
424
506
|
*/
|
|
425
507
|
findBeginningVariableExpression(dottedGet) {
|
|
426
508
|
let left = dottedGet;
|
|
427
509
|
while (left) {
|
|
428
|
-
if (
|
|
510
|
+
if ((0, reflection_1.isVariableExpression)(left)) {
|
|
429
511
|
return left;
|
|
430
512
|
}
|
|
431
|
-
else if (
|
|
513
|
+
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
432
514
|
left = left.obj;
|
|
433
515
|
}
|
|
434
516
|
else {
|
|
@@ -437,9 +519,19 @@ class Util {
|
|
|
437
519
|
}
|
|
438
520
|
}
|
|
439
521
|
/**
|
|
440
|
-
*
|
|
522
|
+
* Do `a` and `b` overlap by at least one character. This returns false if they are at the edges. Here's some examples:
|
|
523
|
+
* ```
|
|
524
|
+
* | true | true | true | true | true | false | false | false | false |
|
|
525
|
+
* |------|------|------|------|------|-------|-------|-------|-------|
|
|
526
|
+
* | aa | aaa | aaa | aaa | a | aa | aa | a | a |
|
|
527
|
+
* | bbb | bb | bbb | b | bbb | bb | bb | b | a |
|
|
528
|
+
* ```
|
|
441
529
|
*/
|
|
442
530
|
rangesIntersect(a, b) {
|
|
531
|
+
//stop if the either range is misisng
|
|
532
|
+
if (!a || !b) {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
443
535
|
// Check if `a` is before `b`
|
|
444
536
|
if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character <= b.start.character)) {
|
|
445
537
|
return false;
|
|
@@ -451,74 +543,159 @@ class Util {
|
|
|
451
543
|
// These ranges must intersect
|
|
452
544
|
return true;
|
|
453
545
|
}
|
|
546
|
+
/**
|
|
547
|
+
* Do `a` and `b` overlap by at least one character or touch at the edges
|
|
548
|
+
* ```
|
|
549
|
+
* | true | true | true | true | true | true | true | false | false |
|
|
550
|
+
* |------|------|------|------|------|-------|-------|-------|-------|
|
|
551
|
+
* | aa | aaa | aaa | aaa | a | aa | aa | a | a |
|
|
552
|
+
* | bbb | bb | bbb | b | bbb | bb | bb | b | a |
|
|
553
|
+
* ```
|
|
554
|
+
*/
|
|
555
|
+
rangesIntersectOrTouch(a, b) {
|
|
556
|
+
//stop if the either range is misisng
|
|
557
|
+
if (!a || !b) {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
// Check if `a` is before `b`
|
|
561
|
+
if (a.end.line < b.start.line || (a.end.line === b.start.line && a.end.character < b.start.character)) {
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
// Check if `b` is before `a`
|
|
565
|
+
if (b.end.line < a.start.line || (b.end.line === a.start.line && b.end.character < a.start.character)) {
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
// These ranges must intersect
|
|
569
|
+
return true;
|
|
570
|
+
}
|
|
454
571
|
/**
|
|
455
572
|
* Test if `position` is in `range`. If the position is at the edges, will return true.
|
|
456
573
|
* Adapted from core vscode
|
|
457
|
-
* @param range
|
|
458
|
-
* @param position
|
|
459
574
|
*/
|
|
460
575
|
rangeContains(range, position) {
|
|
461
576
|
return this.comparePositionToRange(position, range) === 0;
|
|
462
577
|
}
|
|
463
578
|
comparePositionToRange(position, range) {
|
|
464
|
-
if
|
|
579
|
+
//stop if the either range is missng
|
|
580
|
+
if (!position || !range) {
|
|
581
|
+
return 0;
|
|
582
|
+
}
|
|
583
|
+
if (this.comparePosition(position, range.start) < 0) {
|
|
584
|
+
return -1;
|
|
585
|
+
}
|
|
586
|
+
if (this.comparePosition(position, range.end) > 0) {
|
|
587
|
+
return 1;
|
|
588
|
+
}
|
|
589
|
+
return 0;
|
|
590
|
+
}
|
|
591
|
+
comparePosition(a, b) {
|
|
592
|
+
//stop if the either position is missing
|
|
593
|
+
if (!a || !b) {
|
|
594
|
+
return 0;
|
|
595
|
+
}
|
|
596
|
+
if (a.line < b.line || (a.line === b.line && a.character < b.character)) {
|
|
465
597
|
return -1;
|
|
466
598
|
}
|
|
467
|
-
if (
|
|
599
|
+
if (a.line > b.line || (a.line === b.line && a.character > b.character)) {
|
|
468
600
|
return 1;
|
|
469
601
|
}
|
|
470
602
|
return 0;
|
|
471
603
|
}
|
|
472
604
|
/**
|
|
473
|
-
*
|
|
474
|
-
* @param text
|
|
605
|
+
* Is the inner range completely enclosed in the outer range
|
|
475
606
|
*/
|
|
476
|
-
|
|
477
|
-
return
|
|
478
|
-
|
|
479
|
-
if (err) {
|
|
480
|
-
reject(err);
|
|
481
|
-
}
|
|
482
|
-
else {
|
|
483
|
-
resolve(data);
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
});
|
|
607
|
+
isRangeInRange(inner, outer) {
|
|
608
|
+
return this.comparePosition(inner.start, outer.start) === 1 &&
|
|
609
|
+
this.comparePosition(inner.end, outer.end) === -1;
|
|
487
610
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
611
|
+
/**
|
|
612
|
+
* Combine all the documentation for a node - uses the AstNode's leadingTrivia property
|
|
613
|
+
* @param node the node to get the documentation for
|
|
614
|
+
* @param options extra options
|
|
615
|
+
* @param options.prettyPrint if true, will format the comment text for markdown
|
|
616
|
+
* @param options.commentTokens out Array of tokens that match the comment lines
|
|
617
|
+
*/
|
|
618
|
+
getNodeDocumentation(node, options = { prettyPrint: true }) {
|
|
619
|
+
var _a, _b, _c, _d;
|
|
620
|
+
if (!node) {
|
|
621
|
+
return '';
|
|
622
|
+
}
|
|
623
|
+
options = options !== null && options !== void 0 ? options : { prettyPrint: true };
|
|
624
|
+
options.commentTokens = (_a = options.commentTokens) !== null && _a !== void 0 ? _a : [];
|
|
625
|
+
const nodeTrivia = (_b = node.leadingTrivia) !== null && _b !== void 0 ? _b : [];
|
|
626
|
+
const leadingTrivia = (0, reflection_1.isStatement)(node)
|
|
627
|
+
? [...((_d = (_c = node.annotations) === null || _c === void 0 ? void 0 : _c.map(anno => { var _a; return (_a = anno.leadingTrivia) !== null && _a !== void 0 ? _a : []; }).flat()) !== null && _d !== void 0 ? _d : []), ...nodeTrivia]
|
|
628
|
+
: nodeTrivia;
|
|
629
|
+
const tokens = leadingTrivia === null || leadingTrivia === void 0 ? void 0 : leadingTrivia.filter(t => t.kind === TokenKind_1.TokenKind.Newline || t.kind === TokenKind_1.TokenKind.Comment);
|
|
630
|
+
const comments = [];
|
|
631
|
+
let newLinesInRow = 0;
|
|
632
|
+
for (let i = tokens.length - 1; i >= 0; i--) {
|
|
633
|
+
const token = tokens[i];
|
|
634
|
+
//skip whitespace and newline chars
|
|
635
|
+
if (token.kind === TokenKind_1.TokenKind.Comment) {
|
|
636
|
+
comments.push(token);
|
|
637
|
+
newLinesInRow = 0;
|
|
638
|
+
}
|
|
639
|
+
else if (token.kind === TokenKind_1.TokenKind.Newline) {
|
|
640
|
+
//skip these tokens
|
|
641
|
+
newLinesInRow++;
|
|
642
|
+
if (newLinesInRow > 1) {
|
|
643
|
+
// stop processing on empty line.
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
//any other token means there are no more comments
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
break;
|
|
493
650
|
}
|
|
494
651
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
while (subject.length < totalLength) {
|
|
500
|
-
subject = char + subject;
|
|
652
|
+
const jsDocCommentBlockLine = /(\/\*{2,}|\*{1,}\/)/i;
|
|
653
|
+
let usesjsDocCommentBlock = false;
|
|
654
|
+
if (comments.length === 0) {
|
|
655
|
+
return '';
|
|
501
656
|
}
|
|
502
|
-
return
|
|
657
|
+
return comments.reverse()
|
|
658
|
+
.map(x => ({ line: x.text.replace(/^('|rem)/i, '').trim(), token: x }))
|
|
659
|
+
.filter(({ line }) => {
|
|
660
|
+
if (jsDocCommentBlockLine.exec(line)) {
|
|
661
|
+
usesjsDocCommentBlock = true;
|
|
662
|
+
return false;
|
|
663
|
+
}
|
|
664
|
+
return true;
|
|
665
|
+
}).map(({ line, token }) => {
|
|
666
|
+
if (usesjsDocCommentBlock) {
|
|
667
|
+
if (line.startsWith('*')) {
|
|
668
|
+
//remove jsDoc leading '*'
|
|
669
|
+
line = line.slice(1).trim();
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
if (options.prettyPrint && line.startsWith('@')) {
|
|
673
|
+
// Handle jsdoc/brightscriptdoc tags specially
|
|
674
|
+
// make sure they are on their own markdown line, and add italics
|
|
675
|
+
const firstSpaceIndex = line.indexOf(' ');
|
|
676
|
+
if (firstSpaceIndex === -1) {
|
|
677
|
+
return `\n_${line}_`;
|
|
678
|
+
}
|
|
679
|
+
const firstWord = line.substring(0, firstSpaceIndex);
|
|
680
|
+
return `\n_${firstWord}_ ${line.substring(firstSpaceIndex + 1)}`;
|
|
681
|
+
}
|
|
682
|
+
if (options.commentTokens) {
|
|
683
|
+
options.commentTokens.push(token);
|
|
684
|
+
}
|
|
685
|
+
return line;
|
|
686
|
+
}).join('\n');
|
|
503
687
|
}
|
|
504
688
|
/**
|
|
505
|
-
*
|
|
506
|
-
*
|
|
689
|
+
* Prefixes a component name so it can be used as type in the symbol table, without polluting available symbols
|
|
690
|
+
*
|
|
691
|
+
* @param sgNodeName the Name of the component
|
|
692
|
+
* @returns the node name, prefixed with `roSGNode`
|
|
507
693
|
*/
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
//Uri annoyingly coverts all drive letters to lower case...so this will bring back whatever case it came in as
|
|
511
|
-
let match = /\/\/\/([a-z]:)/i.exec(uri);
|
|
512
|
-
if (match) {
|
|
513
|
-
let originalDriveCasing = match[1];
|
|
514
|
-
parsedPath = originalDriveCasing + parsedPath.substring(2);
|
|
515
|
-
}
|
|
516
|
-
const normalizedPath = path.normalize(parsedPath);
|
|
517
|
-
return normalizedPath;
|
|
694
|
+
getSgNodeTypeName(sgNodeName) {
|
|
695
|
+
return 'roSGNode' + sgNodeName;
|
|
518
696
|
}
|
|
519
697
|
/**
|
|
520
698
|
* Force the drive letter to lower case
|
|
521
|
-
* @param fullPath
|
|
522
699
|
*/
|
|
523
700
|
driveLetterToLower(fullPath) {
|
|
524
701
|
if (fullPath) {
|
|
@@ -534,53 +711,72 @@ class Util {
|
|
|
534
711
|
return fullPath;
|
|
535
712
|
}
|
|
536
713
|
/**
|
|
537
|
-
*
|
|
538
|
-
* This considers order and compares by equality.
|
|
714
|
+
* Replace the first instance of `search` in `subject` with `replacement`
|
|
539
715
|
*/
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
716
|
+
replaceCaseInsensitive(subject, search, replacement) {
|
|
717
|
+
let idx = subject.toLowerCase().indexOf(search.toLowerCase());
|
|
718
|
+
if (idx > -1) {
|
|
719
|
+
let result = subject.substring(0, idx) + replacement + subject.substring(idx + search.length);
|
|
720
|
+
return result;
|
|
543
721
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
return false;
|
|
547
|
-
}
|
|
722
|
+
else {
|
|
723
|
+
return subject;
|
|
548
724
|
}
|
|
549
|
-
return true;
|
|
550
725
|
}
|
|
551
726
|
/**
|
|
552
|
-
*
|
|
553
|
-
* @param srcPath The absolute path to the source file on disk
|
|
727
|
+
* Does the string appear to be a uri (i.e. does it start with `file:`)
|
|
554
728
|
*/
|
|
555
|
-
|
|
556
|
-
return
|
|
729
|
+
isUriLike(filePath) {
|
|
730
|
+
return (filePath === null || filePath === void 0 ? void 0 : filePath.indexOf('file:')) === 0; // eslint-disable-line @typescript-eslint/prefer-string-starts-ends-with
|
|
557
731
|
}
|
|
558
732
|
/**
|
|
559
|
-
*
|
|
560
|
-
* @param options
|
|
733
|
+
* Given a file path, convert it to a URI string
|
|
561
734
|
*/
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
735
|
+
pathToUri(filePath) {
|
|
736
|
+
if (!filePath) {
|
|
737
|
+
return filePath;
|
|
738
|
+
}
|
|
739
|
+
else if (this.pathToURICache.has(filePath)) {
|
|
740
|
+
return this.pathToURICache.get(filePath);
|
|
741
|
+
}
|
|
742
|
+
else if (this.isUriLike(filePath)) {
|
|
743
|
+
return filePath;
|
|
567
744
|
}
|
|
568
745
|
else {
|
|
569
|
-
|
|
746
|
+
const uri = vscode_uri_1.URI.file(filePath).toString();
|
|
747
|
+
this.pathToURICache.set(filePath, uri);
|
|
748
|
+
return uri;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Given a URI, convert that to a regular fs path
|
|
753
|
+
*/
|
|
754
|
+
uriToPath(uri) {
|
|
755
|
+
//if this doesn't look like a URI, then assume it's already a path
|
|
756
|
+
if (this.isUriLike(uri) === false) {
|
|
757
|
+
return uri;
|
|
758
|
+
}
|
|
759
|
+
let parsedPath = vscode_uri_1.URI.parse(uri).fsPath;
|
|
760
|
+
//Uri annoyingly converts all drive letters to lower case...so this will bring back whatever case it came in as
|
|
761
|
+
let match = /\/\/\/([a-z]:)/i.exec(uri);
|
|
762
|
+
if (match) {
|
|
763
|
+
let originalDriveCasing = match[1];
|
|
764
|
+
parsedPath = originalDriveCasing + parsedPath.substring(2);
|
|
570
765
|
}
|
|
766
|
+
const normalizedPath = path.normalize(parsedPath);
|
|
767
|
+
return normalizedPath;
|
|
571
768
|
}
|
|
572
769
|
/**
|
|
573
770
|
* Get paths to all files on disc that match this project's source list
|
|
574
771
|
*/
|
|
575
772
|
async getFilePaths(options) {
|
|
576
773
|
let rootDir = this.getRootDir(options);
|
|
577
|
-
let files = await rokuDeploy.getFilePaths(options.files, rootDir);
|
|
774
|
+
let files = await roku_deploy_1.rokuDeploy.getFilePaths(options.files, rootDir);
|
|
578
775
|
return files;
|
|
579
776
|
}
|
|
580
777
|
/**
|
|
581
778
|
* Given a path to a brs file, compute the path to a theoretical d.bs file.
|
|
582
|
-
* Only `.brs` files can have
|
|
583
|
-
* @param brsSrcPath The absolute path to the .brs source file on disk
|
|
779
|
+
* Only `.brs` files can have typedef path, so return undefined for everything else
|
|
584
780
|
*/
|
|
585
781
|
getTypedefPath(brsSrcPath) {
|
|
586
782
|
const typedefPath = brsSrcPath
|
|
@@ -593,51 +789,9 @@ class Util {
|
|
|
593
789
|
return undefined;
|
|
594
790
|
}
|
|
595
791
|
}
|
|
596
|
-
/**
|
|
597
|
-
* Determine whether this diagnostic should be supressed or not, based on brs comment-flags
|
|
598
|
-
* @param diagnostic
|
|
599
|
-
*/
|
|
600
|
-
diagnosticIsSuppressed(diagnostic) {
|
|
601
|
-
var _a, _b;
|
|
602
|
-
for (let flag of (_b = (_a = diagnostic.file) === null || _a === void 0 ? void 0 : _a.commentFlags) !== null && _b !== void 0 ? _b : []) {
|
|
603
|
-
//this diagnostic is affected by this flag
|
|
604
|
-
if (this.rangeContains(flag.affectedRange, diagnostic.range.start)) {
|
|
605
|
-
//if the flag acts upon this diagnostic's code
|
|
606
|
-
if (flag.codes === null || flag.codes.includes(diagnostic.code)) {
|
|
607
|
-
return true;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
/**
|
|
613
|
-
* Walks up the chain
|
|
614
|
-
* @param currentPath
|
|
615
|
-
*/
|
|
616
|
-
async findClosestConfigFile(currentPath) {
|
|
617
|
-
//make the path absolute
|
|
618
|
-
currentPath = path.resolve(path.normalize(currentPath));
|
|
619
|
-
let previousPath;
|
|
620
|
-
//using ../ on the root of the drive results in the same file path, so that's how we know we reached the top
|
|
621
|
-
while (previousPath !== currentPath) {
|
|
622
|
-
previousPath = currentPath;
|
|
623
|
-
let bsPath = path.join(currentPath, 'bsconfig.json');
|
|
624
|
-
let brsPath = path.join(currentPath, 'brsconfig.json');
|
|
625
|
-
if (await this.pathExists(bsPath)) {
|
|
626
|
-
return bsPath;
|
|
627
|
-
}
|
|
628
|
-
else if (await this.pathExists(brsPath)) {
|
|
629
|
-
return brsPath;
|
|
630
|
-
}
|
|
631
|
-
else {
|
|
632
|
-
//walk upwards one directory
|
|
633
|
-
currentPath = path.resolve(path.join(currentPath, '../'));
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
//got to the root path, no config file exists
|
|
637
|
-
}
|
|
638
792
|
/**
|
|
639
793
|
* Set a timeout for the specified milliseconds, and resolve the promise once the timeout is finished.
|
|
640
|
-
* @param milliseconds
|
|
794
|
+
* @param milliseconds the minimum number of milliseconds to sleep for
|
|
641
795
|
*/
|
|
642
796
|
sleep(milliseconds) {
|
|
643
797
|
return new Promise((resolve) => {
|
|
@@ -650,14 +804,6 @@ class Util {
|
|
|
650
804
|
}
|
|
651
805
|
});
|
|
652
806
|
}
|
|
653
|
-
/**
|
|
654
|
-
* Given an array, map and then flatten
|
|
655
|
-
* @param arr
|
|
656
|
-
* @param cb
|
|
657
|
-
*/
|
|
658
|
-
flatMap(array, cb) {
|
|
659
|
-
return Array.prototype.concat.apply([], array.map(cb));
|
|
660
|
-
}
|
|
661
807
|
/**
|
|
662
808
|
* Determines if the position is greater than the range. This means
|
|
663
809
|
* the position does not touch the range, and has a position greater than the end
|
|
@@ -682,56 +828,49 @@ class Util {
|
|
|
682
828
|
}
|
|
683
829
|
}
|
|
684
830
|
/**
|
|
685
|
-
* Get a
|
|
686
|
-
*/
|
|
687
|
-
getRange(startObj, endObj) {
|
|
688
|
-
return exports.util.createRangeFromPositions(startObj.range.start, endObj.range.end);
|
|
689
|
-
}
|
|
690
|
-
/**
|
|
691
|
-
* If the two items both start on the same line
|
|
831
|
+
* Get a range back from an object that contains (or is) a range
|
|
692
832
|
*/
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
833
|
+
extractRange(rangeIsh) {
|
|
834
|
+
var _a;
|
|
835
|
+
if (!rangeIsh) {
|
|
836
|
+
return undefined;
|
|
837
|
+
}
|
|
838
|
+
else if ('location' in rangeIsh) {
|
|
839
|
+
return (_a = rangeIsh.location) === null || _a === void 0 ? void 0 : _a.range;
|
|
840
|
+
}
|
|
841
|
+
else if ('range' in rangeIsh) {
|
|
842
|
+
return rangeIsh.range;
|
|
843
|
+
}
|
|
844
|
+
else if (vscode_languageserver_1.Range.is(rangeIsh)) {
|
|
845
|
+
return rangeIsh;
|
|
696
846
|
}
|
|
697
847
|
else {
|
|
698
|
-
return
|
|
848
|
+
return undefined;
|
|
699
849
|
}
|
|
700
850
|
}
|
|
701
851
|
/**
|
|
702
852
|
* If the two items have lines that touch
|
|
703
|
-
* @param first
|
|
704
|
-
* @param second
|
|
705
853
|
*/
|
|
706
854
|
linesTouch(first, second) {
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
855
|
+
const firstRange = this.extractRange(first);
|
|
856
|
+
const secondRange = this.extractRange(second);
|
|
857
|
+
if (firstRange && secondRange && (firstRange.start.line === secondRange.start.line ||
|
|
858
|
+
firstRange.start.line === secondRange.end.line ||
|
|
859
|
+
firstRange.end.line === secondRange.start.line ||
|
|
860
|
+
firstRange.end.line === secondRange.end.line)) {
|
|
711
861
|
return true;
|
|
712
862
|
}
|
|
713
863
|
else {
|
|
714
864
|
return false;
|
|
715
865
|
}
|
|
716
866
|
}
|
|
717
|
-
/**
|
|
718
|
-
* Given text with (or without) dots separating text, get the rightmost word.
|
|
719
|
-
* (i.e. given "A.B.C", returns "C". or "B" returns "B because there's no dot)
|
|
720
|
-
*/
|
|
721
|
-
getTextAfterFinalDot(name) {
|
|
722
|
-
if (name) {
|
|
723
|
-
let parts = name.split('.');
|
|
724
|
-
if (parts.length > 0) {
|
|
725
|
-
return parts[parts.length - 1];
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
867
|
/**
|
|
730
868
|
* Find a script import that the current position touches, or undefined if not found
|
|
731
869
|
*/
|
|
732
870
|
getScriptImportAtPosition(scriptImports, position) {
|
|
733
871
|
let scriptImport = scriptImports.find((x) => {
|
|
734
|
-
return x.filePathRange
|
|
872
|
+
return x.filePathRange &&
|
|
873
|
+
x.filePathRange.start.line === position.line &&
|
|
735
874
|
//column between start and end
|
|
736
875
|
position.character >= x.filePathRange.start.character &&
|
|
737
876
|
position.character <= x.filePathRange.end.character;
|
|
@@ -775,11 +914,46 @@ class Util {
|
|
|
775
914
|
rangeLines.push(lines[i]);
|
|
776
915
|
}
|
|
777
916
|
const lastLine = rangeLines.pop();
|
|
778
|
-
|
|
917
|
+
if (lastLine !== undefined) {
|
|
918
|
+
rangeLines.push(lastLine.substring(0, endCharacter));
|
|
919
|
+
}
|
|
779
920
|
return rangeLines.join('\n');
|
|
780
921
|
}
|
|
781
922
|
/**
|
|
782
|
-
* Helper for creating `
|
|
923
|
+
* Helper for creating `Location` objects. Prefer using this function because vscode-languageserver's `Location.create()` is significantly slower at scale
|
|
924
|
+
*/
|
|
925
|
+
createLocationFromRange(uri, range) {
|
|
926
|
+
return {
|
|
927
|
+
uri: exports.util.pathToUri(uri),
|
|
928
|
+
range: range
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Helper for creating `Location` objects from a file and range
|
|
933
|
+
*/
|
|
934
|
+
createLocationFromFileRange(file, range) {
|
|
935
|
+
return this.createLocationFromRange(this.pathToUri(file === null || file === void 0 ? void 0 : file.srcPath), range);
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Helper for creating `Location` objects by passing each range value in directly. Prefer using this function because vscode-languageserver's `Location.create()` is significantly slower at scale
|
|
939
|
+
*/
|
|
940
|
+
createLocation(startLine, startCharacter, endLine, endCharacter, uri) {
|
|
941
|
+
return {
|
|
942
|
+
uri: exports.util.pathToUri(uri),
|
|
943
|
+
range: {
|
|
944
|
+
start: {
|
|
945
|
+
line: startLine,
|
|
946
|
+
character: startCharacter
|
|
947
|
+
},
|
|
948
|
+
end: {
|
|
949
|
+
line: endLine,
|
|
950
|
+
character: endCharacter
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Helper for creating `Range` objects. Prefer using this function because vscode-languageserver's `Range.create()` is significantly slower.
|
|
783
957
|
*/
|
|
784
958
|
createRange(startLine, startCharacter, endLine, endCharacter) {
|
|
785
959
|
return {
|
|
@@ -797,141 +971,708 @@ class Util {
|
|
|
797
971
|
* Create a `Range` from two `Position`s
|
|
798
972
|
*/
|
|
799
973
|
createRangeFromPositions(startPosition, endPosition) {
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
line: endPosition.line,
|
|
807
|
-
character: endPosition.character
|
|
808
|
-
}
|
|
809
|
-
};
|
|
974
|
+
startPosition = startPosition !== null && startPosition !== void 0 ? startPosition : endPosition;
|
|
975
|
+
endPosition = endPosition !== null && endPosition !== void 0 ? endPosition : startPosition;
|
|
976
|
+
if (!startPosition && !endPosition) {
|
|
977
|
+
return undefined;
|
|
978
|
+
}
|
|
979
|
+
return this.createRange(startPosition.line, startPosition.character, endPosition.line, endPosition.character);
|
|
810
980
|
}
|
|
811
981
|
/**
|
|
812
|
-
*
|
|
813
|
-
* righthand range. Returns undefined if none of the items have a range.
|
|
982
|
+
* Clone a range
|
|
814
983
|
*/
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
if (leftmost && rightmost) {
|
|
831
|
-
break;
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
if (leftmost) {
|
|
835
|
-
return this.createRangeFromPositions(leftmost.range.start, rightmost.range.end);
|
|
984
|
+
cloneLocation(location) {
|
|
985
|
+
if (location) {
|
|
986
|
+
return {
|
|
987
|
+
uri: location.uri,
|
|
988
|
+
range: {
|
|
989
|
+
start: {
|
|
990
|
+
line: location.range.start.line,
|
|
991
|
+
character: location.range.start.character
|
|
992
|
+
},
|
|
993
|
+
end: {
|
|
994
|
+
line: location.range.end.line,
|
|
995
|
+
character: location.range.end.character
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
};
|
|
836
999
|
}
|
|
837
1000
|
else {
|
|
838
|
-
return
|
|
1001
|
+
return location;
|
|
839
1002
|
}
|
|
840
1003
|
}
|
|
841
1004
|
/**
|
|
842
|
-
*
|
|
1005
|
+
* Clone every token
|
|
843
1006
|
*/
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
result
|
|
1007
|
+
cloneToken(token) {
|
|
1008
|
+
if (token) {
|
|
1009
|
+
const result = {
|
|
1010
|
+
kind: token.kind,
|
|
1011
|
+
location: this.cloneLocation(token.location),
|
|
1012
|
+
text: token.text,
|
|
1013
|
+
isReserved: token.isReserved,
|
|
1014
|
+
leadingWhitespace: token.leadingWhitespace,
|
|
1015
|
+
leadingTrivia: token.leadingTrivia ? token.leadingTrivia.map(x => this.cloneToken(x)) : undefined
|
|
1016
|
+
};
|
|
1017
|
+
//handle those tokens that have charCode
|
|
1018
|
+
if ('charCode' in token) {
|
|
1019
|
+
result.charCode = token.charCode;
|
|
1020
|
+
}
|
|
1021
|
+
return result;
|
|
1022
|
+
}
|
|
1023
|
+
else {
|
|
1024
|
+
return token;
|
|
859
1025
|
}
|
|
860
|
-
return result;
|
|
861
1026
|
}
|
|
862
1027
|
/**
|
|
863
|
-
*
|
|
1028
|
+
* Gets the bounding range of a bunch of ranges or objects that have ranges
|
|
1029
|
+
* TODO: this does a full iteration of the args. If the args were guaranteed to be in range order, we could optimize this
|
|
864
1030
|
*/
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1031
|
+
createBoundingLocation(...locatables) {
|
|
1032
|
+
var _a, _b;
|
|
1033
|
+
let uri;
|
|
1034
|
+
let startPosition;
|
|
1035
|
+
let endPosition;
|
|
1036
|
+
for (let locatable of locatables) {
|
|
1037
|
+
let range;
|
|
1038
|
+
if (!locatable) {
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
else if ('location' in locatable) {
|
|
1042
|
+
range = (_a = locatable.location) === null || _a === void 0 ? void 0 : _a.range;
|
|
1043
|
+
if (!uri) {
|
|
1044
|
+
uri = (_b = locatable.location) === null || _b === void 0 ? void 0 : _b.uri;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
else if (vscode_languageserver_1.Location.is(locatable)) {
|
|
1048
|
+
range = locatable.range;
|
|
1049
|
+
if (!uri) {
|
|
1050
|
+
uri = locatable.uri;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
else if ('range' in locatable) {
|
|
1054
|
+
range = locatable.range;
|
|
1055
|
+
}
|
|
1056
|
+
else {
|
|
1057
|
+
range = locatable;
|
|
1058
|
+
}
|
|
1059
|
+
//skip undefined locations or locations without a range
|
|
1060
|
+
if (!range) {
|
|
1061
|
+
continue;
|
|
1062
|
+
}
|
|
1063
|
+
if (!startPosition) {
|
|
1064
|
+
startPosition = range.start;
|
|
1065
|
+
}
|
|
1066
|
+
else if (this.comparePosition(range.start, startPosition) < 0) {
|
|
1067
|
+
startPosition = range.start;
|
|
1068
|
+
}
|
|
1069
|
+
if (!endPosition) {
|
|
1070
|
+
endPosition = range.end;
|
|
1071
|
+
}
|
|
1072
|
+
else if (this.comparePosition(range.end, endPosition) > 0) {
|
|
1073
|
+
endPosition = range.end;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if (startPosition && endPosition) {
|
|
1077
|
+
return exports.util.createLocation(startPosition.line, startPosition.character, endPosition.line, endPosition.character, uri);
|
|
1078
|
+
}
|
|
1079
|
+
else {
|
|
1080
|
+
return undefined;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Gets the bounding range of a bunch of ranges or objects that have ranges
|
|
1085
|
+
* TODO: this does a full iteration of the args. If the args were guaranteed to be in range order, we could optimize this
|
|
1086
|
+
*/
|
|
1087
|
+
createBoundingRange(...locatables) {
|
|
1088
|
+
var _a;
|
|
1089
|
+
return (_a = this.createBoundingLocation(...locatables)) === null || _a === void 0 ? void 0 : _a.range;
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Gets the bounding range of an object that contains a bunch of tokens
|
|
1093
|
+
* @param tokens Object with tokens in it
|
|
1094
|
+
* @returns Range containing all the tokens
|
|
1095
|
+
*/
|
|
1096
|
+
createBoundingLocationFromTokens(tokens) {
|
|
1097
|
+
var _a;
|
|
1098
|
+
let uri;
|
|
1099
|
+
let startPosition;
|
|
1100
|
+
let endPosition;
|
|
1101
|
+
for (let key in tokens) {
|
|
1102
|
+
let token = tokens === null || tokens === void 0 ? void 0 : tokens[key];
|
|
1103
|
+
let locatableRange = (_a = token === null || token === void 0 ? void 0 : token.location) === null || _a === void 0 ? void 0 : _a.range;
|
|
1104
|
+
if (!locatableRange) {
|
|
1105
|
+
continue;
|
|
1106
|
+
}
|
|
1107
|
+
if (!startPosition) {
|
|
1108
|
+
startPosition = locatableRange.start;
|
|
1109
|
+
}
|
|
1110
|
+
else if (this.comparePosition(locatableRange.start, startPosition) < 0) {
|
|
1111
|
+
startPosition = locatableRange.start;
|
|
1112
|
+
}
|
|
1113
|
+
if (!endPosition) {
|
|
1114
|
+
endPosition = locatableRange.end;
|
|
1115
|
+
}
|
|
1116
|
+
else if (this.comparePosition(locatableRange.end, endPosition) > 0) {
|
|
1117
|
+
endPosition = locatableRange.end;
|
|
1118
|
+
}
|
|
1119
|
+
if (!uri) {
|
|
1120
|
+
uri = token.location.uri;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
if (startPosition && endPosition) {
|
|
1124
|
+
return this.createLocation(startPosition.line, startPosition.character, endPosition.line, endPosition.character, uri);
|
|
1125
|
+
}
|
|
1126
|
+
else {
|
|
1127
|
+
return undefined;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Create a `Position` object. Prefer this over `Position.create` for performance reasons.
|
|
1132
|
+
*/
|
|
1133
|
+
createPosition(line, character) {
|
|
1134
|
+
return {
|
|
1135
|
+
line: line,
|
|
1136
|
+
character: character
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Convert a token into a BscType
|
|
1141
|
+
*/
|
|
1142
|
+
tokenToBscType(token) {
|
|
1143
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
870
1144
|
switch (token.kind) {
|
|
871
|
-
case
|
|
872
|
-
|
|
873
|
-
case
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
case
|
|
877
|
-
return
|
|
878
|
-
case
|
|
879
|
-
return
|
|
880
|
-
case
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
return
|
|
886
|
-
case
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
case
|
|
893
|
-
return
|
|
894
|
-
case
|
|
895
|
-
return
|
|
896
|
-
case
|
|
897
|
-
|
|
898
|
-
case
|
|
899
|
-
|
|
900
|
-
case
|
|
901
|
-
return
|
|
902
|
-
case
|
|
903
|
-
|
|
904
|
-
case
|
|
1145
|
+
case TokenKind_1.TokenKind.Boolean:
|
|
1146
|
+
return BooleanType_1.BooleanType.instance;
|
|
1147
|
+
case TokenKind_1.TokenKind.True:
|
|
1148
|
+
case TokenKind_1.TokenKind.False:
|
|
1149
|
+
return BooleanType_1.BooleanType.instance;
|
|
1150
|
+
case TokenKind_1.TokenKind.Double:
|
|
1151
|
+
return DoubleType_1.DoubleType.instance;
|
|
1152
|
+
case TokenKind_1.TokenKind.DoubleLiteral:
|
|
1153
|
+
return DoubleType_1.DoubleType.instance;
|
|
1154
|
+
case TokenKind_1.TokenKind.Dynamic:
|
|
1155
|
+
return DynamicType_1.DynamicType.instance;
|
|
1156
|
+
case TokenKind_1.TokenKind.Float:
|
|
1157
|
+
return FloatType_1.FloatType.instance;
|
|
1158
|
+
case TokenKind_1.TokenKind.FloatLiteral:
|
|
1159
|
+
return FloatType_1.FloatType.instance;
|
|
1160
|
+
case TokenKind_1.TokenKind.Function:
|
|
1161
|
+
return FunctionType_1.FunctionType.instance;
|
|
1162
|
+
case TokenKind_1.TokenKind.Integer:
|
|
1163
|
+
return IntegerType_1.IntegerType.instance;
|
|
1164
|
+
case TokenKind_1.TokenKind.IntegerLiteral:
|
|
1165
|
+
return IntegerType_1.IntegerType.instance;
|
|
1166
|
+
case TokenKind_1.TokenKind.Invalid:
|
|
1167
|
+
return InvalidType_1.InvalidType.instance;
|
|
1168
|
+
case TokenKind_1.TokenKind.LongInteger:
|
|
1169
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1170
|
+
case TokenKind_1.TokenKind.LongIntegerLiteral:
|
|
1171
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1172
|
+
case TokenKind_1.TokenKind.Object:
|
|
1173
|
+
return ObjectType_1.ObjectType.instance;
|
|
1174
|
+
case TokenKind_1.TokenKind.String:
|
|
1175
|
+
return StringType_1.StringType.instance;
|
|
1176
|
+
case TokenKind_1.TokenKind.StringLiteral:
|
|
1177
|
+
case TokenKind_1.TokenKind.TemplateStringExpressionBegin:
|
|
1178
|
+
case TokenKind_1.TokenKind.TemplateStringExpressionEnd:
|
|
1179
|
+
case TokenKind_1.TokenKind.TemplateStringQuasi:
|
|
1180
|
+
return StringType_1.StringType.instance;
|
|
1181
|
+
case TokenKind_1.TokenKind.Void:
|
|
1182
|
+
return VoidType_1.VoidType.instance;
|
|
1183
|
+
case TokenKind_1.TokenKind.Identifier:
|
|
905
1184
|
switch (token.text.toLowerCase()) {
|
|
906
1185
|
case 'boolean':
|
|
907
|
-
return
|
|
1186
|
+
return BooleanType_1.BooleanType.instance;
|
|
908
1187
|
case 'double':
|
|
909
|
-
return
|
|
1188
|
+
return DoubleType_1.DoubleType.instance;
|
|
1189
|
+
case 'dynamic':
|
|
1190
|
+
return DynamicType_1.DynamicType.instance;
|
|
910
1191
|
case 'float':
|
|
911
|
-
return
|
|
1192
|
+
return FloatType_1.FloatType.instance;
|
|
912
1193
|
case 'function':
|
|
913
|
-
return
|
|
1194
|
+
return FunctionType_1.FunctionType.instance;
|
|
914
1195
|
case 'integer':
|
|
915
|
-
return
|
|
1196
|
+
return IntegerType_1.IntegerType.instance;
|
|
916
1197
|
case 'invalid':
|
|
917
|
-
return
|
|
1198
|
+
return InvalidType_1.InvalidType.instance;
|
|
918
1199
|
case 'longinteger':
|
|
919
|
-
return
|
|
1200
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
920
1201
|
case 'object':
|
|
921
|
-
return
|
|
1202
|
+
return ObjectType_1.ObjectType.instance;
|
|
922
1203
|
case 'string':
|
|
923
|
-
return
|
|
1204
|
+
return StringType_1.StringType.instance;
|
|
924
1205
|
case 'void':
|
|
925
|
-
return
|
|
1206
|
+
return VoidType_1.VoidType.instance;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Deciphers the correct types for fields based on docs
|
|
1212
|
+
* https://developer.roku.com/en-ca/docs/references/scenegraph/xml-elements/interface.md
|
|
1213
|
+
* @param typeDescriptor the type descriptor from the docs
|
|
1214
|
+
* @returns {BscType} the known type, or dynamic
|
|
1215
|
+
*/
|
|
1216
|
+
getNodeFieldType(typeDescriptor, lookupTable) {
|
|
1217
|
+
let typeDescriptorLower = typeDescriptor.toLowerCase().trim().replace(/\*/g, '');
|
|
1218
|
+
if (typeDescriptorLower.startsWith('as ')) {
|
|
1219
|
+
typeDescriptorLower = typeDescriptorLower.substring(3).trim();
|
|
1220
|
+
}
|
|
1221
|
+
const nodeFilter = (new RegExp(/^\[?(.* node)/, 'i')).exec(typeDescriptorLower);
|
|
1222
|
+
if (nodeFilter === null || nodeFilter === void 0 ? void 0 : nodeFilter[1]) {
|
|
1223
|
+
typeDescriptorLower = nodeFilter[1].trim();
|
|
1224
|
+
}
|
|
1225
|
+
const parensFilter = (new RegExp(/(.*)\(.*\)/, 'gi')).exec(typeDescriptorLower);
|
|
1226
|
+
if (parensFilter === null || parensFilter === void 0 ? void 0 : parensFilter[1]) {
|
|
1227
|
+
typeDescriptorLower = parensFilter[1].trim();
|
|
1228
|
+
}
|
|
1229
|
+
const bscType = this.tokenToBscType((0, creators_1.createToken)(TokenKind_1.TokenKind.Identifier, typeDescriptorLower));
|
|
1230
|
+
if (bscType) {
|
|
1231
|
+
return bscType;
|
|
1232
|
+
}
|
|
1233
|
+
function getRect2dType() {
|
|
1234
|
+
const rect2dType = new AssociativeArrayType_1.AssociativeArrayType();
|
|
1235
|
+
rect2dType.addMember('height', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
|
|
1236
|
+
rect2dType.addMember('width', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
|
|
1237
|
+
rect2dType.addMember('x', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
|
|
1238
|
+
rect2dType.addMember('y', {}, FloatType_1.FloatType.instance, 1 /* SymbolTypeFlag.runtime */);
|
|
1239
|
+
return rect2dType;
|
|
1240
|
+
}
|
|
1241
|
+
function getColorType() {
|
|
1242
|
+
return (0, UnionType_1.unionTypeFactory)([IntegerType_1.IntegerType.instance, StringType_1.StringType.instance]);
|
|
1243
|
+
}
|
|
1244
|
+
//check for uniontypes
|
|
1245
|
+
const multipleTypes = typeDescriptorLower.split(' or ').map(s => s.trim());
|
|
1246
|
+
if (multipleTypes.length > 1) {
|
|
1247
|
+
const individualTypes = multipleTypes.map(t => this.getNodeFieldType(t, lookupTable));
|
|
1248
|
+
return (0, UnionType_1.unionTypeFactory)(individualTypes);
|
|
1249
|
+
}
|
|
1250
|
+
const typeIsArray = typeDescriptorLower.startsWith('array of ') || typeDescriptorLower.startsWith('roarray of ');
|
|
1251
|
+
if (typeIsArray) {
|
|
1252
|
+
const ofSearch = ' of ';
|
|
1253
|
+
const arrayPrefixLength = typeDescriptorLower.indexOf(ofSearch) + ofSearch.length;
|
|
1254
|
+
let arrayOfTypeName = typeDescriptorLower.substring(arrayPrefixLength); //cut off beginnin, eg. 'array of' or 'roarray of'
|
|
1255
|
+
if (arrayOfTypeName.endsWith('s')) {
|
|
1256
|
+
// remove "s" in "floats", etc.
|
|
1257
|
+
arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
|
|
1258
|
+
}
|
|
1259
|
+
if (arrayOfTypeName.endsWith('\'')) {
|
|
1260
|
+
// remove "'" in "float's", etc.
|
|
1261
|
+
arrayOfTypeName = arrayOfTypeName.substring(0, arrayOfTypeName.length - 1);
|
|
1262
|
+
}
|
|
1263
|
+
if (arrayOfTypeName === 'rectangle') {
|
|
1264
|
+
arrayOfTypeName = 'rect2d';
|
|
1265
|
+
}
|
|
1266
|
+
let arrayType = this.getNodeFieldType(arrayOfTypeName, lookupTable);
|
|
1267
|
+
return new ArrayType_1.ArrayType(arrayType);
|
|
1268
|
+
}
|
|
1269
|
+
else if (typeDescriptorLower.startsWith('option ')) {
|
|
1270
|
+
const actualTypeName = typeDescriptorLower.substring('option '.length); //cut off beginning 'option '
|
|
1271
|
+
return this.getNodeFieldType(actualTypeName, lookupTable);
|
|
1272
|
+
}
|
|
1273
|
+
else if (typeDescriptorLower.startsWith('value ')) {
|
|
1274
|
+
const actualTypeName = typeDescriptorLower.substring('value '.length); //cut off beginning 'value '
|
|
1275
|
+
return this.getNodeFieldType(actualTypeName, lookupTable);
|
|
1276
|
+
}
|
|
1277
|
+
else if (typeDescriptorLower === 'n/a') {
|
|
1278
|
+
return DynamicType_1.DynamicType.instance;
|
|
1279
|
+
}
|
|
1280
|
+
else if (typeDescriptorLower === 'uri') {
|
|
1281
|
+
return StringType_1.StringType.instance;
|
|
1282
|
+
}
|
|
1283
|
+
else if (typeDescriptorLower === 'color') {
|
|
1284
|
+
return getColorType();
|
|
1285
|
+
}
|
|
1286
|
+
else if (typeDescriptorLower === 'vector2d' || typeDescriptorLower === 'floatarray') {
|
|
1287
|
+
return new ArrayType_1.ArrayType(FloatType_1.FloatType.instance);
|
|
1288
|
+
}
|
|
1289
|
+
else if (typeDescriptorLower === 'vector2darray') {
|
|
1290
|
+
return new ArrayType_1.ArrayType(new ArrayType_1.ArrayType(FloatType_1.FloatType.instance));
|
|
1291
|
+
}
|
|
1292
|
+
else if (typeDescriptorLower === 'intarray') {
|
|
1293
|
+
return new ArrayType_1.ArrayType(IntegerType_1.IntegerType.instance);
|
|
1294
|
+
}
|
|
1295
|
+
else if (typeDescriptorLower === 'colorarray') {
|
|
1296
|
+
return new ArrayType_1.ArrayType(getColorType());
|
|
1297
|
+
}
|
|
1298
|
+
else if (typeDescriptorLower === 'boolarray') {
|
|
1299
|
+
return new ArrayType_1.ArrayType(BooleanType_1.BooleanType.instance);
|
|
1300
|
+
}
|
|
1301
|
+
else if (typeDescriptorLower === 'stringarray' || typeDescriptorLower === 'strarray') {
|
|
1302
|
+
return new ArrayType_1.ArrayType(StringType_1.StringType.instance);
|
|
1303
|
+
}
|
|
1304
|
+
else if (typeDescriptorLower === 'int') {
|
|
1305
|
+
return IntegerType_1.IntegerType.instance;
|
|
1306
|
+
}
|
|
1307
|
+
else if (typeDescriptorLower === 'time') {
|
|
1308
|
+
return DoubleType_1.DoubleType.instance;
|
|
1309
|
+
}
|
|
1310
|
+
else if (typeDescriptorLower === 'str') {
|
|
1311
|
+
return StringType_1.StringType.instance;
|
|
1312
|
+
}
|
|
1313
|
+
else if (typeDescriptorLower === 'bool') {
|
|
1314
|
+
return BooleanType_1.BooleanType.instance;
|
|
1315
|
+
}
|
|
1316
|
+
else if (typeDescriptorLower === 'array' || typeDescriptorLower === 'roarray') {
|
|
1317
|
+
return new ArrayType_1.ArrayType();
|
|
1318
|
+
}
|
|
1319
|
+
else if (typeDescriptorLower === 'assocarray' ||
|
|
1320
|
+
typeDescriptorLower === 'associative array' ||
|
|
1321
|
+
typeDescriptorLower === 'associativearray' ||
|
|
1322
|
+
typeDescriptorLower === 'roassociativearray' ||
|
|
1323
|
+
typeDescriptorLower.startsWith('associative array of') ||
|
|
1324
|
+
typeDescriptorLower.startsWith('associativearray of') ||
|
|
1325
|
+
typeDescriptorLower.startsWith('roassociativearray of')) {
|
|
1326
|
+
return new AssociativeArrayType_1.AssociativeArrayType();
|
|
1327
|
+
}
|
|
1328
|
+
else if (typeDescriptorLower === 'node') {
|
|
1329
|
+
return ComponentType_1.ComponentType.instance;
|
|
1330
|
+
}
|
|
1331
|
+
else if (typeDescriptorLower === 'nodearray') {
|
|
1332
|
+
return new ArrayType_1.ArrayType(ComponentType_1.ComponentType.instance);
|
|
1333
|
+
}
|
|
1334
|
+
else if (typeDescriptorLower === 'rect2d') {
|
|
1335
|
+
return getRect2dType();
|
|
1336
|
+
}
|
|
1337
|
+
else if (typeDescriptorLower === 'rect2darray') {
|
|
1338
|
+
return new ArrayType_1.ArrayType(getRect2dType());
|
|
1339
|
+
}
|
|
1340
|
+
else if (typeDescriptorLower === 'font') {
|
|
1341
|
+
return this.getNodeFieldType('roSGNodeFont', lookupTable);
|
|
1342
|
+
}
|
|
1343
|
+
else if (typeDescriptorLower === 'contentnode') {
|
|
1344
|
+
return this.getNodeFieldType('roSGNodeContentNode', lookupTable);
|
|
1345
|
+
}
|
|
1346
|
+
else if (typeDescriptorLower.endsWith(' node')) {
|
|
1347
|
+
return this.getNodeFieldType('roSgNode' + typeDescriptorLower.substring(0, typeDescriptorLower.length - 5), lookupTable);
|
|
1348
|
+
}
|
|
1349
|
+
else if (lookupTable) {
|
|
1350
|
+
//try doing a lookup
|
|
1351
|
+
return lookupTable.getSymbolType(typeDescriptorLower, {
|
|
1352
|
+
flags: 2 /* SymbolTypeFlag.typetime */,
|
|
1353
|
+
fullName: typeDescriptor,
|
|
1354
|
+
tableProvider: () => lookupTable
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1357
|
+
return DynamicType_1.DynamicType.instance;
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Return the type of the result of a binary operator
|
|
1361
|
+
* Note: compound assignments (eg. +=) internally use a binary expression, so that's why TokenKind.PlusEqual, etc. are here too
|
|
1362
|
+
*/
|
|
1363
|
+
binaryOperatorResultType(leftType, operator, rightType) {
|
|
1364
|
+
if (((0, reflection_1.isAnyReferenceType)(leftType) && !leftType.isResolvable()) ||
|
|
1365
|
+
((0, reflection_1.isAnyReferenceType)(rightType) && !rightType.isResolvable())) {
|
|
1366
|
+
return new ReferenceType_1.BinaryOperatorReferenceType(leftType, operator, rightType, (lhs, op, rhs) => {
|
|
1367
|
+
return this.binaryOperatorResultType(lhs, op, rhs);
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
// Try to find a common value of union type
|
|
1371
|
+
leftType = (0, helpers_1.getUniqueType)([leftType], UnionType_1.unionTypeFactory);
|
|
1372
|
+
rightType = (0, helpers_1.getUniqueType)([rightType], UnionType_1.unionTypeFactory);
|
|
1373
|
+
if ((0, reflection_1.isUnionType)(leftType)) {
|
|
1374
|
+
leftType = this.getHighestPriorityType(leftType.types);
|
|
1375
|
+
}
|
|
1376
|
+
if ((0, reflection_1.isUnionType)(rightType)) {
|
|
1377
|
+
rightType = this.getHighestPriorityType(rightType.types);
|
|
1378
|
+
}
|
|
1379
|
+
if ((0, reflection_1.isVoidType)(leftType) || (0, reflection_1.isVoidType)(rightType) || (0, reflection_1.isUninitializedType)(leftType) || (0, reflection_1.isUninitializedType)(rightType)) {
|
|
1380
|
+
return undefined;
|
|
1381
|
+
}
|
|
1382
|
+
if ((0, reflection_1.isEnumMemberType)(leftType)) {
|
|
1383
|
+
leftType = leftType.underlyingType;
|
|
1384
|
+
}
|
|
1385
|
+
if ((0, reflection_1.isEnumMemberType)(rightType)) {
|
|
1386
|
+
rightType = rightType.underlyingType;
|
|
1387
|
+
}
|
|
1388
|
+
// treat object type like dynamic
|
|
1389
|
+
if ((0, reflection_1.isObjectType)(leftType)) {
|
|
1390
|
+
leftType = DynamicType_1.DynamicType.instance;
|
|
1391
|
+
}
|
|
1392
|
+
if ((0, reflection_1.isObjectType)(rightType)) {
|
|
1393
|
+
rightType = DynamicType_1.DynamicType.instance;
|
|
1394
|
+
}
|
|
1395
|
+
let hasDouble = (0, reflection_1.isDoubleTypeLike)(leftType) || (0, reflection_1.isDoubleTypeLike)(rightType);
|
|
1396
|
+
let hasFloat = (0, reflection_1.isFloatTypeLike)(leftType) || (0, reflection_1.isFloatTypeLike)(rightType);
|
|
1397
|
+
let hasLongInteger = (0, reflection_1.isLongIntegerTypeLike)(leftType) || (0, reflection_1.isLongIntegerTypeLike)(rightType);
|
|
1398
|
+
let hasInvalid = (0, reflection_1.isInvalidTypeLike)(leftType) || (0, reflection_1.isInvalidTypeLike)(rightType);
|
|
1399
|
+
let hasDynamic = (0, reflection_1.isDynamicType)(leftType) || (0, reflection_1.isDynamicType)(rightType);
|
|
1400
|
+
let bothDynamic = (0, reflection_1.isDynamicType)(leftType) && (0, reflection_1.isDynamicType)(rightType);
|
|
1401
|
+
let bothNumbers = (0, reflection_1.isNumberTypeLike)(leftType) && (0, reflection_1.isNumberTypeLike)(rightType);
|
|
1402
|
+
let hasNumber = (0, reflection_1.isNumberTypeLike)(leftType) || (0, reflection_1.isNumberTypeLike)(rightType);
|
|
1403
|
+
let bothStrings = (0, reflection_1.isStringTypeLike)(leftType) && (0, reflection_1.isStringTypeLike)(rightType);
|
|
1404
|
+
let hasString = (0, reflection_1.isStringTypeLike)(leftType) || (0, reflection_1.isStringTypeLike)(rightType);
|
|
1405
|
+
let hasBoolean = (0, reflection_1.isBooleanTypeLike)(leftType) || (0, reflection_1.isBooleanTypeLike)(rightType);
|
|
1406
|
+
let eitherBooleanOrNum = ((0, reflection_1.isNumberTypeLike)(leftType) || (0, reflection_1.isBooleanTypeLike)(leftType)) && ((0, reflection_1.isNumberTypeLike)(rightType) || (0, reflection_1.isBooleanTypeLike)(rightType));
|
|
1407
|
+
let leftIsPrimitive = (0, reflection_1.isPrimitiveType)(leftType);
|
|
1408
|
+
let rightIsPrimitive = (0, reflection_1.isPrimitiveType)(rightType);
|
|
1409
|
+
let hasPrimitive = leftIsPrimitive || rightIsPrimitive;
|
|
1410
|
+
let nonDynamicType;
|
|
1411
|
+
if (hasPrimitive) {
|
|
1412
|
+
nonDynamicType = leftIsPrimitive ? leftType : rightType;
|
|
1413
|
+
}
|
|
1414
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
1415
|
+
switch (operator.kind) {
|
|
1416
|
+
// Math operators
|
|
1417
|
+
case TokenKind_1.TokenKind.Plus:
|
|
1418
|
+
case TokenKind_1.TokenKind.PlusEqual:
|
|
1419
|
+
if (bothStrings) {
|
|
1420
|
+
// "string" + "string" is the only binary expression allowed with strings
|
|
1421
|
+
return StringType_1.StringType.instance;
|
|
1422
|
+
}
|
|
1423
|
+
else if (hasString && hasDynamic) {
|
|
1424
|
+
// assume dynamicValue is a string
|
|
1425
|
+
return StringType_1.StringType.instance;
|
|
1426
|
+
}
|
|
1427
|
+
// eslint-disable-next-line no-fallthrough
|
|
1428
|
+
case TokenKind_1.TokenKind.Minus:
|
|
1429
|
+
case TokenKind_1.TokenKind.MinusEqual:
|
|
1430
|
+
case TokenKind_1.TokenKind.Star:
|
|
1431
|
+
case TokenKind_1.TokenKind.StarEqual:
|
|
1432
|
+
case TokenKind_1.TokenKind.Mod:
|
|
1433
|
+
if (bothNumbers) {
|
|
1434
|
+
if (hasDouble) {
|
|
1435
|
+
return DoubleType_1.DoubleType.instance;
|
|
1436
|
+
}
|
|
1437
|
+
else if (hasFloat) {
|
|
1438
|
+
return FloatType_1.FloatType.instance;
|
|
1439
|
+
}
|
|
1440
|
+
else if (hasLongInteger) {
|
|
1441
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1442
|
+
}
|
|
1443
|
+
return IntegerType_1.IntegerType.instance;
|
|
1444
|
+
}
|
|
1445
|
+
else if (hasNumber && hasDynamic) {
|
|
1446
|
+
// assume dynamic is a number
|
|
1447
|
+
return nonDynamicType;
|
|
1448
|
+
}
|
|
1449
|
+
break;
|
|
1450
|
+
case TokenKind_1.TokenKind.Forwardslash:
|
|
1451
|
+
case TokenKind_1.TokenKind.ForwardslashEqual:
|
|
1452
|
+
if (bothNumbers) {
|
|
1453
|
+
if (hasDouble) {
|
|
1454
|
+
return DoubleType_1.DoubleType.instance;
|
|
1455
|
+
}
|
|
1456
|
+
else if (hasFloat) {
|
|
1457
|
+
return FloatType_1.FloatType.instance;
|
|
1458
|
+
}
|
|
1459
|
+
else if (hasLongInteger) {
|
|
1460
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1461
|
+
}
|
|
1462
|
+
return FloatType_1.FloatType.instance;
|
|
1463
|
+
}
|
|
1464
|
+
else if (hasNumber && hasDynamic) {
|
|
1465
|
+
// assume dynamic is a number
|
|
1466
|
+
return nonDynamicType;
|
|
1467
|
+
}
|
|
1468
|
+
break;
|
|
1469
|
+
case TokenKind_1.TokenKind.Backslash:
|
|
1470
|
+
case TokenKind_1.TokenKind.BackslashEqual:
|
|
1471
|
+
if (bothNumbers) {
|
|
1472
|
+
if (hasLongInteger) {
|
|
1473
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1474
|
+
}
|
|
1475
|
+
return IntegerType_1.IntegerType.instance;
|
|
1476
|
+
}
|
|
1477
|
+
else if (hasNumber && hasDynamic) {
|
|
1478
|
+
// assume dynamic is a number
|
|
1479
|
+
return IntegerType_1.IntegerType.instance;
|
|
1480
|
+
}
|
|
1481
|
+
break;
|
|
1482
|
+
case TokenKind_1.TokenKind.Caret:
|
|
1483
|
+
if (bothNumbers) {
|
|
1484
|
+
if (hasDouble || hasLongInteger) {
|
|
1485
|
+
return DoubleType_1.DoubleType.instance;
|
|
1486
|
+
}
|
|
1487
|
+
else if (hasFloat) {
|
|
1488
|
+
return FloatType_1.FloatType.instance;
|
|
1489
|
+
}
|
|
1490
|
+
return IntegerType_1.IntegerType.instance;
|
|
926
1491
|
}
|
|
927
|
-
if (
|
|
928
|
-
|
|
1492
|
+
else if (hasNumber && hasDynamic) {
|
|
1493
|
+
// assume dynamic is a number
|
|
1494
|
+
return IntegerType_1.IntegerType.instance;
|
|
929
1495
|
}
|
|
1496
|
+
break;
|
|
1497
|
+
// Bitshift operators
|
|
1498
|
+
case TokenKind_1.TokenKind.LeftShift:
|
|
1499
|
+
case TokenKind_1.TokenKind.LeftShiftEqual:
|
|
1500
|
+
case TokenKind_1.TokenKind.RightShift:
|
|
1501
|
+
case TokenKind_1.TokenKind.RightShiftEqual:
|
|
1502
|
+
if (bothNumbers) {
|
|
1503
|
+
if (hasLongInteger) {
|
|
1504
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1505
|
+
}
|
|
1506
|
+
// Bitshifts are allowed with non-integer numerics
|
|
1507
|
+
// but will always truncate to ints
|
|
1508
|
+
return IntegerType_1.IntegerType.instance;
|
|
1509
|
+
}
|
|
1510
|
+
else if (hasNumber && hasDynamic) {
|
|
1511
|
+
// assume dynamic is a number
|
|
1512
|
+
return IntegerType_1.IntegerType.instance;
|
|
1513
|
+
}
|
|
1514
|
+
break;
|
|
1515
|
+
// Comparison operators
|
|
1516
|
+
// All comparison operators result in boolean
|
|
1517
|
+
case TokenKind_1.TokenKind.Equal:
|
|
1518
|
+
case TokenKind_1.TokenKind.LessGreater:
|
|
1519
|
+
// = and <> can accept invalid / dynamic
|
|
1520
|
+
if (hasDynamic || hasInvalid || bothStrings || eitherBooleanOrNum) {
|
|
1521
|
+
return BooleanType_1.BooleanType.instance;
|
|
1522
|
+
}
|
|
1523
|
+
break;
|
|
1524
|
+
case TokenKind_1.TokenKind.Greater:
|
|
1525
|
+
case TokenKind_1.TokenKind.Less:
|
|
1526
|
+
case TokenKind_1.TokenKind.GreaterEqual:
|
|
1527
|
+
case TokenKind_1.TokenKind.LessEqual:
|
|
1528
|
+
if (bothStrings || bothNumbers) {
|
|
1529
|
+
return BooleanType_1.BooleanType.instance;
|
|
1530
|
+
}
|
|
1531
|
+
else if ((hasNumber || hasString) && hasDynamic) {
|
|
1532
|
+
// assume dynamic is a valid type
|
|
1533
|
+
return BooleanType_1.BooleanType.instance;
|
|
1534
|
+
}
|
|
1535
|
+
break;
|
|
1536
|
+
// Logical or bitwise operators
|
|
1537
|
+
case TokenKind_1.TokenKind.Or:
|
|
1538
|
+
case TokenKind_1.TokenKind.And:
|
|
1539
|
+
if (bothNumbers) {
|
|
1540
|
+
// "and"/"or" represent bitwise operators
|
|
1541
|
+
if (hasLongInteger && !hasDouble && !hasFloat) {
|
|
1542
|
+
// 2 long ints or long int and int
|
|
1543
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1544
|
+
}
|
|
1545
|
+
return IntegerType_1.IntegerType.instance;
|
|
1546
|
+
}
|
|
1547
|
+
else if (eitherBooleanOrNum) {
|
|
1548
|
+
// "and"/"or" represent logical operators
|
|
1549
|
+
return BooleanType_1.BooleanType.instance;
|
|
1550
|
+
}
|
|
1551
|
+
else if (hasNumber && hasDynamic) {
|
|
1552
|
+
// assume dynamic is a valid type
|
|
1553
|
+
return IntegerType_1.IntegerType.instance;
|
|
1554
|
+
}
|
|
1555
|
+
else if (hasBoolean && hasDynamic) {
|
|
1556
|
+
// assume dynamic is a valid type
|
|
1557
|
+
return BooleanType_1.BooleanType.instance;
|
|
1558
|
+
}
|
|
1559
|
+
break;
|
|
930
1560
|
}
|
|
1561
|
+
if (bothDynamic) {
|
|
1562
|
+
return DynamicType_1.DynamicType.instance;
|
|
1563
|
+
}
|
|
1564
|
+
return undefined;
|
|
1565
|
+
}
|
|
1566
|
+
getHighestPriorityType(types, depth = 0) {
|
|
1567
|
+
let result;
|
|
1568
|
+
if (depth > 4) {
|
|
1569
|
+
// shortcut for very complicated types, or self-referencing union types
|
|
1570
|
+
return DynamicType_1.DynamicType.instance;
|
|
1571
|
+
}
|
|
1572
|
+
for (let type of types) {
|
|
1573
|
+
if ((0, reflection_1.isUnionType)(type)) {
|
|
1574
|
+
type = (0, helpers_1.getUniqueType)([type], UnionType_1.unionTypeFactory);
|
|
1575
|
+
if ((0, reflection_1.isUnionType)(type)) {
|
|
1576
|
+
type = this.getHighestPriorityType(type.types, depth + 1);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
if (!result) {
|
|
1580
|
+
result = type;
|
|
1581
|
+
}
|
|
1582
|
+
else {
|
|
1583
|
+
if (type.binaryOpPriorityLevel < result.binaryOpPriorityLevel) {
|
|
1584
|
+
result = type;
|
|
1585
|
+
}
|
|
1586
|
+
else if (type.binaryOpPriorityLevel === result.binaryOpPriorityLevel && !result.isEqual(type)) {
|
|
1587
|
+
// equal priority types, but not equal types, like Boolean and String... just be dynamic at this point
|
|
1588
|
+
result = DynamicType_1.DynamicType.instance;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
if ((0, reflection_1.isUninitializedType)(type)) {
|
|
1592
|
+
return type;
|
|
1593
|
+
}
|
|
1594
|
+
if ((0, reflection_1.isVoidType)(type)) {
|
|
1595
|
+
return type;
|
|
1596
|
+
}
|
|
1597
|
+
if ((0, reflection_1.isInvalidTypeLike)(type)) {
|
|
1598
|
+
return type;
|
|
1599
|
+
}
|
|
1600
|
+
if ((0, reflection_1.isObjectType)(type) && !(0, reflection_1.isDynamicType)(type)) {
|
|
1601
|
+
result = type;
|
|
1602
|
+
}
|
|
1603
|
+
if ((0, reflection_1.isDynamicType)(type)) {
|
|
1604
|
+
result = type;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
return result !== null && result !== void 0 ? result : DynamicType_1.DynamicType.instance;
|
|
1608
|
+
}
|
|
1609
|
+
/**
|
|
1610
|
+
* Return the type of the result of a unary operator
|
|
1611
|
+
*/
|
|
1612
|
+
unaryOperatorResultType(operator, exprType) {
|
|
1613
|
+
if ((0, reflection_1.isUnionType)(exprType)) {
|
|
1614
|
+
exprType = this.getHighestPriorityType(exprType.types);
|
|
1615
|
+
}
|
|
1616
|
+
if ((0, reflection_1.isVoidType)(exprType) || (0, reflection_1.isInvalidTypeLike)(exprType) || (0, reflection_1.isUninitializedType)(exprType)) {
|
|
1617
|
+
return undefined;
|
|
1618
|
+
}
|
|
1619
|
+
if ((0, reflection_1.isDynamicType)(exprType) || (0, reflection_1.isObjectType)(exprType)) {
|
|
1620
|
+
return exprType;
|
|
1621
|
+
}
|
|
1622
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
1623
|
+
switch (operator.kind) {
|
|
1624
|
+
// Math operators
|
|
1625
|
+
case TokenKind_1.TokenKind.Plus: // (`num = +num` is valid syntax)
|
|
1626
|
+
case TokenKind_1.TokenKind.Minus:
|
|
1627
|
+
if ((0, reflection_1.isNumberTypeLike)(exprType)) {
|
|
1628
|
+
// a negative number will be the same type, eg, double->double, int->int, etc.
|
|
1629
|
+
return this.getUnboxedType(exprType);
|
|
1630
|
+
}
|
|
1631
|
+
break;
|
|
1632
|
+
case TokenKind_1.TokenKind.Not:
|
|
1633
|
+
if ((0, reflection_1.isBooleanTypeLike)(exprType)) {
|
|
1634
|
+
return BooleanType_1.BooleanType.instance;
|
|
1635
|
+
}
|
|
1636
|
+
else if ((0, reflection_1.isNumberTypeLike)(exprType)) {
|
|
1637
|
+
//numbers can be "notted"
|
|
1638
|
+
// by default they go to ints, except longints, which stay that way
|
|
1639
|
+
if ((0, reflection_1.isLongIntegerTypeLike)(exprType)) {
|
|
1640
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1641
|
+
}
|
|
1642
|
+
return IntegerType_1.IntegerType.instance;
|
|
1643
|
+
}
|
|
1644
|
+
break;
|
|
1645
|
+
}
|
|
1646
|
+
return undefined;
|
|
1647
|
+
}
|
|
1648
|
+
getUnboxedType(boxedType) {
|
|
1649
|
+
if ((0, reflection_1.isIntegerTypeLike)(boxedType)) {
|
|
1650
|
+
return IntegerType_1.IntegerType.instance;
|
|
1651
|
+
}
|
|
1652
|
+
else if ((0, reflection_1.isLongIntegerTypeLike)(boxedType)) {
|
|
1653
|
+
return LongIntegerType_1.LongIntegerType.instance;
|
|
1654
|
+
}
|
|
1655
|
+
else if ((0, reflection_1.isFloatTypeLike)(boxedType)) {
|
|
1656
|
+
return FloatType_1.FloatType.instance;
|
|
1657
|
+
}
|
|
1658
|
+
else if ((0, reflection_1.isDoubleTypeLike)(boxedType)) {
|
|
1659
|
+
return DoubleType_1.DoubleType.instance;
|
|
1660
|
+
}
|
|
1661
|
+
else if ((0, reflection_1.isBooleanTypeLike)(boxedType)) {
|
|
1662
|
+
return BooleanType_1.BooleanType.instance;
|
|
1663
|
+
}
|
|
1664
|
+
else if ((0, reflection_1.isStringTypeLike)(boxedType)) {
|
|
1665
|
+
return StringType_1.StringType.instance;
|
|
1666
|
+
}
|
|
1667
|
+
else if ((0, reflection_1.isInvalidTypeLike)(boxedType)) {
|
|
1668
|
+
return InvalidType_1.InvalidType.instance;
|
|
1669
|
+
}
|
|
1670
|
+
return boxedType;
|
|
931
1671
|
}
|
|
932
1672
|
/**
|
|
933
1673
|
* Get the extension for the given file path. Basically the part after the final dot, except for
|
|
934
1674
|
* `d.bs` which is treated as single extension
|
|
1675
|
+
* @returns the file extension (i.e. ".d.bs", ".bs", ".brs", ".xml", ".jpg", etc...)
|
|
935
1676
|
*/
|
|
936
1677
|
getExtension(filePath) {
|
|
937
1678
|
filePath = filePath.toLowerCase();
|
|
@@ -939,21 +1680,18 @@ class Util {
|
|
|
939
1680
|
return '.d.bs';
|
|
940
1681
|
}
|
|
941
1682
|
else {
|
|
942
|
-
|
|
943
|
-
if (idx > -1) {
|
|
944
|
-
return filePath.substring(idx);
|
|
945
|
-
}
|
|
1683
|
+
return path.extname(filePath).toLowerCase();
|
|
946
1684
|
}
|
|
947
1685
|
}
|
|
948
1686
|
/**
|
|
949
1687
|
* Load and return the list of plugins
|
|
950
1688
|
*/
|
|
951
1689
|
loadPlugins(cwd, pathOrModules, onError) {
|
|
952
|
-
const logger =
|
|
1690
|
+
const logger = (0, logging_1.createLogger)();
|
|
953
1691
|
return pathOrModules.reduce((acc, pathOrModule) => {
|
|
954
1692
|
if (typeof pathOrModule === 'string') {
|
|
955
1693
|
try {
|
|
956
|
-
const loaded =
|
|
1694
|
+
const loaded = requireRelative(pathOrModule, cwd);
|
|
957
1695
|
const theExport = loaded.default ? loaded.default : loaded;
|
|
958
1696
|
let plugin;
|
|
959
1697
|
// legacy plugins returned a plugin object. If we find that, then add a warning
|
|
@@ -963,7 +1701,13 @@ class Util {
|
|
|
963
1701
|
// the official plugin format is a factory function that returns a new instance of a plugin.
|
|
964
1702
|
}
|
|
965
1703
|
else if (typeof theExport === 'function') {
|
|
966
|
-
plugin = theExport(
|
|
1704
|
+
plugin = theExport({
|
|
1705
|
+
version: this.getBrighterScriptVersion()
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
else {
|
|
1709
|
+
//this should never happen; somehow an invalid plugin has made it into here
|
|
1710
|
+
throw new Error(`TILT: Encountered an invalid plugin: ${String(plugin)}`);
|
|
967
1711
|
}
|
|
968
1712
|
if (!plugin.name) {
|
|
969
1713
|
plugin.name = pathOrModule;
|
|
@@ -982,45 +1726,45 @@ class Util {
|
|
|
982
1726
|
return acc;
|
|
983
1727
|
}, []);
|
|
984
1728
|
}
|
|
985
|
-
resolveRequire(cwd, pathOrModule) {
|
|
986
|
-
let target = pathOrModule;
|
|
987
|
-
if (!path.isAbsolute(pathOrModule)) {
|
|
988
|
-
const localPath = path.resolve(cwd, pathOrModule);
|
|
989
|
-
if (fs.existsSync(localPath)) {
|
|
990
|
-
target = localPath;
|
|
991
|
-
}
|
|
992
|
-
else {
|
|
993
|
-
const modulePath = path.resolve(cwd, 'node_modules', pathOrModule);
|
|
994
|
-
if (fs.existsSync(modulePath)) {
|
|
995
|
-
target = modulePath;
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
}
|
|
999
|
-
// eslint-disable-next-line
|
|
1000
|
-
return require(target);
|
|
1001
|
-
}
|
|
1002
1729
|
/**
|
|
1003
1730
|
* Gathers expressions, variables, and unique names from an expression.
|
|
1004
1731
|
* This is mostly used for the ternary expression
|
|
1005
1732
|
*/
|
|
1006
|
-
getExpressionInfo(expression) {
|
|
1733
|
+
getExpressionInfo(expression, file) {
|
|
1007
1734
|
const expressions = [expression];
|
|
1008
1735
|
const variableExpressions = [];
|
|
1009
1736
|
const uniqueVarNames = new Set();
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
expression === null || expression === void 0 ? void 0 : expression.walk((expression) => {
|
|
1013
|
-
if (astUtils_1.isExpression(expression)) {
|
|
1737
|
+
function expressionWalker(expression) {
|
|
1738
|
+
if ((0, reflection_1.isExpression)(expression)) {
|
|
1014
1739
|
expressions.push(expression);
|
|
1015
1740
|
}
|
|
1016
|
-
if (
|
|
1741
|
+
if ((0, reflection_1.isVariableExpression)(expression)) {
|
|
1017
1742
|
variableExpressions.push(expression);
|
|
1018
|
-
uniqueVarNames.add(expression.name.text);
|
|
1743
|
+
uniqueVarNames.add(expression.tokens.name.text);
|
|
1019
1744
|
}
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1745
|
+
}
|
|
1746
|
+
// Collect all expressions. Most of these expressions are fairly small so this should be quick!
|
|
1747
|
+
// This should only be called during transpile time and only when we actually need it.
|
|
1748
|
+
expression === null || expression === void 0 ? void 0 : expression.walk(expressionWalker, {
|
|
1749
|
+
walkMode: visitors_1.WalkMode.visitExpressions
|
|
1022
1750
|
});
|
|
1023
|
-
|
|
1751
|
+
//handle the expression itself (for situations when expression is a VariableExpression)
|
|
1752
|
+
expressionWalker(expression);
|
|
1753
|
+
const scope = file.program.getFirstScopeForFile(file);
|
|
1754
|
+
let filteredVarNames = [...uniqueVarNames];
|
|
1755
|
+
if (scope) {
|
|
1756
|
+
filteredVarNames = filteredVarNames.filter((varName) => {
|
|
1757
|
+
const varNameLower = varName.toLowerCase();
|
|
1758
|
+
// TODO: include namespaces in this filter
|
|
1759
|
+
return !scope.getEnumMap().has(varNameLower) &&
|
|
1760
|
+
!scope.getConstMap().has(varNameLower);
|
|
1761
|
+
});
|
|
1762
|
+
}
|
|
1763
|
+
return { expressions: expressions, varExpressions: variableExpressions, uniqueVarNames: filteredVarNames };
|
|
1764
|
+
}
|
|
1765
|
+
concatAnnotationLeadingTrivia(stmt) {
|
|
1766
|
+
var _a, _b;
|
|
1767
|
+
return [...((_b = (_a = stmt.annotations) === null || _a === void 0 ? void 0 : _a.map(anno => { var _a; return (_a = anno.leadingTrivia) !== null && _a !== void 0 ? _a : []; }).flat()) !== null && _b !== void 0 ? _b : []), ...stmt.leadingTrivia];
|
|
1024
1768
|
}
|
|
1025
1769
|
/**
|
|
1026
1770
|
* Create a SourceNode that maps every line to itself. Useful for creating maps for files
|
|
@@ -1037,129 +1781,105 @@ class Util {
|
|
|
1037
1781
|
return new source_map_1.SourceNode(null, null, source, chunks);
|
|
1038
1782
|
}
|
|
1039
1783
|
/**
|
|
1040
|
-
*
|
|
1041
|
-
*/
|
|
1042
|
-
cloneSGAttribute(attr, value) {
|
|
1043
|
-
return new SGTypes_1.SGAttribute({ text: attr.tokens.key.text, range: attr.range }, { text: '=' }, { text: '"' }, { text: value, range: attr.tokens.value.range }, { text: '"' });
|
|
1044
|
-
}
|
|
1045
|
-
/**
|
|
1046
|
-
* Shorthand for creating a new source node
|
|
1784
|
+
* Converts a path into a standardized format (drive letter to lower, remove extra slashes, use single slash type, resolve relative parts, etc...)
|
|
1047
1785
|
*/
|
|
1048
|
-
|
|
1049
|
-
if
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
//convert 0-based Range line to 1-based SourceNode line
|
|
1053
|
-
node.line = locatable.range.start.line + 1;
|
|
1054
|
-
//SourceNode columns are 0-based so no conversion necessary
|
|
1055
|
-
node.column = locatable.range.start.character;
|
|
1056
|
-
}
|
|
1057
|
-
return node;
|
|
1786
|
+
standardizePath(thePath) {
|
|
1787
|
+
//if we have the value in cache already, return it
|
|
1788
|
+
if (this.standardizePathCache.has(thePath)) {
|
|
1789
|
+
return this.standardizePathCache.get(thePath);
|
|
1058
1790
|
}
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
*/
|
|
1063
|
-
removeProtocol(pkgPath) {
|
|
1064
|
-
let match = /^[-a-z_]+:\//.exec(pkgPath);
|
|
1065
|
-
if (match) {
|
|
1066
|
-
return pkgPath.substring(match[0].length);
|
|
1791
|
+
const originalPath = thePath;
|
|
1792
|
+
if (typeof thePath !== 'string') {
|
|
1793
|
+
return thePath;
|
|
1067
1794
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1795
|
+
//handle `virtual:/` paths specially - just normalize slashes, don't use path.normalize which would mangle the `virtual:` prefix
|
|
1796
|
+
if (/^virtual:[\/\\]/i.test(thePath)) {
|
|
1797
|
+
// Strip the `virtual:` prefix, normalize slashes, then re-add the prefix
|
|
1798
|
+
thePath = 'virtual:/' + thePath.slice(8).replace(/^[\/\\]+/, '').replace(/[\/\\]+/g, '/').toLowerCase();
|
|
1799
|
+
this.standardizePathCache.set(originalPath, thePath);
|
|
1800
|
+
return thePath;
|
|
1070
1801
|
}
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}
|
|
1075
|
-
/*
|
|
1076
|
-
* Copy the version of bslib from local node_modules to the staging folder
|
|
1077
|
-
*/
|
|
1078
|
-
async copyBslibToStaging(stagingDir) {
|
|
1079
|
-
//copy bslib to the output directory
|
|
1080
|
-
await fsExtra.ensureDir(standardizePath(`${stagingDir}/source`));
|
|
1081
|
-
// eslint-disable-next-line
|
|
1082
|
-
const bslib = require('@rokucommunity/bslib');
|
|
1083
|
-
let source = bslib.source;
|
|
1084
|
-
//apply the `bslib_` prefix to the functions
|
|
1085
|
-
let match;
|
|
1086
|
-
const positions = [];
|
|
1087
|
-
const regexp = /^(\s*(?:function|sub)\s+)([a-z0-9_]+)/mg;
|
|
1088
|
-
// eslint-disable-next-line no-cond-assign
|
|
1089
|
-
while (match = regexp.exec(source)) {
|
|
1090
|
-
positions.push(match.index + match[1].length);
|
|
1802
|
+
//windows path.normalize will convert all slashes to backslashes and remove duplicates
|
|
1803
|
+
if (this.isWindows) {
|
|
1804
|
+
thePath = path.win32.normalize(thePath);
|
|
1091
1805
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1806
|
+
else {
|
|
1807
|
+
//replace all windows or consecutive slashes with path.sep
|
|
1808
|
+
thePath = thePath.replace(/[\/\\]+/g, '/');
|
|
1809
|
+
// only use path.normalize if dots are present since it's expensive
|
|
1810
|
+
if (thePath.includes('./')) {
|
|
1811
|
+
thePath = path.posix.normalize(thePath);
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
// Lowercase drive letter on Windows-like paths (e.g., "C:/...")
|
|
1815
|
+
if (thePath.charCodeAt(1) === 58 /* : */) {
|
|
1816
|
+
// eslint-disable-next-line no-var
|
|
1817
|
+
var firstChar = thePath.charCodeAt(0);
|
|
1818
|
+
if (firstChar >= 65 && firstChar <= 90) {
|
|
1819
|
+
thePath = String.fromCharCode(firstChar + 32) + thePath.slice(1);
|
|
1820
|
+
}
|
|
1095
1821
|
}
|
|
1096
|
-
|
|
1822
|
+
this.standardizePathCache.set(originalPath, thePath);
|
|
1823
|
+
return thePath;
|
|
1097
1824
|
}
|
|
1098
1825
|
/**
|
|
1099
|
-
* Given a Diagnostic or BsDiagnostic, return a
|
|
1826
|
+
* Given a Diagnostic or BsDiagnostic, return a deep clone of the diagnostic.
|
|
1827
|
+
* @param diagnostic the diagnostic to clone
|
|
1828
|
+
* @param relatedInformationFallbackLocation a default location to use for all `relatedInformation` entries that are missing a location
|
|
1100
1829
|
*/
|
|
1101
|
-
toDiagnostic(diagnostic) {
|
|
1102
|
-
var _a;
|
|
1103
|
-
|
|
1830
|
+
toDiagnostic(diagnostic, relatedInformationFallbackLocation) {
|
|
1831
|
+
var _a, _b, _c, _d, _e;
|
|
1832
|
+
let relatedInformation = (_a = diagnostic.relatedInformation) !== null && _a !== void 0 ? _a : [];
|
|
1833
|
+
if (relatedInformation.length > diagnosticUtils_1.MAX_RELATED_INFOS_COUNT) {
|
|
1834
|
+
const relatedInfoLength = relatedInformation.length;
|
|
1835
|
+
relatedInformation = relatedInformation.slice(0, diagnosticUtils_1.MAX_RELATED_INFOS_COUNT);
|
|
1836
|
+
relatedInformation.push({
|
|
1837
|
+
message: `...and ${relatedInfoLength - diagnosticUtils_1.MAX_RELATED_INFOS_COUNT} more`,
|
|
1838
|
+
location: exports.util.createLocationFromRange(' ', exports.util.createRange(0, 0, 0, 0))
|
|
1839
|
+
});
|
|
1840
|
+
}
|
|
1841
|
+
const range = (_c = (_b = diagnostic.location) === null || _b === void 0 ? void 0 : _b.range) !== null && _c !== void 0 ? _c : diagnostic.range;
|
|
1842
|
+
let result = {
|
|
1104
1843
|
severity: diagnostic.severity,
|
|
1105
|
-
range:
|
|
1844
|
+
range: range,
|
|
1106
1845
|
message: diagnostic.message,
|
|
1107
|
-
relatedInformation:
|
|
1846
|
+
relatedInformation: relatedInformation.map(x => {
|
|
1108
1847
|
//clone related information just in case a plugin added circular ref info here
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1848
|
+
const clone = Object.assign({}, x);
|
|
1849
|
+
if (!clone.location) {
|
|
1850
|
+
// use the fallback location if available
|
|
1851
|
+
if (relatedInformationFallbackLocation) {
|
|
1852
|
+
clone.location = exports.util.createLocationFromRange(relatedInformationFallbackLocation, range);
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
//remove this related information so it doesn't bring crash the language server
|
|
1856
|
+
return undefined;
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return clone;
|
|
1860
|
+
//filter out null relatedInformation items
|
|
1861
|
+
}).filter((x) => Boolean(x)),
|
|
1862
|
+
code: diagnostic.code ? diagnostic.code : diagnostic.legacyCode,
|
|
1863
|
+
source: (_d = diagnostic.source) !== null && _d !== void 0 ? _d : 'brs'
|
|
1113
1864
|
};
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
* Gets the minimum and maximum number of allowed params
|
|
1117
|
-
* @param params The list of callable parameters to check
|
|
1118
|
-
* @returns the minimum and maximum number of allowed params
|
|
1119
|
-
*/
|
|
1120
|
-
getMinMaxParamCount(params) {
|
|
1121
|
-
//get min/max parameter count for callable
|
|
1122
|
-
let minParams = 0;
|
|
1123
|
-
let maxParams = 0;
|
|
1124
|
-
let continueCheckingForRequired = true;
|
|
1125
|
-
for (let param of params) {
|
|
1126
|
-
maxParams++;
|
|
1127
|
-
//optional parameters must come last, so we can assume that minParams won't increase once we hit
|
|
1128
|
-
//the first isOptional
|
|
1129
|
-
if (continueCheckingForRequired && !param.isOptional) {
|
|
1130
|
-
minParams++;
|
|
1131
|
-
}
|
|
1132
|
-
else {
|
|
1133
|
-
continueCheckingForRequired = false;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
return { min: minParams, max: maxParams };
|
|
1137
|
-
}
|
|
1138
|
-
/**
|
|
1139
|
-
* Finds the array of callables from a container map, taking into account the function from which it was called
|
|
1140
|
-
* If the callable was called in a function in a namespace, functions in that namespace are preferred
|
|
1141
|
-
* @return an array with callable containers - could be empty if nothing was found
|
|
1142
|
-
*/
|
|
1143
|
-
getCallableContainersFromContainerMapByFunctionCall(callablesByLowerName, expCall) {
|
|
1144
|
-
let callablesWithThisName = [];
|
|
1145
|
-
const lowerName = expCall.name.toLowerCase();
|
|
1146
|
-
if (expCall.functionExpression.namespaceName) {
|
|
1147
|
-
// prefer namespaced function
|
|
1148
|
-
const potentialNamespacedCallable = expCall.functionExpression.namespaceName.getName(Parser_1.ParseMode.BrightScript).toLowerCase() + '_' + lowerName;
|
|
1149
|
-
callablesWithThisName = callablesByLowerName.get(potentialNamespacedCallable.toLowerCase());
|
|
1150
|
-
}
|
|
1151
|
-
if (!callablesWithThisName || callablesWithThisName.length === 0) {
|
|
1152
|
-
// just try it as is
|
|
1153
|
-
callablesWithThisName = callablesByLowerName.get(lowerName);
|
|
1865
|
+
if (((_e = diagnostic === null || diagnostic === void 0 ? void 0 : diagnostic.tags) === null || _e === void 0 ? void 0 : _e.length) > 0) {
|
|
1866
|
+
result.tags = diagnostic.tags;
|
|
1154
1867
|
}
|
|
1155
|
-
return
|
|
1868
|
+
return result;
|
|
1156
1869
|
}
|
|
1157
1870
|
/**
|
|
1158
1871
|
* Sort an array of objects that have a Range
|
|
1159
1872
|
*/
|
|
1160
1873
|
sortByRange(locatables) {
|
|
1161
1874
|
//sort the tokens by range
|
|
1162
|
-
return locatables.sort((a, b) => {
|
|
1875
|
+
return locatables === null || locatables === void 0 ? void 0 : locatables.sort((a, b) => {
|
|
1876
|
+
//handle undefined tokens to prevent crashes
|
|
1877
|
+
if (!(a === null || a === void 0 ? void 0 : a.range)) {
|
|
1878
|
+
return 1;
|
|
1879
|
+
}
|
|
1880
|
+
if (!(b === null || b === void 0 ? void 0 : b.range)) {
|
|
1881
|
+
return -1;
|
|
1882
|
+
}
|
|
1163
1883
|
//start line
|
|
1164
1884
|
if (a.range.start.line < b.range.start.line) {
|
|
1165
1885
|
return -1;
|
|
@@ -1192,26 +1912,873 @@ class Util {
|
|
|
1192
1912
|
});
|
|
1193
1913
|
}
|
|
1194
1914
|
/**
|
|
1195
|
-
*
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1915
|
+
* Wrap the given code in a markdown code fence (with the language)
|
|
1916
|
+
*/
|
|
1917
|
+
mdFence(code, language = '') {
|
|
1918
|
+
return '```' + language + '\n' + code + '\n```';
|
|
1919
|
+
}
|
|
1920
|
+
/**
|
|
1921
|
+
* Gets each part of the dotted get.
|
|
1922
|
+
* @param node any ast expression
|
|
1923
|
+
* @returns an array of the parts of the dotted get. If not fully a dotted get, then returns undefined
|
|
1924
|
+
*/
|
|
1925
|
+
getAllDottedGetParts(node) {
|
|
1926
|
+
//this is a hot function and has been optimized. Don't rewrite unless necessary
|
|
1927
|
+
const parts = [];
|
|
1928
|
+
let nextPart = node;
|
|
1929
|
+
loop: while (nextPart) {
|
|
1930
|
+
switch (nextPart === null || nextPart === void 0 ? void 0 : nextPart.kind) {
|
|
1931
|
+
case AstNode_1.AstNodeKind.AssignmentStatement:
|
|
1932
|
+
return [node.tokens.name];
|
|
1933
|
+
case AstNode_1.AstNodeKind.DottedGetExpression:
|
|
1934
|
+
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.name);
|
|
1935
|
+
nextPart = nextPart.obj;
|
|
1936
|
+
continue;
|
|
1937
|
+
case AstNode_1.AstNodeKind.CallExpression:
|
|
1938
|
+
nextPart = nextPart.callee;
|
|
1939
|
+
continue;
|
|
1940
|
+
case AstNode_1.AstNodeKind.CallfuncExpression:
|
|
1941
|
+
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.methodName);
|
|
1942
|
+
nextPart = nextPart.callee;
|
|
1943
|
+
continue;
|
|
1944
|
+
case AstNode_1.AstNodeKind.TypeExpression:
|
|
1945
|
+
nextPart = nextPart.expression;
|
|
1946
|
+
continue;
|
|
1947
|
+
case AstNode_1.AstNodeKind.VariableExpression:
|
|
1948
|
+
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.name);
|
|
1949
|
+
break loop;
|
|
1950
|
+
case AstNode_1.AstNodeKind.LiteralExpression:
|
|
1951
|
+
parts.push(nextPart === null || nextPart === void 0 ? void 0 : nextPart.tokens.value);
|
|
1952
|
+
break loop;
|
|
1953
|
+
case AstNode_1.AstNodeKind.IndexedGetExpression:
|
|
1954
|
+
nextPart = nextPart.obj;
|
|
1955
|
+
continue;
|
|
1956
|
+
case AstNode_1.AstNodeKind.FunctionParameterExpression:
|
|
1957
|
+
return [nextPart.tokens.name];
|
|
1958
|
+
case AstNode_1.AstNodeKind.GroupingExpression:
|
|
1959
|
+
parts.push((0, creators_1.createIdentifier)('()', nextPart.location));
|
|
1960
|
+
break loop;
|
|
1961
|
+
default:
|
|
1962
|
+
//we found a non-DottedGet expression, so return because this whole operation is invalid.
|
|
1963
|
+
return undefined;
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
return parts.reverse();
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* Given an expression, return all the DottedGet name parts as a string.
|
|
1970
|
+
* Mostly used to convert namespaced item full names to a strings
|
|
1971
|
+
*/
|
|
1972
|
+
getAllDottedGetPartsAsString(node, parseMode = Parser_1.ParseMode.BrighterScript, lastSep = '.') {
|
|
1973
|
+
var _a, _b;
|
|
1974
|
+
//this is a hot function and has been optimized. Don't rewrite unless necessary
|
|
1975
|
+
/* eslint-disable no-var */
|
|
1976
|
+
var sep = parseMode === Parser_1.ParseMode.BrighterScript ? '.' : '_';
|
|
1977
|
+
const parts = (_a = this.getAllDottedGetParts(node)) !== null && _a !== void 0 ? _a : [];
|
|
1978
|
+
var result = (_b = parts[0]) === null || _b === void 0 ? void 0 : _b.text;
|
|
1979
|
+
for (var i = 1; i < parts.length; i++) {
|
|
1980
|
+
//some parts can be undefined (e.g. an unfinished `widget@.` callfunc with no method name)
|
|
1981
|
+
const part = parts[i];
|
|
1982
|
+
if (!part) {
|
|
1983
|
+
continue;
|
|
1984
|
+
}
|
|
1985
|
+
result += (i === parts.length - 1 && parseMode === Parser_1.ParseMode.BrighterScript ? lastSep : sep) + part.text;
|
|
1986
|
+
}
|
|
1987
|
+
return result;
|
|
1988
|
+
/* eslint-enable no-var */
|
|
1989
|
+
}
|
|
1990
|
+
/**
|
|
1991
|
+
* Break an expression into each part.
|
|
1992
|
+
*/
|
|
1993
|
+
splitExpression(expression) {
|
|
1994
|
+
const parts = [expression];
|
|
1995
|
+
let nextPart = expression;
|
|
1996
|
+
while (nextPart) {
|
|
1997
|
+
if ((0, reflection_1.isDottedGetExpression)(nextPart) || (0, reflection_1.isIndexedGetExpression)(nextPart) || (0, reflection_1.isXmlAttributeGetExpression)(nextPart)) {
|
|
1998
|
+
nextPart = nextPart.obj;
|
|
1999
|
+
}
|
|
2000
|
+
else if ((0, reflection_1.isCallExpression)(nextPart) || (0, reflection_1.isCallfuncExpression)(nextPart)) {
|
|
2001
|
+
nextPart = nextPart.callee;
|
|
2002
|
+
}
|
|
2003
|
+
else if ((0, reflection_1.isTypeExpression)(nextPart)) {
|
|
2004
|
+
nextPart = nextPart.expression;
|
|
2005
|
+
}
|
|
2006
|
+
else {
|
|
2007
|
+
break;
|
|
2008
|
+
}
|
|
2009
|
+
parts.unshift(nextPart);
|
|
2010
|
+
}
|
|
2011
|
+
return parts;
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Returns an integer if valid, or undefined. Eliminates checking for NaN
|
|
2015
|
+
*/
|
|
2016
|
+
parseInt(value) {
|
|
2017
|
+
const result = parseInt(value);
|
|
2018
|
+
if (!isNaN(result)) {
|
|
2019
|
+
return result;
|
|
2020
|
+
}
|
|
2021
|
+
else {
|
|
2022
|
+
return undefined;
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Converts a range to a string in the format 1:2-3:4
|
|
2027
|
+
*/
|
|
2028
|
+
rangeToString(range) {
|
|
2029
|
+
var _a, _b, _c, _d;
|
|
2030
|
+
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}`;
|
|
2031
|
+
}
|
|
2032
|
+
validateTooDeepFile(file) {
|
|
2033
|
+
var _a, _b;
|
|
2034
|
+
//find any files nested too deep
|
|
2035
|
+
let destPath = (_a = file === null || file === void 0 ? void 0 : file.destPath) === null || _a === void 0 ? void 0 : _a.toString();
|
|
2036
|
+
let rootFolder = destPath === null || destPath === void 0 ? void 0 : destPath.replace(/^pkg:/, '').split(/[\\\/]/)[0].toLowerCase();
|
|
2037
|
+
if ((0, reflection_1.isBrsFile)(file) && rootFolder !== 'source') {
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
if ((0, reflection_1.isXmlFile)(file) && rootFolder !== 'components') {
|
|
2041
|
+
return;
|
|
2042
|
+
}
|
|
2043
|
+
let fileDepth = this.getParentDirectoryCount(destPath);
|
|
2044
|
+
if (fileDepth >= 8) {
|
|
2045
|
+
(_b = file.program) === null || _b === void 0 ? void 0 : _b.diagnostics.register(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.detectedTooDeepFileSource(fileDepth)), { location: exports.util.createLocationFromFileRange(file, this.createRange(0, 0, 0, Number.MAX_VALUE)) }));
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
/**
|
|
2049
|
+
* Execute dispose for a series of disposable items
|
|
2050
|
+
* @param disposables a list of functions or disposables
|
|
2051
|
+
*/
|
|
2052
|
+
applyDispose(disposables) {
|
|
2053
|
+
var _a;
|
|
2054
|
+
for (const disposable of disposables !== null && disposables !== void 0 ? disposables : []) {
|
|
2055
|
+
if (typeof disposable === 'function') {
|
|
2056
|
+
disposable();
|
|
2057
|
+
}
|
|
2058
|
+
else {
|
|
2059
|
+
(_a = disposable === null || disposable === void 0 ? void 0 : disposable.dispose) === null || _a === void 0 ? void 0 : _a.call(disposable);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
/**
|
|
2064
|
+
* Race a series of promises, and return the first one that resolves AND matches the matcher function.
|
|
2065
|
+
* If all of the promises reject, then this will emit an AggregatreError with all of the errors.
|
|
2066
|
+
* If at least one promise resolves, then this will log all of the errors to the console
|
|
2067
|
+
* If at least one promise resolves but none of them match the matcher, then this will return undefined.
|
|
2068
|
+
* @param promises all of the promises to race
|
|
2069
|
+
* @param matcher a function that should return true if this value should be kept. Returning any value other than true means `false`
|
|
2070
|
+
* @returns the first resolved value that matches the matcher, or undefined if none of them match
|
|
2071
|
+
*/
|
|
2072
|
+
async promiseRaceMatch(promises, matcher) {
|
|
2073
|
+
const workingPromises = [
|
|
2074
|
+
...promises
|
|
2075
|
+
];
|
|
2076
|
+
const results = [];
|
|
2077
|
+
let returnValue;
|
|
2078
|
+
while (workingPromises.length > 0) {
|
|
2079
|
+
//race the promises. If any of them resolve, evaluate it against the matcher. If that passes, return the value. otherwise, eliminate this promise and try again
|
|
2080
|
+
const result = await Promise.race(workingPromises.map((promise, i) => {
|
|
2081
|
+
return Promise.resolve(promise)
|
|
2082
|
+
.then(value => ({ value: value, index: i }))
|
|
2083
|
+
.catch(error => ({ error: error, index: i }));
|
|
2084
|
+
}));
|
|
2085
|
+
results.push(result);
|
|
2086
|
+
//if we got a value and it matches the matcher, return it
|
|
2087
|
+
if ('value' in result && (matcher === null || matcher === void 0 ? void 0 : matcher(result.value)) === true) {
|
|
2088
|
+
returnValue = result.value;
|
|
2089
|
+
break;
|
|
2090
|
+
}
|
|
2091
|
+
//remove this non-matched (or errored) promise from the list and try again
|
|
2092
|
+
workingPromises.splice(result.index, 1);
|
|
2093
|
+
}
|
|
2094
|
+
const errors = results
|
|
2095
|
+
.filter(x => 'error' in x)
|
|
2096
|
+
.map(x => x.error);
|
|
2097
|
+
//if all of them crashed, then reject
|
|
2098
|
+
if (promises.length > 0 && errors.length === promises.length) {
|
|
2099
|
+
throw new AggregateError(errors, 'All requests failed. First error message: ' + errors[0].message);
|
|
2100
|
+
}
|
|
2101
|
+
else {
|
|
2102
|
+
//log all of the errors
|
|
2103
|
+
for (const error of errors) {
|
|
2104
|
+
console.error(error);
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
//return the matched value, or undefined if there wasn't one
|
|
2108
|
+
return returnValue;
|
|
2109
|
+
}
|
|
2110
|
+
/**
|
|
2111
|
+
* Wraps SourceNode's constructor to be compatible with the TranspileResult type
|
|
2112
|
+
*/
|
|
2113
|
+
sourceNodeFromTranspileResult(line, column, source, chunks, name) {
|
|
2114
|
+
// we can use a typecast rather than actually transforming the data because SourceNode
|
|
2115
|
+
// accepts a more permissive type than its typedef states
|
|
2116
|
+
return new source_map_1.SourceNode(line, column, source, chunks, name);
|
|
2117
|
+
}
|
|
2118
|
+
/**
|
|
2119
|
+
* Find the index of the last item in the array that matches.
|
|
2120
|
+
*/
|
|
2121
|
+
findLastIndex(array, matcher) {
|
|
2122
|
+
for (let i = array.length - 1; i >= 0; i--) {
|
|
2123
|
+
if (matcher(array[i])) {
|
|
2124
|
+
return i;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
processTypeChain(typeChain) {
|
|
2129
|
+
var _a, _b, _c, _d, _e;
|
|
2130
|
+
let fullChainName = '';
|
|
2131
|
+
let fullErrorName = '';
|
|
2132
|
+
let itemName = '';
|
|
2133
|
+
let previousTypeName = '';
|
|
2134
|
+
let parentTypeName = '';
|
|
2135
|
+
let itemTypeKind = '';
|
|
2136
|
+
let parentTypeKind = '';
|
|
2137
|
+
let astNode;
|
|
2138
|
+
let errorLocation;
|
|
2139
|
+
let containsDynamic = false;
|
|
2140
|
+
let continueResolvingAllItems = true;
|
|
2141
|
+
let crossedCallFunc = false;
|
|
2142
|
+
for (let i = 0; i < typeChain.length; i++) {
|
|
2143
|
+
const chainItem = typeChain[i];
|
|
2144
|
+
const dotSep = (_b = (_a = chainItem.separatorToken) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '.';
|
|
2145
|
+
if (i > 0) {
|
|
2146
|
+
fullChainName += dotSep;
|
|
2147
|
+
}
|
|
2148
|
+
fullChainName += chainItem.name;
|
|
2149
|
+
if (continueResolvingAllItems) {
|
|
2150
|
+
parentTypeName = previousTypeName;
|
|
2151
|
+
parentTypeKind = itemTypeKind;
|
|
2152
|
+
fullErrorName = previousTypeName ? `${previousTypeName}${dotSep}${chainItem.name}` : chainItem.name;
|
|
2153
|
+
itemTypeKind = (_c = chainItem.type) === null || _c === void 0 ? void 0 : _c.kind;
|
|
2154
|
+
let typeString = (_d = chainItem.type) === null || _d === void 0 ? void 0 : _d.toString();
|
|
2155
|
+
let typeToFindStringFor = chainItem.type;
|
|
2156
|
+
while (typeToFindStringFor) {
|
|
2157
|
+
if ((0, reflection_1.isCompoundType)(chainItem.type)) {
|
|
2158
|
+
typeString = `(${typeToFindStringFor.toString()})`;
|
|
2159
|
+
break;
|
|
2160
|
+
}
|
|
2161
|
+
else if ((0, reflection_1.isCallableType)(typeToFindStringFor)) {
|
|
2162
|
+
if ((0, reflection_1.isTypedFunctionType)(typeToFindStringFor) && i < typeChain.length - 1) {
|
|
2163
|
+
typeToFindStringFor = typeToFindStringFor.returnType;
|
|
2164
|
+
}
|
|
2165
|
+
else {
|
|
2166
|
+
typeString = 'function';
|
|
2167
|
+
break;
|
|
2168
|
+
}
|
|
2169
|
+
parentTypeName = previousTypeName;
|
|
2170
|
+
}
|
|
2171
|
+
else if ((0, reflection_1.isNamespaceType)(typeToFindStringFor) && parentTypeName) {
|
|
2172
|
+
const chainItemTypeName = typeToFindStringFor.toString();
|
|
2173
|
+
typeString = parentTypeName + '.' + chainItemTypeName;
|
|
2174
|
+
if (chainItemTypeName.toLowerCase().startsWith(parentTypeName.toLowerCase())) {
|
|
2175
|
+
// the following namespace already knows...
|
|
2176
|
+
typeString = chainItemTypeName;
|
|
2177
|
+
}
|
|
2178
|
+
break;
|
|
2179
|
+
}
|
|
2180
|
+
else {
|
|
2181
|
+
typeString = typeToFindStringFor === null || typeToFindStringFor === void 0 ? void 0 : typeToFindStringFor.toString();
|
|
2182
|
+
break;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
previousTypeName = typeString !== null && typeString !== void 0 ? typeString : '';
|
|
2186
|
+
itemName = chainItem.name;
|
|
2187
|
+
astNode = chainItem.astNode;
|
|
2188
|
+
containsDynamic = containsDynamic || ((0, reflection_1.isDynamicType)(chainItem.type) && !(0, reflection_1.isAnyReferenceType)(chainItem.type));
|
|
2189
|
+
crossedCallFunc = crossedCallFunc || ((_e = chainItem.data) === null || _e === void 0 ? void 0 : _e.isFromCallFunc);
|
|
2190
|
+
if (!chainItem.isResolved) {
|
|
2191
|
+
errorLocation = chainItem.location;
|
|
2192
|
+
continueResolvingAllItems = false;
|
|
2193
|
+
}
|
|
2194
|
+
}
|
|
2195
|
+
}
|
|
2196
|
+
return {
|
|
2197
|
+
itemName: itemName,
|
|
2198
|
+
itemTypeKind: itemTypeKind,
|
|
2199
|
+
itemParentTypeName: parentTypeName,
|
|
2200
|
+
itemParentTypeKind: parentTypeKind,
|
|
2201
|
+
fullNameOfItem: fullErrorName,
|
|
2202
|
+
fullChainName: fullChainName,
|
|
2203
|
+
location: errorLocation,
|
|
2204
|
+
containsDynamic: containsDynamic,
|
|
2205
|
+
astNode: astNode,
|
|
2206
|
+
crossedCallFunc: crossedCallFunc
|
|
2207
|
+
};
|
|
2208
|
+
}
|
|
2209
|
+
getCircularReferenceDiagnosticDetail(circularReferenceInfo, defaultName = '') {
|
|
2210
|
+
if (!circularReferenceInfo || !circularReferenceInfo.referenceChainNames) {
|
|
2211
|
+
if (defaultName) {
|
|
2212
|
+
return [defaultName];
|
|
2213
|
+
}
|
|
2214
|
+
return [];
|
|
2215
|
+
}
|
|
2216
|
+
if (circularReferenceInfo.referenceChainNames[0] === circularReferenceInfo.referenceChainNames[circularReferenceInfo.referenceChainNames.length - 1]) {
|
|
2217
|
+
// last element is same as first it will read okay
|
|
2218
|
+
return circularReferenceInfo.referenceChainNames;
|
|
2219
|
+
}
|
|
2220
|
+
return [...circularReferenceInfo.referenceChainNames, circularReferenceInfo.referenceChainNames[0]];
|
|
2221
|
+
}
|
|
2222
|
+
isInTypeExpression(expression) {
|
|
2223
|
+
//TODO: this is much faster than node.findAncestor(), but may need to be updated for "complicated" type expressions
|
|
2224
|
+
if ((0, reflection_1.isTypeExpression)(expression) ||
|
|
2225
|
+
(0, reflection_1.isTypeExpression)(expression === null || expression === void 0 ? void 0 : expression.parent) ||
|
|
2226
|
+
(0, reflection_1.isTypedArrayExpression)(expression) ||
|
|
2227
|
+
(0, reflection_1.isTypedArrayExpression)(expression === null || expression === void 0 ? void 0 : expression.parent)) {
|
|
2228
|
+
return true;
|
|
2229
|
+
}
|
|
2230
|
+
if ((0, reflection_1.isBinaryExpression)(expression === null || expression === void 0 ? void 0 : expression.parent)) {
|
|
2231
|
+
let currentExpr = expression.parent;
|
|
2232
|
+
while ((0, reflection_1.isBinaryExpression)(currentExpr) && (currentExpr.tokens.operator.kind === TokenKind_1.TokenKind.Or || currentExpr.tokens.operator.kind === TokenKind_1.TokenKind.And)) {
|
|
2233
|
+
currentExpr = currentExpr.parent;
|
|
2234
|
+
}
|
|
2235
|
+
return (0, reflection_1.isTypeExpression)(currentExpr) || (0, reflection_1.isTypedArrayExpression)(currentExpr);
|
|
2236
|
+
}
|
|
2237
|
+
return false;
|
|
2238
|
+
}
|
|
2239
|
+
/**
|
|
2240
|
+
* Parse the `sourceMappingURL` comment from file contents and resolve it to a RawSourceMap.
|
|
2241
|
+
* Handles inline base64 data URIs, absolute paths, relative paths (resolved against srcPath's
|
|
2242
|
+
* directory), and falls back to a co-located `<srcPath>.map` file.
|
|
2243
|
+
* Supports both BrightScript-style comments (`'//# sourceMappingURL=...`) and XML-style
|
|
2244
|
+
* comments (`<!--//# sourceMappingURL=... -->`).
|
|
2245
|
+
* Returns undefined if no map can be found.
|
|
2246
|
+
*/
|
|
2247
|
+
async resolveInputSourceMap(fileContents, srcPath) {
|
|
2248
|
+
// Match sourceMappingURL - [^\s]+ stops at whitespace (safe, no backtracking risk).
|
|
2249
|
+
// Strip any trailing XML comment close (either --> or --!>) that may have been captured
|
|
2250
|
+
// when the URL is not followed by a space in an XML comment like <!--//# ...=url-->.
|
|
2251
|
+
const match = /['"]?\/\/# sourceMappingURL=([^\s]+)/m.exec(fileContents);
|
|
2252
|
+
if (match) {
|
|
2253
|
+
const url = match[1].replace(/--!?>$/, '').trim();
|
|
2254
|
+
if (url.startsWith('data:')) {
|
|
2255
|
+
// inline base64: data:application/json;base64,<b64>
|
|
2256
|
+
const b64Match = /base64,([A-Za-z0-9+/=]+)$/.exec(url);
|
|
2257
|
+
if (b64Match) {
|
|
2258
|
+
return JSON.parse(Buffer.from(b64Match[1], 'base64').toString('utf8'));
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
else {
|
|
2262
|
+
const mapPath = path.isAbsolute(url) ? url : path.resolve(path.dirname(srcPath), url);
|
|
2263
|
+
if (await fsExtra.pathExists(mapPath)) {
|
|
2264
|
+
return JSON.parse(await fsExtra.readFile(mapPath, 'utf8'));
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
// no usable sourceMappingURL; try co-located <srcPath>.map
|
|
2269
|
+
const colocated = `${srcPath}.map`;
|
|
2270
|
+
if (await fsExtra.pathExists(colocated)) {
|
|
2271
|
+
return JSON.parse(await fsExtra.readFile(colocated, 'utf8'));
|
|
2272
|
+
}
|
|
2273
|
+
return undefined;
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Apply an input sourcemap to a generated SourceMapGenerator, chaining mappings so the
|
|
2277
|
+
* output traces back through the input map to the original source.
|
|
2278
|
+
*/
|
|
2279
|
+
async applySourceMap(generator, inputMap, sourceFile) {
|
|
2280
|
+
await source_map_1.SourceMapConsumer.with(inputMap, null, (consumer) => {
|
|
2281
|
+
generator.applySourceMap(consumer, sourceFile);
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
/**
|
|
2285
|
+
* Chain a prebuild input sourcemap (loaded from a co-located `.map` file or a
|
|
2286
|
+
* `sourceMappingURL` comment in the file contents) onto an existing serialized output
|
|
2287
|
+
* sourcemap. Returns the chained sourcemap as a JSON string. If no input map is found,
|
|
2288
|
+
* the original output map JSON is returned unchanged.
|
|
2289
|
+
*/
|
|
2290
|
+
async chainInputSourceMap(outputMapJson, file) {
|
|
2291
|
+
var _a;
|
|
2292
|
+
const inputMap = await this.resolveInputSourceMap((_a = file.fileContents) !== null && _a !== void 0 ? _a : '', file.srcPath);
|
|
2293
|
+
if (!inputMap) {
|
|
2294
|
+
return outputMapJson;
|
|
2295
|
+
}
|
|
2296
|
+
const { SourceMapConsumer: Consumer, SourceMapGenerator: Generator } = await Promise.resolve().then(() => require('source-map'));
|
|
2297
|
+
const outputMap = JSON.parse(outputMapJson);
|
|
2298
|
+
return Consumer.with(outputMap, null, async (outputConsumer) => {
|
|
2299
|
+
const generator = Generator.fromSourceMap(outputConsumer);
|
|
2300
|
+
await Consumer.with(inputMap, null, (inputConsumer) => {
|
|
2301
|
+
generator.applySourceMap(inputConsumer, file.srcPath);
|
|
2302
|
+
});
|
|
2303
|
+
return generator.toString();
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
isBuiltInType(typeName) {
|
|
2307
|
+
const typeNameLower = typeName.toLowerCase();
|
|
2308
|
+
if (typeNameLower.startsWith('rosgnode')) {
|
|
2309
|
+
// NOTE: this is unsafe and only used to avoid validation errors in backported v1 type syntax
|
|
2310
|
+
return true;
|
|
2311
|
+
}
|
|
2312
|
+
return false;
|
|
2313
|
+
}
|
|
2314
|
+
isGenericNodeType(type) {
|
|
2315
|
+
if ((0, reflection_1.isComponentType)(type)) {
|
|
2316
|
+
const lowerName = type.toString().toLowerCase();
|
|
2317
|
+
if (lowerName === 'rosgnode' || lowerName === 'rosgnodenode') {
|
|
2318
|
+
return true;
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
return false;
|
|
2322
|
+
}
|
|
2323
|
+
hasAnyRequiredSymbolChanged(requiredSymbols, changedSymbols) {
|
|
2324
|
+
if (!requiredSymbols || !changedSymbols) {
|
|
2325
|
+
return false;
|
|
2326
|
+
}
|
|
2327
|
+
const runTimeChanges = changedSymbols.get(1 /* SymbolTypeFlag.runtime */);
|
|
2328
|
+
const typeTimeChanges = changedSymbols.get(2 /* SymbolTypeFlag.typetime */);
|
|
2329
|
+
for (const symbol of requiredSymbols) {
|
|
2330
|
+
if (this.setContainsUnresolvedSymbol(runTimeChanges, symbol) || this.setContainsUnresolvedSymbol(typeTimeChanges, symbol)) {
|
|
2331
|
+
return true;
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
return false;
|
|
2335
|
+
}
|
|
2336
|
+
setContainsUnresolvedSymbol(symbolLowerNameSet, symbol) {
|
|
2337
|
+
if (!symbolLowerNameSet || symbolLowerNameSet.size === 0) {
|
|
2338
|
+
return false;
|
|
2339
|
+
}
|
|
2340
|
+
for (const possibleNameLower of symbol.lookups) {
|
|
2341
|
+
if (symbolLowerNameSet.has(possibleNameLower)) {
|
|
2342
|
+
return true;
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
return false;
|
|
2346
|
+
}
|
|
2347
|
+
getCustomTypesInSymbolTree(setToFill, type, filter) {
|
|
2348
|
+
var _a, _b;
|
|
2349
|
+
const subSymbolTypes = (0, reflection_1.isCompoundType)(type)
|
|
2350
|
+
? type.types
|
|
2351
|
+
: (_b = (_a = type.getMemberTable()) === null || _a === void 0 ? void 0 : _a.getAllSymbols(1 /* SymbolTypeFlag.runtime */).map(sym => sym.type)) !== null && _b !== void 0 ? _b : [];
|
|
2352
|
+
for (const subSymbolType of subSymbolTypes) {
|
|
2353
|
+
if (!(subSymbolType === null || subSymbolType === void 0 ? void 0 : subSymbolType.isBuiltIn) && !setToFill.has(subSymbolType)) {
|
|
2354
|
+
if (filter && !filter(subSymbolType)) {
|
|
2355
|
+
continue;
|
|
2356
|
+
}
|
|
2357
|
+
// if this is a custom type, and we haven't added it to the types to check to see if can add it to the additional types
|
|
2358
|
+
// add the type, and investigate any members
|
|
2359
|
+
setToFill.add(subSymbolType);
|
|
2360
|
+
this.getCustomTypesInSymbolTree(setToFill, subSymbolType, filter);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
}
|
|
2364
|
+
truncate(options) {
|
|
2365
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2366
|
+
let leadingText = options.leadingText;
|
|
2367
|
+
let items = (_a = options === null || options === void 0 ? void 0 : options.items) !== null && _a !== void 0 ? _a : [];
|
|
2368
|
+
let trailingText = (_b = options === null || options === void 0 ? void 0 : options.trailingText) !== null && _b !== void 0 ? _b : '';
|
|
2369
|
+
let maxLength = (_c = options === null || options === void 0 ? void 0 : options.maxLength) !== null && _c !== void 0 ? _c : 160;
|
|
2370
|
+
let itemSeparator = (_d = options === null || options === void 0 ? void 0 : options.itemSeparator) !== null && _d !== void 0 ? _d : ', ';
|
|
2371
|
+
let partBuilder = (_e = options === null || options === void 0 ? void 0 : options.partBuilder) !== null && _e !== void 0 ? _e : ((x) => x.toString());
|
|
2372
|
+
let parts = [];
|
|
2373
|
+
let length = leadingText.length + ((_f = trailingText === null || trailingText === void 0 ? void 0 : trailingText.length) !== null && _f !== void 0 ? _f : 0);
|
|
2374
|
+
//calculate the max number of items we could fit in the given space
|
|
2375
|
+
for (let i = 0; i < items.length; i++) {
|
|
2376
|
+
let part = partBuilder(items[i]);
|
|
2377
|
+
if (i > 0) {
|
|
2378
|
+
part = itemSeparator + part;
|
|
2379
|
+
}
|
|
2380
|
+
parts.push(part);
|
|
2381
|
+
length += part.length;
|
|
2382
|
+
//exit the loop if we've maxed out our length
|
|
2383
|
+
if (length >= maxLength) {
|
|
2384
|
+
break;
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
let message;
|
|
2388
|
+
//we have enough space to include all the parts
|
|
2389
|
+
if (parts.length >= items.length) {
|
|
2390
|
+
message = leadingText + parts.join('') + trailingText;
|
|
2391
|
+
//we require truncation
|
|
2392
|
+
}
|
|
2393
|
+
else {
|
|
2394
|
+
//account for truncation message length including max possible "more" items digits, trailing text length, and the separator between last item and trailing text
|
|
2395
|
+
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);
|
|
2396
|
+
message = leadingText;
|
|
2397
|
+
for (let i = 0; i < parts.length; i++) {
|
|
2398
|
+
//always include at least 2 items. if this part would overflow the max, then skip it and finalize the message
|
|
2399
|
+
if (i > 1 && length + parts[i].length > maxLength) {
|
|
2400
|
+
message += itemSeparator + `...and ${items.length - i} more` + trailingText;
|
|
2401
|
+
return message;
|
|
2402
|
+
}
|
|
2403
|
+
else {
|
|
2404
|
+
message += parts[i];
|
|
2405
|
+
length += parts[i].length;
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
return message;
|
|
2410
|
+
}
|
|
2411
|
+
getAstNodeFriendlyName(node) {
|
|
2412
|
+
return node === null || node === void 0 ? void 0 : node.kind.replace(/Statement|Expression/g, '');
|
|
2413
|
+
}
|
|
2414
|
+
hasLeadingComments(input) {
|
|
2415
|
+
var _a;
|
|
2416
|
+
const leadingTrivia = (0, Token_1.isToken)(input) ? input === null || input === void 0 ? void 0 : input.leadingTrivia : (_a = input === null || input === void 0 ? void 0 : input.leadingTrivia) !== null && _a !== void 0 ? _a : [];
|
|
2417
|
+
return !!(leadingTrivia === null || leadingTrivia === void 0 ? void 0 : leadingTrivia.find(t => (t === null || t === void 0 ? void 0 : t.kind) === TokenKind_1.TokenKind.Comment));
|
|
2418
|
+
}
|
|
2419
|
+
getLeadingComments(input) {
|
|
2420
|
+
var _a;
|
|
2421
|
+
const leadingTrivia = (0, Token_1.isToken)(input) ? input === null || input === void 0 ? void 0 : input.leadingTrivia : (_a = input === null || input === void 0 ? void 0 : input.leadingTrivia) !== null && _a !== void 0 ? _a : [];
|
|
2422
|
+
return leadingTrivia.filter(t => (t === null || t === void 0 ? void 0 : t.kind) === TokenKind_1.TokenKind.Comment);
|
|
2423
|
+
}
|
|
2424
|
+
isLeadingCommentOnSameLine(line, input) {
|
|
2425
|
+
var _a;
|
|
2426
|
+
const leadingCommentRange = (_a = this.getLeadingComments(input)) === null || _a === void 0 ? void 0 : _a[0];
|
|
2427
|
+
if (leadingCommentRange) {
|
|
2428
|
+
return this.linesTouch(line, leadingCommentRange === null || leadingCommentRange === void 0 ? void 0 : leadingCommentRange.location);
|
|
2429
|
+
}
|
|
2430
|
+
return false;
|
|
2431
|
+
}
|
|
2432
|
+
isClassUsedAsFunction(potentialClassType, expression, options) {
|
|
2433
|
+
var _a, _b, _c;
|
|
2434
|
+
// eslint-disable-next-line no-bitwise
|
|
2435
|
+
if (((_a = options === null || options === void 0 ? void 0 : options.flags) !== null && _a !== void 0 ? _a : 0) & 1 /* SymbolTypeFlag.runtime */ &&
|
|
2436
|
+
(0, reflection_1.isClassType)(potentialClassType) &&
|
|
2437
|
+
!options.isExistenceTest &&
|
|
2438
|
+
((_b = potentialClassType.name) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === ((_c = this.getAllDottedGetPartsAsString(expression)) === null || _c === void 0 ? void 0 : _c.toLowerCase()) &&
|
|
2439
|
+
!(expression === null || expression === void 0 ? void 0 : expression.findAncestor(reflection_1.isNewExpression))) {
|
|
2440
|
+
return true;
|
|
2441
|
+
}
|
|
2442
|
+
return false;
|
|
2443
|
+
}
|
|
2444
|
+
getSpecialCaseCallExpressionReturnType(callExpr, options) {
|
|
2445
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
2446
|
+
if ((0, reflection_1.isVariableExpression)(callExpr.callee) && callExpr.callee.tokens.name.text.toLowerCase() === 'createobject') {
|
|
2447
|
+
const componentName = (0, reflection_1.isLiteralString)(callExpr.args[0]) ? (_b = (_a = callExpr.args[0].tokens.value) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.replace(/"/g, '') : '';
|
|
2448
|
+
const nodeType = componentName.toLowerCase() === 'rosgnode' && (0, reflection_1.isLiteralString)(callExpr.args[1]) ? (_d = (_c = callExpr.args[1].tokens.value) === null || _c === void 0 ? void 0 : _c.text) === null || _d === void 0 ? void 0 : _d.replace(/"/g, '') : '';
|
|
2449
|
+
if (componentName === null || componentName === void 0 ? void 0 : componentName.toLowerCase().startsWith('ro')) {
|
|
2450
|
+
let fullName = componentName + nodeType;
|
|
2451
|
+
if (nodeType.includes(':')) {
|
|
2452
|
+
// This node has a colon in its name, most likely from a component Library
|
|
2453
|
+
// This componentType is most likely unknown, so return `roSGNode`
|
|
2454
|
+
fullName = 'roSGNode';
|
|
2455
|
+
}
|
|
2456
|
+
const data = {};
|
|
2457
|
+
const symbolTable = callExpr.getSymbolTable();
|
|
2458
|
+
const foundType = symbolTable.getSymbolType(fullName, {
|
|
2459
|
+
flags: 2 /* SymbolTypeFlag.typetime */,
|
|
2460
|
+
data: data,
|
|
2461
|
+
tableProvider: () => callExpr === null || callExpr === void 0 ? void 0 : callExpr.getSymbolTable(),
|
|
2462
|
+
fullName: fullName
|
|
1209
2463
|
});
|
|
2464
|
+
if (foundType) {
|
|
2465
|
+
return foundType;
|
|
2466
|
+
}
|
|
1210
2467
|
}
|
|
1211
|
-
|
|
2468
|
+
}
|
|
2469
|
+
else if ((0, reflection_1.isDottedGetExpression)(callExpr.callee) &&
|
|
2470
|
+
((_g = (_f = (_e = callExpr.callee.tokens) === null || _e === void 0 ? void 0 : _e.name) === null || _f === void 0 ? void 0 : _f.text) === null || _g === void 0 ? void 0 : _g.toLowerCase()) === 'callfunc' &&
|
|
2471
|
+
(0, reflection_1.isLiteralString)((_h = callExpr.args) === null || _h === void 0 ? void 0 : _h[0])) {
|
|
2472
|
+
return this.getCallFuncType(callExpr, (_k = (_j = callExpr.args) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.tokens.value, options);
|
|
2473
|
+
}
|
|
2474
|
+
else if ((0, reflection_1.isDottedGetExpression)(callExpr.callee) &&
|
|
2475
|
+
((_o = (_m = (_l = callExpr.callee.tokens) === null || _l === void 0 ? void 0 : _l.name) === null || _m === void 0 ? void 0 : _m.text) === null || _o === void 0 ? void 0 : _o.toLowerCase()) === 'createchild' &&
|
|
2476
|
+
(0, reflection_1.isComponentType)((_p = callExpr.callee.obj) === null || _p === void 0 ? void 0 : _p.getType({ flags: 1 /* SymbolTypeFlag.runtime */ })) &&
|
|
2477
|
+
(0, reflection_1.isLiteralString)((_q = callExpr.args) === null || _q === void 0 ? void 0 : _q[0])) {
|
|
2478
|
+
const fullName = `roSGNode${(_u = (_t = (_s = (_r = callExpr.args) === null || _r === void 0 ? void 0 : _r[0].tokens) === null || _s === void 0 ? void 0 : _s.value) === null || _t === void 0 ? void 0 : _t.text) === null || _u === void 0 ? void 0 : _u.replace(/"/g, '')}`;
|
|
2479
|
+
const data = {};
|
|
2480
|
+
const symbolTable = callExpr.getSymbolTable();
|
|
2481
|
+
return symbolTable.getSymbolType(fullName, {
|
|
2482
|
+
flags: 2 /* SymbolTypeFlag.typetime */,
|
|
2483
|
+
data: data,
|
|
2484
|
+
tableProvider: () => callExpr === null || callExpr === void 0 ? void 0 : callExpr.getSymbolTable(),
|
|
2485
|
+
fullName: fullName
|
|
2486
|
+
});
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
getCallFuncType(callExpr, methodNameToken, options) {
|
|
2490
|
+
var _a, _b, _c, _d;
|
|
2491
|
+
let result;
|
|
2492
|
+
let methodName = (_a = methodNameToken === null || methodNameToken === void 0 ? void 0 : methodNameToken.text) === null || _a === void 0 ? void 0 : _a.replace(/"/g, ''); // remove quotes if it was the first arg of .callFunc()
|
|
2493
|
+
//bail early when there's no method name (e.g. an unfinished `widget@.` callfunc).
|
|
2494
|
+
//downstream getCallFuncType / ReferenceType paths assume a non-empty member name and
|
|
2495
|
+
//will eventually try `name.toLowerCase()` on undefined and crash.
|
|
2496
|
+
if (!methodName) {
|
|
2497
|
+
return undefined;
|
|
2498
|
+
}
|
|
2499
|
+
// a little hacky here with checking options.ignoreCall because callFuncExpression has the method name
|
|
2500
|
+
// It's nicer for CallExpression, because it's a call on any expression.
|
|
2501
|
+
let calleeType;
|
|
2502
|
+
if ((0, reflection_1.isCallfuncExpression)(callExpr)) {
|
|
2503
|
+
calleeType = callExpr.callee.getType(Object.assign(Object.assign({}, options), { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: false }));
|
|
2504
|
+
}
|
|
2505
|
+
else if ((0, reflection_1.isCallExpression)(callExpr) && (0, reflection_1.isDottedGetExpression)(callExpr.callee)) {
|
|
2506
|
+
calleeType = callExpr.callee.obj.getType(Object.assign(Object.assign({}, options), { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: false }));
|
|
2507
|
+
}
|
|
2508
|
+
const funcType = (_b = calleeType === null || calleeType === void 0 ? void 0 : calleeType.getCallFuncType) === null || _b === void 0 ? void 0 : _b.call(calleeType, methodName, options);
|
|
2509
|
+
if (funcType) {
|
|
2510
|
+
(_c = options.typeChain) === null || _c === void 0 ? void 0 : _c.push(new interfaces_1.TypeChainEntry({
|
|
2511
|
+
name: methodName,
|
|
2512
|
+
type: funcType,
|
|
2513
|
+
data: options.data,
|
|
2514
|
+
location: methodNameToken.location,
|
|
2515
|
+
separatorToken: (0, creators_1.createToken)(TokenKind_1.TokenKind.Callfunc),
|
|
2516
|
+
astNode: callExpr
|
|
2517
|
+
}));
|
|
2518
|
+
if (options.ignoreCall) {
|
|
2519
|
+
result = funcType;
|
|
2520
|
+
}
|
|
2521
|
+
else if ((0, reflection_1.isCallableType)(funcType) && (!(0, reflection_1.isReferenceType)(funcType.returnType) || funcType.returnType.isResolvable())) {
|
|
2522
|
+
result = funcType.returnType;
|
|
2523
|
+
}
|
|
2524
|
+
else if (!(0, reflection_1.isReferenceType)(funcType) && ((_d = funcType === null || funcType === void 0 ? void 0 : funcType.returnType) === null || _d === void 0 ? void 0 : _d.isResolvable())) {
|
|
2525
|
+
result = funcType.returnType;
|
|
2526
|
+
}
|
|
2527
|
+
else if (this.isUnionOfFunctions(funcType)) {
|
|
2528
|
+
result = this.getReturnTypeOfUnionOfFunctions(funcType);
|
|
2529
|
+
}
|
|
2530
|
+
else {
|
|
2531
|
+
result = new ReferenceType_1.TypePropertyReferenceType(funcType, 'returnType');
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
if ((0, reflection_1.isVoidType)(result)) {
|
|
2535
|
+
// CallFunc will always return invalid, even if function called is `as void`
|
|
2536
|
+
result = DynamicType_1.DynamicType.instance;
|
|
2537
|
+
}
|
|
2538
|
+
if (options.data && !options.ignoreCall) {
|
|
2539
|
+
options.data.isFromCallFunc = true;
|
|
1212
2540
|
}
|
|
1213
2541
|
return result;
|
|
1214
2542
|
}
|
|
2543
|
+
isUnionOfFunctions(type, allowReferenceTypes = false) {
|
|
2544
|
+
if ((0, reflection_1.isUnionType)(type)) {
|
|
2545
|
+
const callablesInUnion = type.types.filter(t => (0, reflection_1.isCallableType)(t) || (allowReferenceTypes && (0, reflection_1.isReferenceType)(t)));
|
|
2546
|
+
return callablesInUnion.length === type.types.length && callablesInUnion.length > 0;
|
|
2547
|
+
}
|
|
2548
|
+
return false;
|
|
2549
|
+
}
|
|
2550
|
+
isIntersectionOfFunctions(type, allowReferenceTypes = false) {
|
|
2551
|
+
if ((0, reflection_1.isIntersectionType)(type)) {
|
|
2552
|
+
const callablesInUnion = type.types.filter(t => (0, reflection_1.isCallableType)(t) || (allowReferenceTypes && (0, reflection_1.isReferenceType)(t)));
|
|
2553
|
+
return callablesInUnion.length === type.types.length && callablesInUnion.length > 0;
|
|
2554
|
+
}
|
|
2555
|
+
return false;
|
|
2556
|
+
}
|
|
2557
|
+
getFunctionTypeFromUnion(type) {
|
|
2558
|
+
if (this.isUnionOfFunctions(type)) {
|
|
2559
|
+
const typedFuncsInUnion = type.types.filter(reflection_1.isTypedFunctionType);
|
|
2560
|
+
if (typedFuncsInUnion.length < type.types.length) {
|
|
2561
|
+
// has non-typedFuncs in union
|
|
2562
|
+
return FunctionType_1.FunctionType.instance;
|
|
2563
|
+
}
|
|
2564
|
+
const exampleFunc = typedFuncsInUnion[0];
|
|
2565
|
+
const cumulativeFunction = new types_1.TypedFunctionType((0, helpers_1.getUniqueType)(typedFuncsInUnion.map(f => f.returnType), (types) => new UnionType_1.UnionType(types)))
|
|
2566
|
+
.setName(exampleFunc.name)
|
|
2567
|
+
.setSub(exampleFunc.isSub);
|
|
2568
|
+
for (const param of exampleFunc.params) {
|
|
2569
|
+
cumulativeFunction.addParameter(param.name, param.type, param.isOptional);
|
|
2570
|
+
}
|
|
2571
|
+
return cumulativeFunction;
|
|
2572
|
+
}
|
|
2573
|
+
return undefined;
|
|
2574
|
+
}
|
|
2575
|
+
getFunctionTypeFromIntersection(type) {
|
|
2576
|
+
if (this.isIntersectionOfFunctions(type)) {
|
|
2577
|
+
const typedFuncsInUnion = type.types.filter(reflection_1.isTypedFunctionType);
|
|
2578
|
+
if (typedFuncsInUnion.length < type.types.length) {
|
|
2579
|
+
// has non-typedFuncs in union
|
|
2580
|
+
return FunctionType_1.FunctionType.instance;
|
|
2581
|
+
}
|
|
2582
|
+
const exampleFunc = typedFuncsInUnion[0];
|
|
2583
|
+
const cumulativeFunction = new types_1.TypedFunctionType((0, helpers_1.getUniqueType)(typedFuncsInUnion.map(f => f.returnType), (types) => new IntersectionType_1.IntersectionType(types)))
|
|
2584
|
+
.setName(exampleFunc.name)
|
|
2585
|
+
.setSub(exampleFunc.isSub);
|
|
2586
|
+
for (const param of exampleFunc.params) {
|
|
2587
|
+
cumulativeFunction.addParameter(param.name, param.type, param.isOptional);
|
|
2588
|
+
}
|
|
2589
|
+
return cumulativeFunction;
|
|
2590
|
+
}
|
|
2591
|
+
return undefined;
|
|
2592
|
+
}
|
|
2593
|
+
getReturnTypeOfUnionOfFunctions(type) {
|
|
2594
|
+
if (this.isUnionOfFunctions(type, true)) {
|
|
2595
|
+
const typedFuncsInUnion = type.types.filter(t => (0, reflection_1.isTypedFunctionTypeLike)(t) || (0, reflection_1.isReferenceType)(t));
|
|
2596
|
+
if (typedFuncsInUnion.length < type.types.length) {
|
|
2597
|
+
// is non-typedFuncs in union
|
|
2598
|
+
return DynamicType_1.DynamicType.instance;
|
|
2599
|
+
}
|
|
2600
|
+
const funcReturns = typedFuncsInUnion.map(f => f.returnType);
|
|
2601
|
+
return (0, helpers_1.getUniqueType)(funcReturns, (types) => new UnionType_1.UnionType(types));
|
|
2602
|
+
}
|
|
2603
|
+
return InvalidType_1.InvalidType.instance;
|
|
2604
|
+
}
|
|
2605
|
+
getReturnTypeOfIntersectionOfFunctions(type) {
|
|
2606
|
+
if (this.isIntersectionOfFunctions(type, true)) {
|
|
2607
|
+
const typedFuncsInUnion = type.types.filter(t => (0, reflection_1.isTypedFunctionType)(t) || (0, reflection_1.isReferenceType)(t));
|
|
2608
|
+
if (typedFuncsInUnion.length < type.types.length) {
|
|
2609
|
+
// is non-typedFuncs in union
|
|
2610
|
+
return DynamicType_1.DynamicType.instance;
|
|
2611
|
+
}
|
|
2612
|
+
const funcReturns = typedFuncsInUnion.map(f => f.returnType);
|
|
2613
|
+
return new IntersectionType_1.IntersectionType(funcReturns); //getUniqueType(funcReturns, (types) => new UnionType(types));
|
|
2614
|
+
}
|
|
2615
|
+
return InvalidType_1.InvalidType.instance;
|
|
2616
|
+
}
|
|
2617
|
+
symbolComesFromSameNode(symbolName, definingNode, symbolTable) {
|
|
2618
|
+
let nsData = {};
|
|
2619
|
+
let foundType = symbolTable === null || symbolTable === void 0 ? void 0 : symbolTable.getSymbolType(symbolName, { flags: 1 /* SymbolTypeFlag.runtime */, data: nsData });
|
|
2620
|
+
if (foundType && definingNode === (nsData === null || nsData === void 0 ? void 0 : nsData.definingNode)) {
|
|
2621
|
+
return true;
|
|
2622
|
+
}
|
|
2623
|
+
return false;
|
|
2624
|
+
}
|
|
2625
|
+
isCalleeMemberOfNamespace(symbolName, nodeWhereUsed, namespace) {
|
|
2626
|
+
namespace = namespace !== null && namespace !== void 0 ? namespace : nodeWhereUsed.findAncestor(reflection_1.isNamespaceStatement);
|
|
2627
|
+
if (!this.isVariableMemberOfNamespace(symbolName, nodeWhereUsed, namespace)) {
|
|
2628
|
+
return false;
|
|
2629
|
+
}
|
|
2630
|
+
const exprType = nodeWhereUsed.getType({ flags: 1 /* SymbolTypeFlag.runtime */ });
|
|
2631
|
+
if ((0, reflection_1.isCallableType)(exprType) || (0, reflection_1.isClassType)(exprType)) {
|
|
2632
|
+
return true;
|
|
2633
|
+
}
|
|
2634
|
+
return false;
|
|
2635
|
+
}
|
|
2636
|
+
isVariableMemberOfNamespace(symbolName, nodeWhereUsed, namespace) {
|
|
2637
|
+
namespace = namespace !== null && namespace !== void 0 ? namespace : nodeWhereUsed.findAncestor(reflection_1.isNamespaceStatement);
|
|
2638
|
+
if (!(0, reflection_1.isNamespaceStatement)(namespace)) {
|
|
2639
|
+
return false;
|
|
2640
|
+
}
|
|
2641
|
+
const namespaceParts = namespace.getNameParts();
|
|
2642
|
+
let namespaceType;
|
|
2643
|
+
let symbolTable = namespace.getSymbolTable();
|
|
2644
|
+
for (const part of namespaceParts) {
|
|
2645
|
+
namespaceType = symbolTable.getSymbolType(part.text, { flags: 1 /* SymbolTypeFlag.runtime */ });
|
|
2646
|
+
if (namespaceType) {
|
|
2647
|
+
symbolTable = namespaceType.getMemberTable();
|
|
2648
|
+
}
|
|
2649
|
+
else {
|
|
2650
|
+
return false;
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
let varData = {};
|
|
2654
|
+
nodeWhereUsed.getType({ flags: 1 /* SymbolTypeFlag.runtime */, data: varData });
|
|
2655
|
+
const isFromSameNodeInMemberTable = this.symbolComesFromSameNode(symbolName, varData === null || varData === void 0 ? void 0 : varData.definingNode, namespaceType === null || namespaceType === void 0 ? void 0 : namespaceType.getMemberTable());
|
|
2656
|
+
return isFromSameNodeInMemberTable;
|
|
2657
|
+
}
|
|
2658
|
+
isVariableShadowingSomething(symbolName, nodeWhereUsed) {
|
|
2659
|
+
let varData = {};
|
|
2660
|
+
let exprType = nodeWhereUsed.getType({ flags: 1 /* SymbolTypeFlag.runtime */, data: varData });
|
|
2661
|
+
if ((0, reflection_1.isReferenceType)(exprType)) {
|
|
2662
|
+
exprType = exprType.getTarget();
|
|
2663
|
+
}
|
|
2664
|
+
const namespace = nodeWhereUsed === null || nodeWhereUsed === void 0 ? void 0 : nodeWhereUsed.findAncestor(reflection_1.isNamespaceStatement);
|
|
2665
|
+
if ((0, reflection_1.isNamespaceStatement)(namespace)) {
|
|
2666
|
+
let namespaceHasSymbol = namespace.getSymbolTable().hasSymbol(symbolName, 1 /* SymbolTypeFlag.runtime */);
|
|
2667
|
+
// check if the namespace has a symbol with the same name, but different definiton
|
|
2668
|
+
if (namespaceHasSymbol && !this.symbolComesFromSameNode(symbolName, varData.definingNode, namespace.getSymbolTable())) {
|
|
2669
|
+
return true;
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
const bodyTable = nodeWhereUsed.getRoot().getSymbolTable();
|
|
2673
|
+
const hasSymbolAtFileLevel = bodyTable.hasSymbol(symbolName, 1 /* SymbolTypeFlag.runtime */);
|
|
2674
|
+
if (hasSymbolAtFileLevel && !this.symbolComesFromSameNode(symbolName, varData.definingNode, bodyTable)) {
|
|
2675
|
+
return true;
|
|
2676
|
+
}
|
|
2677
|
+
return false;
|
|
2678
|
+
}
|
|
2679
|
+
chooseTypeFromCodeOrDocComment(codeType, docType, options) {
|
|
2680
|
+
let returnType;
|
|
2681
|
+
if (options.preferDocType && docType) {
|
|
2682
|
+
returnType = docType;
|
|
2683
|
+
if (options.data) {
|
|
2684
|
+
options.data.isFromDocComment = true;
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
else {
|
|
2688
|
+
returnType = codeType;
|
|
2689
|
+
if (!returnType && docType) {
|
|
2690
|
+
returnType = docType;
|
|
2691
|
+
if (options.data) {
|
|
2692
|
+
options.data.isFromDocComment = true;
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
return returnType;
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* Gets the type for a default value (eg. as a function param, class member or typed array)
|
|
2700
|
+
*/
|
|
2701
|
+
getDefaultTypeFromValueType(valueType) {
|
|
2702
|
+
var _a;
|
|
2703
|
+
if (!valueType) {
|
|
2704
|
+
return undefined;
|
|
2705
|
+
}
|
|
2706
|
+
let resultType = DynamicType_1.DynamicType.instance;
|
|
2707
|
+
if (Array.isArray(valueType)) {
|
|
2708
|
+
// passed an array opf types, potential from ArrayType.innerTypes
|
|
2709
|
+
if (valueType.length > 0) {
|
|
2710
|
+
//at least one, use it
|
|
2711
|
+
resultType = valueType[0];
|
|
2712
|
+
if ((valueType === null || valueType === void 0 ? void 0 : valueType.length) > 1) {
|
|
2713
|
+
// more than 1, find union
|
|
2714
|
+
resultType = (0, helpers_1.getUniqueType)(valueType, UnionType_1.unionTypeFactory);
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
else {
|
|
2719
|
+
resultType = valueType;
|
|
2720
|
+
}
|
|
2721
|
+
if (!resultType.isResolvable()) {
|
|
2722
|
+
if ((0, reflection_1.isUnionType)(resultType)) {
|
|
2723
|
+
resultType = DynamicType_1.DynamicType.instance;
|
|
2724
|
+
}
|
|
2725
|
+
else if ((0, reflection_1.isParamTypeFromValueReferenceType)(resultType)) {
|
|
2726
|
+
//already wrapped — wrapping again would build a recursive proxy chain whose
|
|
2727
|
+
//get handlers loop forever via Reflect.get
|
|
2728
|
+
}
|
|
2729
|
+
else {
|
|
2730
|
+
resultType = new ReferenceType_1.ParamTypeFromValueReferenceType(resultType);
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
else if ((0, reflection_1.isEnumMemberType)(resultType)) {
|
|
2734
|
+
// the type was an enum member... Try to get the parent enum type
|
|
2735
|
+
resultType = (_a = resultType.parentEnumType) !== null && _a !== void 0 ? _a : resultType;
|
|
2736
|
+
}
|
|
2737
|
+
else if ((0, reflection_1.isUnionType)(resultType)) {
|
|
2738
|
+
// it was a union -- I wonder if they're resolvable now?
|
|
2739
|
+
const moddedTypes = resultType.types.map(t => {
|
|
2740
|
+
var _a;
|
|
2741
|
+
if ((0, reflection_1.isEnumMemberType)(t)) {
|
|
2742
|
+
// the type was an enum member... Try to get the parent enum type
|
|
2743
|
+
return (_a = t.parentEnumType) !== null && _a !== void 0 ? _a : resultType;
|
|
2744
|
+
}
|
|
2745
|
+
return t;
|
|
2746
|
+
});
|
|
2747
|
+
resultType = (0, helpers_1.getUniqueType)(moddedTypes, UnionType_1.unionTypeFactory);
|
|
2748
|
+
}
|
|
2749
|
+
return resultType;
|
|
2750
|
+
}
|
|
2751
|
+
/**
|
|
2752
|
+
* Get the default type for an iterator of the given type
|
|
2753
|
+
* Used for `for each` loops
|
|
2754
|
+
*/
|
|
2755
|
+
getIteratorDefaultType(iteratorType) {
|
|
2756
|
+
if ((0, reflection_1.isArrayType)(iteratorType)) {
|
|
2757
|
+
return iteratorType.defaultType;
|
|
2758
|
+
}
|
|
2759
|
+
else if ((0, reflection_1.isAssociativeArrayTypeLike)(iteratorType)) {
|
|
2760
|
+
return StringType_1.StringType.instance;
|
|
2761
|
+
}
|
|
2762
|
+
else if ((0, reflection_1.isBuiltInType)(iteratorType, 'roByteArray')) {
|
|
2763
|
+
return IntegerType_1.IntegerType.instance;
|
|
2764
|
+
}
|
|
2765
|
+
else if ((0, reflection_1.isUnionType)(iteratorType)) {
|
|
2766
|
+
const iteratorDefaultTypes = iteratorType.types.map(t => this.getIteratorDefaultType(t));
|
|
2767
|
+
return (0, helpers_1.getUniqueType)(iteratorDefaultTypes, UnionType_1.unionTypeFactory);
|
|
2768
|
+
}
|
|
2769
|
+
return DynamicType_1.DynamicType.instance;
|
|
2770
|
+
}
|
|
2771
|
+
/**
|
|
2772
|
+
* Get a short name that can be used to reference the project in logs. (typically something like `prj1`, `prj8`, etc...)
|
|
2773
|
+
*/
|
|
2774
|
+
getProjectLogName(config) {
|
|
2775
|
+
//if we have a project number, use it
|
|
2776
|
+
if ((config === null || config === void 0 ? void 0 : config.projectNumber) !== undefined) {
|
|
2777
|
+
return `prj${config.projectNumber}`;
|
|
2778
|
+
}
|
|
2779
|
+
//just return empty string so log functions don't crash with undefined project numbers
|
|
2780
|
+
return '';
|
|
2781
|
+
}
|
|
1215
2782
|
}
|
|
1216
2783
|
exports.Util = Util;
|
|
1217
2784
|
/**
|
|
@@ -1220,7 +2787,7 @@ exports.Util = Util;
|
|
|
1220
2787
|
*/
|
|
1221
2788
|
function standardizePath(stringParts, ...expressions) {
|
|
1222
2789
|
let result = [];
|
|
1223
|
-
for (let i = 0; i < stringParts.length; i++) {
|
|
2790
|
+
for (let i = 0; i < (stringParts === null || stringParts === void 0 ? void 0 : stringParts.length); i++) {
|
|
1224
2791
|
result.push(stringParts[i], expressions[i]);
|
|
1225
2792
|
}
|
|
1226
2793
|
return exports.util.standardizePath(result.join(''));
|