brighterscript 1.0.0-alpha.5 → 1.0.0-alpha.50
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 +76 -138
- package/bsconfig.schema.json +121 -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 +72 -39
- 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 +12 -4
- package/dist/CodeActionUtil.js +22 -5
- package/dist/CodeActionUtil.js.map +1 -1
- package/dist/CommentFlagProcessor.d.ts +7 -6
- package/dist/CommentFlagProcessor.js +11 -8
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/CrossScopeValidator.d.ts +68 -0
- package/dist/CrossScopeValidator.js +642 -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 +82 -0
- package/dist/DiagnosticManager.js +406 -0
- package/dist/DiagnosticManager.js.map +1 -0
- package/dist/DiagnosticMessages.d.ts +558 -196
- package/dist/DiagnosticMessages.js +870 -340
- 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 +100 -105
- package/dist/LanguageServer.js +444 -745
- 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 +241 -98
- package/dist/Program.js +1432 -717
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +47 -23
- package/dist/ProgramBuilder.js +224 -178
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +149 -109
- package/dist/Scope.js +557 -550
- package/dist/Scope.js.map +1 -1
- 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 +136 -24
- package/dist/SymbolTable.js +565 -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 +334 -0
- package/dist/astUtils/CachedLookups.js.map +1 -0
- package/dist/astUtils/CachedLookups.spec.js +39 -0
- package/dist/astUtils/CachedLookups.spec.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/Editor.spec.js +258 -0
- package/dist/astUtils/Editor.spec.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/creators.spec.js +5 -5
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +196 -85
- package/dist/astUtils/reflection.js +497 -144
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +267 -167
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/stackedVisitor.js.map +1 -1
- package/dist/astUtils/stackedVisitor.spec.js +14 -14
- package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +116 -53
- package/dist/astUtils/visitors.js +95 -15
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +629 -51
- package/dist/astUtils/visitors.spec.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 +24 -4
- package/dist/bscPlugin/BscPlugin.js +88 -4
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
- package/dist/bscPlugin/CallExpressionInfo.js +143 -0
- package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
- package/dist/bscPlugin/FileWriter.d.ts +6 -0
- package/dist/bscPlugin/FileWriter.js +24 -0
- package/dist/bscPlugin/FileWriter.js.map +1 -0
- package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
- package/dist/bscPlugin/SignatureHelpUtil.js +137 -0
- package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.d.ts +6 -5
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +173 -27
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +138 -21
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- 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/completions/CompletionsProcessor.spec.js +2512 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/definition/DefinitionProvider.d.ts +13 -0
- package/dist/bscPlugin/definition/DefinitionProvider.js +212 -0
- package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
- package/dist/bscPlugin/definition/DefinitionProvider.spec.js +87 -0
- package/dist/bscPlugin/definition/DefinitionProvider.spec.js.map +1 -0
- package/dist/bscPlugin/fileProviders/FileProvider.d.ts +9 -0
- package/dist/bscPlugin/fileProviders/FileProvider.js +51 -0
- package/dist/bscPlugin/fileProviders/FileProvider.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.d.ts +18 -0
- package/dist/bscPlugin/hover/HoverProcessor.js +230 -0
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +991 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.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/references/ReferencesProvider.spec.d.ts +1 -0
- package/dist/bscPlugin/references/ReferencesProvider.spec.js +51 -0
- package/dist/bscPlugin/references/ReferencesProvider.spec.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/semanticTokens/BrsFileSemanticTokensProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +564 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js +33 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.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 +75 -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/DocumentSymbolProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.js +291 -0
- package/dist/bscPlugin/symbols/DocumentSymbolProcessor.spec.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/WorkspaceSymbolProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.js +245 -0
- package/dist/bscPlugin/symbols/WorkspaceSymbolProcessor.spec.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 +27 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +418 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +75 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/validation/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 +37 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js +638 -0
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +1517 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.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 +141 -0
- package/dist/bscPlugin/validation/ScopeValidator.js +1323 -0
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +6135 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
- package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js +36 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
- package/dist/cli.js +126 -27
- 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/common/Sequencer.spec.d.ts +1 -0
- package/dist/common/Sequencer.spec.js +75 -0
- package/dist/common/Sequencer.spec.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 +10 -3
- package/dist/diagnosticUtils.js +64 -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.Class.spec.js +1213 -259
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +145 -87
- package/dist/files/BrsFile.js +836 -934
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +4226 -902
- package/dist/files/BrsFile.spec.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/LazyFileData.spec.d.ts +1 -0
- package/dist/files/LazyFileData.spec.js +27 -0
- package/dist/files/LazyFileData.spec.js.map +1 -0
- package/dist/files/XmlFile.d.ts +80 -41
- package/dist/files/XmlFile.js +161 -137
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +444 -336
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +62 -52
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.d.ts +1 -0
- package/dist/files/tests/optionalChaning.spec.js +152 -0
- package/dist/files/tests/optionalChaning.spec.js.map +1 -0
- 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 +942 -125
- package/dist/interfaces.js +21 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Character.spec.js +5 -5
- package/dist/lexer/Character.spec.js.map +1 -1
- package/dist/lexer/Lexer.d.ts +51 -12
- package/dist/lexer/Lexer.js +215 -65
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +812 -568
- package/dist/lexer/Lexer.spec.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 +40 -2
- package/dist/lexer/TokenKind.js +147 -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/ActionQueue.spec.d.ts +1 -0
- package/dist/lsp/ActionQueue.spec.js +80 -0
- package/dist/lsp/ActionQueue.spec.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/DocumentManager.spec.d.ts +1 -0
- package/dist/lsp/DocumentManager.spec.js +103 -0
- package/dist/lsp/DocumentManager.spec.js.map +1 -0
- package/dist/lsp/LspProject.d.ts +239 -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/PathFilterer.spec.d.ts +1 -0
- package/dist/lsp/PathFilterer.spec.js +182 -0
- package/dist/lsp/PathFilterer.spec.js.map +1 -0
- package/dist/lsp/Project.d.ts +168 -0
- package/dist/lsp/Project.js +437 -0
- package/dist/lsp/Project.js.map +1 -0
- package/dist/lsp/Project.spec.d.ts +1 -0
- package/dist/lsp/Project.spec.js +267 -0
- package/dist/lsp/Project.spec.js.map +1 -0
- package/dist/lsp/ProjectManager.d.ts +242 -0
- package/dist/lsp/ProjectManager.js +824 -0
- package/dist/lsp/ProjectManager.js.map +1 -0
- package/dist/lsp/ProjectManager.spec.d.ts +1 -0
- package/dist/lsp/ProjectManager.spec.js +913 -0
- package/dist/lsp/ProjectManager.spec.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/MessageHandler.spec.d.ts +1 -0
- package/dist/lsp/worker/MessageHandler.spec.js +64 -0
- package/dist/lsp/worker/MessageHandler.spec.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/WorkerPool.spec.d.ts +1 -0
- package/dist/lsp/worker/WorkerPool.spec.js +59 -0
- package/dist/lsp/worker/WorkerPool.spec.js.map +1 -0
- package/dist/lsp/worker/WorkerThreadProject.d.ts +143 -0
- package/dist/lsp/worker/WorkerThreadProject.js +189 -0
- package/dist/lsp/worker/WorkerThreadProject.js.map +1 -0
- package/dist/lsp/worker/WorkerThreadProject.spec.d.ts +2 -0
- package/dist/lsp/worker/WorkerThreadProject.spec.js +71 -0
- package/dist/lsp/worker/WorkerThreadProject.spec.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.d.ts +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 +203 -0
- package/dist/parser/AstNode.js +303 -0
- package/dist/parser/AstNode.js.map +1 -0
- package/dist/parser/AstNode.spec.d.ts +1 -0
- package/dist/parser/AstNode.spec.js +1455 -0
- package/dist/parser/AstNode.spec.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/BrightScriptDocParser.spec.d.ts +1 -0
- package/dist/parser/BrightScriptDocParser.spec.js +310 -0
- package/dist/parser/BrightScriptDocParser.spec.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 +553 -221
- package/dist/parser/Expression.js +1414 -505
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Expression.spec.d.ts +1 -0
- package/dist/parser/Expression.spec.js +40 -0
- package/dist/parser/Expression.spec.js.map +1 -0
- package/dist/parser/Parser.Class.spec.js +255 -125
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +117 -124
- package/dist/parser/Parser.js +1669 -982
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.d.ts +3 -1
- package/dist/parser/Parser.spec.js +2111 -525
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +29 -13
- package/dist/parser/SGParser.js +85 -56
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +30 -45
- package/dist/parser/SGParser.spec.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 +849 -267
- package/dist/parser/Statement.js +2412 -625
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +133 -36
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/TranspileState.d.ts +26 -12
- package/dist/parser/TranspileState.js +115 -24
- package/dist/parser/TranspileState.js.map +1 -1
- package/dist/parser/tests/Parser.spec.d.ts +3 -9
- package/dist/parser/tests/Parser.spec.js +7 -13
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +83 -75
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +85 -51
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +382 -239
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +52 -45
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +51 -43
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +192 -142
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +236 -160
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +41 -34
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +173 -55
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +20 -20
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +291 -282
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +193 -110
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +42 -42
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +260 -115
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +58 -52
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +76 -60
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +171 -0
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -0
- package/dist/parser/tests/expression/Relational.spec.js +50 -50
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +31 -31
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +281 -94
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +747 -192
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/TypeExpression.spec.js +126 -0
- package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +44 -44
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/ConstStatement.spec.d.ts +1 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js +500 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Continue.spec.js +119 -0
- package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
- package/dist/parser/tests/statement/Declaration.spec.js +61 -55
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Dim.spec.js +29 -22
- package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Enum.spec.js +744 -0
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -0
- package/dist/parser/tests/statement/For.spec.d.ts +1 -0
- package/dist/parser/tests/statement/For.spec.js +45 -0
- package/dist/parser/tests/statement/For.spec.js.map +1 -0
- package/dist/parser/tests/statement/ForEach.spec.d.ts +1 -0
- package/dist/parser/tests/statement/ForEach.spec.js +36 -0
- package/dist/parser/tests/statement/ForEach.spec.js.map +1 -0
- package/dist/parser/tests/statement/Function.spec.js +226 -215
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +16 -15
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +64 -61
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.d.ts +1 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +110 -0
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/LibraryStatement.spec.js +22 -22
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +127 -168
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +133 -114
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +57 -54
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +131 -117
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +14 -13
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/parser/tests/statement/Throw.spec.js +11 -8
- package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +26 -15
- package/dist/parser/tests/statement/TryCatch.spec.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/preprocessor/Manifest.spec.d.ts +1 -0
- package/dist/preprocessor/Manifest.spec.js +78 -103
- package/dist/preprocessor/Manifest.spec.js.map +1 -1
- package/dist/roku-types/data.json +20347 -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 +89 -24
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +39 -11
- package/dist/types/ArrayType.spec.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/BooleanType.spec.js +10 -4
- package/dist/types/BooleanType.spec.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/BuiltInInterfaceAdder.spec.d.ts +1 -0
- package/dist/types/BuiltInInterfaceAdder.spec.js +115 -0
- package/dist/types/BuiltInInterfaceAdder.spec.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 +60 -0
- package/dist/types/ClassType.js.map +1 -0
- package/dist/types/ClassType.spec.d.ts +1 -0
- package/dist/types/ClassType.spec.js +76 -0
- package/dist/types/ClassType.spec.js.map +1 -0
- package/dist/types/ComponentType.d.ts +22 -0
- package/dist/types/ComponentType.js +107 -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/DoubleType.spec.js +12 -4
- package/dist/types/DoubleType.spec.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/DynamicType.spec.js +16 -5
- package/dist/types/DynamicType.spec.js.map +1 -1
- package/dist/types/EnumType.d.ts +42 -0
- package/dist/types/EnumType.js +98 -0
- package/dist/types/EnumType.js.map +1 -0
- package/dist/types/EnumType.spec.d.ts +1 -0
- package/dist/types/EnumType.spec.js +33 -0
- package/dist/types/EnumType.spec.js.map +1 -0
- package/dist/types/FloatType.d.ts +10 -5
- package/dist/types/FloatType.js +21 -17
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +4 -4
- package/dist/types/FloatType.spec.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/IntegerType.spec.js +8 -4
- package/dist/types/IntegerType.spec.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/InterfaceType.spec.d.ts +1 -0
- package/dist/types/InterfaceType.spec.js +227 -0
- package/dist/types/InterfaceType.spec.js.map +1 -0
- package/dist/types/IntersectionType.d.ts +29 -0
- package/dist/types/IntersectionType.js +253 -0
- package/dist/types/IntersectionType.js.map +1 -0
- package/dist/types/IntersectionType.spec.d.ts +1 -0
- package/dist/types/IntersectionType.spec.js +150 -0
- package/dist/types/IntersectionType.spec.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/InvalidType.spec.js +8 -4
- package/dist/types/InvalidType.spec.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/LongIntegerType.spec.js +10 -4
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/NamespaceType.d.ts +12 -0
- package/dist/types/NamespaceType.js +28 -0
- package/dist/types/NamespaceType.js.map +1 -0
- package/dist/types/ObjectType.d.ts +12 -5
- package/dist/types/ObjectType.js +25 -8
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ObjectType.spec.js +3 -3
- package/dist/types/ObjectType.spec.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +123 -0
- package/dist/types/ReferenceType.js +720 -0
- package/dist/types/ReferenceType.js.map +1 -0
- package/dist/types/ReferenceType.spec.d.ts +1 -0
- package/dist/types/ReferenceType.spec.js +151 -0
- package/dist/types/ReferenceType.spec.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/StringType.spec.js +3 -3
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/TypeStatementType.d.ts +18 -0
- package/dist/types/TypeStatementType.js +45 -0
- package/dist/types/TypeStatementType.js.map +1 -0
- package/dist/types/TypedFunctionType.d.ts +34 -0
- package/dist/types/TypedFunctionType.js +147 -0
- package/dist/types/TypedFunctionType.js.map +1 -0
- package/dist/types/TypedFunctionType.spec.d.ts +1 -0
- package/dist/types/TypedFunctionType.spec.js +122 -0
- package/dist/types/TypedFunctionType.spec.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 +193 -0
- package/dist/types/UnionType.js.map +1 -0
- package/dist/types/UnionType.spec.d.ts +1 -0
- package/dist/types/UnionType.spec.js +205 -0
- package/dist/types/UnionType.spec.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/VoidType.spec.js +3 -3
- package/dist/types/VoidType.spec.js.map +1 -1
- package/dist/types/helper.spec.d.ts +1 -0
- package/dist/types/helper.spec.js +174 -0
- package/dist/types/helper.spec.js.map +1 -0
- package/dist/types/helpers.d.ts +51 -0
- package/dist/types/helpers.js +323 -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/types/roFunctionType.spec.d.ts +1 -0
- package/dist/types/roFunctionType.spec.js +20 -0
- package/dist/types/roFunctionType.spec.js.map +1 -0
- package/dist/util.d.ts +288 -187
- package/dist/util.js +2018 -575
- 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 +185 -138
- package/CHANGELOG.md +0 -1188
- 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/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.js +0 -45
- package/dist/bscPlugin/semanticTokens/SemanticTokensProcessor.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/SGTypes.spec.js +0 -351
- package/dist/parser/SGTypes.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/preprocessor/Chunk.d.ts +0 -82
- package/dist/preprocessor/Chunk.js +0 -77
- package/dist/preprocessor/Chunk.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.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.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/CustomType.d.ts +0 -10
- package/dist/types/CustomType.js +0 -35
- package/dist/types/CustomType.js.map +0 -1
- package/dist/types/FunctionType.spec.js +0 -29
- package/dist/types/FunctionType.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/{bscPlugin/semanticTokens/SemanticTokensProcessor.spec.d.ts → astUtils/CachedLookups.spec.d.ts} +0 -0
- /package/dist/{parser/SGTypes.spec.d.ts → astUtils/Editor.spec.d.ts} +0 -0
- /package/dist/{preprocessor/Preprocessor.spec.d.ts → bscPlugin/completions/CompletionsProcessor.spec.d.ts} +0 -0
- /package/dist/{preprocessor/PreprocessorParser.spec.d.ts → bscPlugin/definition/DefinitionProvider.spec.d.ts} +0 -0
- /package/dist/{types/FunctionType.spec.d.ts → bscPlugin/hover/HoverProcessor.spec.d.ts} +0 -0
package/dist/Program.js
CHANGED
|
@@ -7,32 +7,61 @@ const path = require("path");
|
|
|
7
7
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
8
8
|
const Scope_1 = require("./Scope");
|
|
9
9
|
const DiagnosticMessages_1 = require("./DiagnosticMessages");
|
|
10
|
-
const BrsFile_1 = require("./files/BrsFile");
|
|
11
|
-
const XmlFile_1 = require("./files/XmlFile");
|
|
12
10
|
const util_1 = require("./util");
|
|
13
11
|
const XmlScope_1 = require("./XmlScope");
|
|
14
|
-
const DiagnosticFilterer_1 = require("./DiagnosticFilterer");
|
|
15
12
|
const DependencyGraph_1 = require("./DependencyGraph");
|
|
16
|
-
const
|
|
13
|
+
const logging_1 = require("./logging");
|
|
17
14
|
const chalk_1 = require("chalk");
|
|
18
15
|
const globalCallables_1 = require("./globalCallables");
|
|
19
16
|
const Manifest_1 = require("./preprocessor/Manifest");
|
|
20
17
|
const vscode_uri_1 = require("vscode-uri");
|
|
21
18
|
const PluginInterface_1 = require("./PluginInterface");
|
|
22
19
|
const reflection_1 = require("./astUtils/reflection");
|
|
23
|
-
const parser_1 = require("./parser");
|
|
24
|
-
const lexer_1 = require("./lexer");
|
|
25
20
|
const BscPlugin_1 = require("./bscPlugin/BscPlugin");
|
|
21
|
+
const Editor_1 = require("./astUtils/Editor");
|
|
22
|
+
const IntegerType_1 = require("./types/IntegerType");
|
|
23
|
+
const StringType_1 = require("./types/StringType");
|
|
24
|
+
const BooleanType_1 = require("./types/BooleanType");
|
|
25
|
+
const DoubleType_1 = require("./types/DoubleType");
|
|
26
|
+
const DynamicType_1 = require("./types/DynamicType");
|
|
27
|
+
const FloatType_1 = require("./types/FloatType");
|
|
28
|
+
const LongIntegerType_1 = require("./types/LongIntegerType");
|
|
29
|
+
const ObjectType_1 = require("./types/ObjectType");
|
|
30
|
+
const VoidType_1 = require("./types/VoidType");
|
|
31
|
+
const FunctionType_1 = require("./types/FunctionType");
|
|
32
|
+
const Factory_1 = require("./files/Factory");
|
|
33
|
+
const ActionPipeline_1 = require("./ActionPipeline");
|
|
34
|
+
const LazyFileData_1 = require("./files/LazyFileData");
|
|
26
35
|
const roku_deploy_1 = require("roku-deploy");
|
|
27
|
-
const
|
|
28
|
-
const
|
|
36
|
+
const roku_types_1 = require("./roku-types");
|
|
37
|
+
const ComponentType_1 = require("./types/ComponentType");
|
|
38
|
+
const InterfaceType_1 = require("./types/InterfaceType");
|
|
39
|
+
const BuiltInInterfaceAdder_1 = require("./types/BuiltInInterfaceAdder");
|
|
40
|
+
const visitors_1 = require("./astUtils/visitors");
|
|
41
|
+
const thenby_1 = require("thenby");
|
|
42
|
+
const CrossScopeValidator_1 = require("./CrossScopeValidator");
|
|
43
|
+
const DiagnosticManager_1 = require("./DiagnosticManager");
|
|
44
|
+
const ProgramValidator_1 = require("./bscPlugin/validation/ProgramValidator");
|
|
45
|
+
const SymbolTable_1 = require("./SymbolTable");
|
|
46
|
+
const ReferenceType_1 = require("./types/ReferenceType");
|
|
47
|
+
const helpers_1 = require("./types/helpers");
|
|
48
|
+
const CallExpressionInfo_1 = require("./bscPlugin/CallExpressionInfo");
|
|
49
|
+
const SignatureHelpUtil_1 = require("./bscPlugin/SignatureHelpUtil");
|
|
50
|
+
const Sequencer_1 = require("./common/Sequencer");
|
|
51
|
+
const deferred_1 = require("./deferred");
|
|
52
|
+
const roFunctionType_1 = require("./types/roFunctionType");
|
|
53
|
+
const bslibNonAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/rokucommunity_bslib/bslib.brs`;
|
|
54
|
+
const bslibAliasedRokuModulesPkgPath = (0, util_1.standardizePath) `source/roku_modules/bslib/bslib.brs`;
|
|
29
55
|
class Program {
|
|
30
56
|
constructor(
|
|
31
57
|
/**
|
|
32
58
|
* The root directory for this program
|
|
33
59
|
*/
|
|
34
|
-
options, logger, plugins) {
|
|
35
|
-
|
|
60
|
+
options, logger, plugins, diagnosticsManager) {
|
|
61
|
+
/**
|
|
62
|
+
* An editor that plugins can use to modify program-level things during the build flow. Don't use this to edit files (they have their own `.editor`)
|
|
63
|
+
*/
|
|
64
|
+
this.editor = new Editor_1.Editor();
|
|
36
65
|
/**
|
|
37
66
|
* A graph of all files and their dependencies.
|
|
38
67
|
* For example:
|
|
@@ -40,20 +69,37 @@ class Program {
|
|
|
40
69
|
* lib2.brs -> [lib3.brs] //via an import statement
|
|
41
70
|
*/
|
|
42
71
|
this.dependencyGraph = new DependencyGraph_1.DependencyGraph();
|
|
43
|
-
this.diagnosticFilterer = new DiagnosticFilterer_1.DiagnosticFilterer();
|
|
44
72
|
/**
|
|
45
|
-
* A
|
|
46
|
-
*
|
|
73
|
+
* A scope that contains all built-in global functions.
|
|
74
|
+
* All scopes should directly or indirectly inherit from this scope
|
|
75
|
+
*/
|
|
76
|
+
this.globalScope = undefined;
|
|
77
|
+
this.fileSymbolInformation = new Map();
|
|
78
|
+
/**
|
|
79
|
+
* Map of typetime symbols which depend upon the key symbol
|
|
47
80
|
*/
|
|
48
|
-
this.
|
|
81
|
+
this.symbolDependencies = new Map();
|
|
49
82
|
/**
|
|
50
|
-
*
|
|
83
|
+
* Symbol Table for storing custom component types
|
|
84
|
+
* This is a sibling to the global table (as Components can be used/referenced anywhere)
|
|
85
|
+
* Keeping custom components out of the global table and in a specific symbol table
|
|
86
|
+
* compartmentalizes their use
|
|
51
87
|
*/
|
|
52
|
-
this.
|
|
88
|
+
this.componentsTable = new SymbolTable_1.SymbolTable('Custom Components');
|
|
53
89
|
/**
|
|
54
|
-
* A map of every file loaded into this program, indexed by its
|
|
90
|
+
* A map of every file loaded into this program, indexed by its original file location
|
|
55
91
|
*/
|
|
56
92
|
this.files = {};
|
|
93
|
+
/**
|
|
94
|
+
* A map of every file loaded into this program, indexed by its destPath
|
|
95
|
+
*/
|
|
96
|
+
this.destMap = new Map();
|
|
97
|
+
/**
|
|
98
|
+
* Plugins can contribute multiple virtual files for a single physical file.
|
|
99
|
+
* This collection links the virtual files back to the physical file that produced them.
|
|
100
|
+
* The key is the standardized and lower-cased srcPath
|
|
101
|
+
*/
|
|
102
|
+
this.fileClusters = new Map();
|
|
57
103
|
this.scopes = {};
|
|
58
104
|
/**
|
|
59
105
|
* A map of every component currently loaded into the program, indexed by the component name.
|
|
@@ -62,28 +108,184 @@ class Program {
|
|
|
62
108
|
* but if you do, only ever use the component at index 0.
|
|
63
109
|
*/
|
|
64
110
|
this.components = {};
|
|
111
|
+
/**
|
|
112
|
+
* Keeps a set of all the components that need to have their types updated during the current validation cycle
|
|
113
|
+
* Map <componentKey, componentName>
|
|
114
|
+
*/
|
|
115
|
+
this.componentSymbolsToUpdate = new Map();
|
|
116
|
+
this.crossScopeValidation = new CrossScopeValidator_1.CrossScopeValidator(this);
|
|
117
|
+
this.isFirstValidation = true;
|
|
118
|
+
this.validationDetails = {
|
|
119
|
+
brsFilesValidated: [],
|
|
120
|
+
xmlFilesValidated: [],
|
|
121
|
+
changedSymbols: new Map(),
|
|
122
|
+
changedComponentTypes: [],
|
|
123
|
+
scopesToValidate: [],
|
|
124
|
+
filesToBeValidatedInScopeContext: new Set()
|
|
125
|
+
};
|
|
126
|
+
this.lastValidationInfo = {
|
|
127
|
+
brsFilesSrcPath: new Set(),
|
|
128
|
+
xmlFilesSrcPath: new Set(),
|
|
129
|
+
scopeNames: new Set(),
|
|
130
|
+
componentsRebuilt: new Set()
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Counter used to track which validation run is being logged
|
|
134
|
+
*/
|
|
135
|
+
this.validationRunSequence = 1;
|
|
136
|
+
/**
|
|
137
|
+
* How many milliseconds can pass while doing synchronous operations in validate before we register a short timeout (i.e. yield to the event loop)
|
|
138
|
+
*/
|
|
139
|
+
this.validationMinSyncDuration = 75;
|
|
140
|
+
this.getFilePathCache = new Map();
|
|
141
|
+
this.sortedScopeNames = undefined;
|
|
142
|
+
this.getTranspiledFileContentsPipeline = new ActionPipeline_1.ActionPipeline();
|
|
143
|
+
this.buildPipeline = new ActionPipeline_1.ActionPipeline();
|
|
65
144
|
this.options = util_1.util.normalizeConfig(options);
|
|
66
|
-
this.logger = logger
|
|
67
|
-
this.plugins = plugins || new PluginInterface_1.default([], this.logger);
|
|
145
|
+
this.logger = logger !== null && logger !== void 0 ? logger : (0, logging_1.createLogger)(options);
|
|
146
|
+
this.plugins = plugins || new PluginInterface_1.default([], { logger: this.logger });
|
|
147
|
+
this.diagnostics = diagnosticsManager || new DiagnosticManager_1.DiagnosticManager();
|
|
148
|
+
//try to find a location for the diagnostic if it doesn't have one
|
|
149
|
+
this.diagnostics.locationResolver = (args) => {
|
|
150
|
+
//find the first xml scope for this diagnostic
|
|
151
|
+
for (let context of args.contexts) {
|
|
152
|
+
if ((0, reflection_1.isXmlScope)(context.scope) && (0, reflection_1.isXmlFile)(context.scope.xmlFile)) {
|
|
153
|
+
return util_1.util.createLocation(0, 0, 0, 100, context.scope.xmlFile.srcPath);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
//we couldn't find an xml scope for this, so try to find the manifest file instead
|
|
157
|
+
const manifest = this.getFile('manifest', false);
|
|
158
|
+
if (manifest) {
|
|
159
|
+
return util_1.util.createLocation(0, 0, 0, 100, manifest.srcPath);
|
|
160
|
+
}
|
|
161
|
+
//if we still don't have a manifest, try to find the first file in the program
|
|
162
|
+
for (const key in this.files) {
|
|
163
|
+
if ((0, reflection_1.isBrsFile)(this.files[key]) || (0, reflection_1.isXmlFile)(this.files[key])) {
|
|
164
|
+
return util_1.util.createLocation(0, 0, 0, 100, this.files[key].srcPath);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
this.logger.warn(`Unable to find a location for the diagnostic.`, args);
|
|
168
|
+
//we couldn't find any locations for the file, so just return undefined
|
|
169
|
+
return undefined;
|
|
170
|
+
};
|
|
171
|
+
// initialize the diagnostics Manager
|
|
172
|
+
this.diagnostics.logger = this.logger;
|
|
173
|
+
this.diagnostics.options = this.options;
|
|
174
|
+
this.diagnostics.program = this;
|
|
68
175
|
//inject the bsc plugin as the first plugin in the stack.
|
|
69
176
|
this.plugins.addFirst(new BscPlugin_1.BscPlugin());
|
|
70
177
|
//normalize the root dir path
|
|
71
178
|
this.options.rootDir = util_1.util.getRootDir(this.options);
|
|
72
179
|
this.createGlobalScope();
|
|
180
|
+
this.fileFactory = new Factory_1.FileFactory(this);
|
|
73
181
|
}
|
|
74
182
|
createGlobalScope() {
|
|
75
183
|
//create the 'global' scope
|
|
76
184
|
this.globalScope = new Scope_1.Scope('global', this, 'scope:global');
|
|
77
185
|
this.globalScope.attachDependencyGraph(this.dependencyGraph);
|
|
78
186
|
this.scopes.global = this.globalScope;
|
|
187
|
+
this.populateGlobalSymbolTable();
|
|
188
|
+
this.globalScope.symbolTable.addSibling(this.componentsTable);
|
|
79
189
|
//hardcode the files list for global scope to only contain the global file
|
|
80
190
|
this.globalScope.getAllFiles = () => [globalCallables_1.globalFile];
|
|
191
|
+
globalCallables_1.globalFile.isValidated = true;
|
|
81
192
|
this.globalScope.validate();
|
|
82
|
-
//for now, disable validation of global scope because the global files have some duplicate method declarations
|
|
83
|
-
this.globalScope.getDiagnostics = () => [];
|
|
84
193
|
//TODO we might need to fix this because the isValidated clears stuff now
|
|
85
194
|
this.globalScope.isValidated = true;
|
|
86
195
|
}
|
|
196
|
+
recursivelyAddNodeToSymbolTable(nodeData) {
|
|
197
|
+
if (!nodeData) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
let nodeType;
|
|
201
|
+
const nodeName = util_1.util.getSgNodeTypeName(nodeData.name);
|
|
202
|
+
if (!this.globalScope.symbolTable.hasSymbol(nodeName, 2 /* SymbolTypeFlag.typetime */)) {
|
|
203
|
+
let parentNode;
|
|
204
|
+
if (nodeData.extends) {
|
|
205
|
+
const parentNodeData = roku_types_1.nodes[nodeData.extends.name.toLowerCase()];
|
|
206
|
+
try {
|
|
207
|
+
parentNode = this.recursivelyAddNodeToSymbolTable(parentNodeData);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
this.logger.error(error, nodeData);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
nodeType = new ComponentType_1.ComponentType(nodeData.name, parentNode);
|
|
214
|
+
nodeType.addBuiltInInterfaces();
|
|
215
|
+
nodeType.isBuiltIn = true;
|
|
216
|
+
if (nodeData.name === 'Node') {
|
|
217
|
+
// Add `roSGNode` as shorthand for `roSGNodeNode`
|
|
218
|
+
this.globalScope.symbolTable.addSymbol('roSGNode', { description: nodeData.description, isBuiltIn: true }, nodeType, 2 /* SymbolTypeFlag.typetime */);
|
|
219
|
+
}
|
|
220
|
+
this.globalScope.symbolTable.addSymbol(nodeName, { description: nodeData.description, isBuiltIn: true }, nodeType, 2 /* SymbolTypeFlag.typetime */);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
nodeType = this.globalScope.symbolTable.getSymbolType(nodeName, { flags: 2 /* SymbolTypeFlag.typetime */ });
|
|
224
|
+
}
|
|
225
|
+
return nodeType;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Do all setup required for the global symbol table.
|
|
229
|
+
*/
|
|
230
|
+
populateGlobalSymbolTable() {
|
|
231
|
+
//Setup primitive types in global symbolTable
|
|
232
|
+
const builtInSymbolData = { isBuiltIn: true };
|
|
233
|
+
this.globalScope.symbolTable.addSymbol('boolean', builtInSymbolData, BooleanType_1.BooleanType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
234
|
+
this.globalScope.symbolTable.addSymbol('double', builtInSymbolData, DoubleType_1.DoubleType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
235
|
+
this.globalScope.symbolTable.addSymbol('dynamic', builtInSymbolData, DynamicType_1.DynamicType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
236
|
+
this.globalScope.symbolTable.addSymbol('float', builtInSymbolData, FloatType_1.FloatType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
237
|
+
this.globalScope.symbolTable.addSymbol('function', builtInSymbolData, FunctionType_1.FunctionType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
238
|
+
this.globalScope.symbolTable.addSymbol('integer', builtInSymbolData, IntegerType_1.IntegerType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
239
|
+
this.globalScope.symbolTable.addSymbol('longinteger', builtInSymbolData, LongIntegerType_1.LongIntegerType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
240
|
+
this.globalScope.symbolTable.addSymbol('object', builtInSymbolData, ObjectType_1.ObjectType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
241
|
+
this.globalScope.symbolTable.addSymbol('string', builtInSymbolData, StringType_1.StringType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
242
|
+
this.globalScope.symbolTable.addSymbol('void', builtInSymbolData, VoidType_1.VoidType.instance, 2 /* SymbolTypeFlag.typetime */);
|
|
243
|
+
BuiltInInterfaceAdder_1.BuiltInInterfaceAdder.getLookupTable = () => this.globalScope.symbolTable;
|
|
244
|
+
for (const callable of globalCallables_1.globalCallables) {
|
|
245
|
+
this.globalScope.symbolTable.addSymbol(callable.name, Object.assign(Object.assign({}, builtInSymbolData), { description: callable.shortDescription }), callable.type, 1 /* SymbolTypeFlag.runtime */);
|
|
246
|
+
}
|
|
247
|
+
for (const ifaceData of Object.values(roku_types_1.interfaces)) {
|
|
248
|
+
const ifaceType = new InterfaceType_1.InterfaceType(ifaceData.name);
|
|
249
|
+
ifaceType.addBuiltInInterfaces();
|
|
250
|
+
ifaceType.isBuiltIn = true;
|
|
251
|
+
this.globalScope.symbolTable.addSymbol(ifaceData.name, Object.assign(Object.assign({}, builtInSymbolData), { description: ifaceData.description }), ifaceType, 2 /* SymbolTypeFlag.typetime */);
|
|
252
|
+
}
|
|
253
|
+
for (const componentData of Object.values(roku_types_1.components)) {
|
|
254
|
+
let roComponentType;
|
|
255
|
+
const lowerComponentName = componentData.name.toLowerCase();
|
|
256
|
+
if (lowerComponentName === 'rosgnode') {
|
|
257
|
+
// we will add `roSGNode` as shorthand for `roSGNodeNode`, since all roSgNode components are SceneGraph nodes
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (lowerComponentName === 'rofunction') {
|
|
261
|
+
roComponentType = new roFunctionType_1.roFunctionType();
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
roComponentType = new InterfaceType_1.InterfaceType(componentData.name);
|
|
265
|
+
}
|
|
266
|
+
roComponentType.addBuiltInInterfaces();
|
|
267
|
+
roComponentType.isBuiltIn = true;
|
|
268
|
+
this.globalScope.symbolTable.addSymbol(componentData.name, Object.assign(Object.assign({}, builtInSymbolData), { description: componentData.description }), roComponentType, 2 /* SymbolTypeFlag.typetime */);
|
|
269
|
+
}
|
|
270
|
+
for (const nodeData of Object.values(roku_types_1.nodes)) {
|
|
271
|
+
this.recursivelyAddNodeToSymbolTable(nodeData);
|
|
272
|
+
}
|
|
273
|
+
for (const eventData of Object.values(roku_types_1.events)) {
|
|
274
|
+
const eventType = new InterfaceType_1.InterfaceType(eventData.name);
|
|
275
|
+
eventType.addBuiltInInterfaces();
|
|
276
|
+
eventType.isBuiltIn = true;
|
|
277
|
+
this.globalScope.symbolTable.addSymbol(eventData.name, Object.assign(Object.assign({}, builtInSymbolData), { description: eventData.description }), eventType, 2 /* SymbolTypeFlag.typetime */);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
addFileSymbolInfo(file) {
|
|
281
|
+
this.fileSymbolInformation.set(file.pkgPath, {
|
|
282
|
+
provides: file.providedSymbols,
|
|
283
|
+
requires: file.requiredSymbols
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
getFileSymbolInfo(file) {
|
|
287
|
+
return this.fileSymbolInformation.get(file.pkgPath);
|
|
288
|
+
}
|
|
87
289
|
/**
|
|
88
290
|
* The path to bslib.brs (the BrightScript runtime for certain BrighterScript features)
|
|
89
291
|
*/
|
|
@@ -98,7 +300,7 @@ class Program {
|
|
|
98
300
|
//default to the embedded version
|
|
99
301
|
}
|
|
100
302
|
else {
|
|
101
|
-
return
|
|
303
|
+
return `${this.options.bslibDestinationDir}${path.sep}bslib.brs`;
|
|
102
304
|
}
|
|
103
305
|
}
|
|
104
306
|
get bslibPrefix() {
|
|
@@ -109,18 +311,15 @@ class Program {
|
|
|
109
311
|
return 'bslib';
|
|
110
312
|
}
|
|
111
313
|
}
|
|
112
|
-
/**
|
|
113
|
-
* Get a copy of the list of files currently loaded in the program
|
|
114
|
-
*/
|
|
115
|
-
getFiles() {
|
|
116
|
-
return Object.values(this.files);
|
|
117
|
-
}
|
|
118
314
|
addScope(scope) {
|
|
119
315
|
this.scopes[scope.name] = scope;
|
|
120
|
-
this.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
316
|
+
delete this.sortedScopeNames;
|
|
317
|
+
}
|
|
318
|
+
removeScope(scope) {
|
|
319
|
+
if (this.scopes[scope.name]) {
|
|
320
|
+
delete this.scopes[scope.name];
|
|
321
|
+
delete this.sortedScopeNames;
|
|
322
|
+
}
|
|
124
323
|
}
|
|
125
324
|
/**
|
|
126
325
|
* Get the component with the specified name
|
|
@@ -129,19 +328,34 @@ class Program {
|
|
|
129
328
|
var _a;
|
|
130
329
|
if (componentName) {
|
|
131
330
|
//return the first compoment in the list with this name
|
|
132
|
-
//(components are ordered in this list by
|
|
331
|
+
//(components are ordered in this list by destPath to ensure consistency)
|
|
133
332
|
return (_a = this.components[componentName.toLowerCase()]) === null || _a === void 0 ? void 0 : _a[0];
|
|
134
333
|
}
|
|
135
334
|
else {
|
|
136
335
|
return undefined;
|
|
137
336
|
}
|
|
138
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Get the sorted names of custom components
|
|
340
|
+
*/
|
|
341
|
+
getSortedComponentNames() {
|
|
342
|
+
const componentNames = Object.keys(this.components);
|
|
343
|
+
componentNames.sort((a, b) => {
|
|
344
|
+
if (a < b) {
|
|
345
|
+
return -1;
|
|
346
|
+
}
|
|
347
|
+
else if (b < a) {
|
|
348
|
+
return 1;
|
|
349
|
+
}
|
|
350
|
+
return 0;
|
|
351
|
+
});
|
|
352
|
+
return componentNames;
|
|
353
|
+
}
|
|
139
354
|
/**
|
|
140
355
|
* Register (or replace) the reference to a component in the component map
|
|
141
356
|
*/
|
|
142
357
|
registerComponent(xmlFile, scope) {
|
|
143
|
-
|
|
144
|
-
const key = ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
358
|
+
const key = this.getComponentKey(xmlFile);
|
|
145
359
|
if (!this.components[key]) {
|
|
146
360
|
this.components[key] = [];
|
|
147
361
|
}
|
|
@@ -149,15 +363,25 @@ class Program {
|
|
|
149
363
|
file: xmlFile,
|
|
150
364
|
scope: scope
|
|
151
365
|
});
|
|
152
|
-
this.components[key].sort((
|
|
366
|
+
this.components[key].sort((a, b) => {
|
|
367
|
+
const pathA = a.file.destPath.toLowerCase();
|
|
368
|
+
const pathB = b.file.destPath.toLowerCase();
|
|
369
|
+
if (pathA < pathB) {
|
|
370
|
+
return -1;
|
|
371
|
+
}
|
|
372
|
+
else if (pathA > pathB) {
|
|
373
|
+
return 1;
|
|
374
|
+
}
|
|
375
|
+
return 0;
|
|
376
|
+
});
|
|
153
377
|
this.syncComponentDependencyGraph(this.components[key]);
|
|
378
|
+
this.addDeferredComponentTypeSymbolCreation(xmlFile);
|
|
154
379
|
}
|
|
155
380
|
/**
|
|
156
381
|
* Remove the specified component from the components map
|
|
157
382
|
*/
|
|
158
383
|
unregisterComponent(xmlFile) {
|
|
159
|
-
|
|
160
|
-
const key = ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
384
|
+
const key = this.getComponentKey(xmlFile);
|
|
161
385
|
const arr = this.components[key] || [];
|
|
162
386
|
for (let i = 0; i < arr.length; i++) {
|
|
163
387
|
if (arr[i].file === xmlFile) {
|
|
@@ -166,6 +390,84 @@ class Program {
|
|
|
166
390
|
}
|
|
167
391
|
}
|
|
168
392
|
this.syncComponentDependencyGraph(arr);
|
|
393
|
+
this.addDeferredComponentTypeSymbolCreation(xmlFile);
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Adds a component described in an XML to the set of components that needs to be updated this validation cycle.
|
|
397
|
+
* @param xmlFile XML file with <component> tag
|
|
398
|
+
*/
|
|
399
|
+
addDeferredComponentTypeSymbolCreation(xmlFile) {
|
|
400
|
+
var _a;
|
|
401
|
+
const componentKey = this.getComponentKey(xmlFile);
|
|
402
|
+
const componentName = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text;
|
|
403
|
+
if (this.componentSymbolsToUpdate.has(componentKey)) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
this.componentSymbolsToUpdate.set(componentKey, componentName);
|
|
407
|
+
}
|
|
408
|
+
getComponentKey(xmlFile) {
|
|
409
|
+
var _a, _b;
|
|
410
|
+
return ((_b = (_a = xmlFile.componentName) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : xmlFile.pkgPath).toLowerCase();
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Resolves symbol table with the first component in this.components to have the same name as the component in the file
|
|
414
|
+
* @param componentKey key getting a component from `this.components`
|
|
415
|
+
* @param componentName the unprefixed name of the component that will be added (e.g. 'MyLabel' NOT 'roSgNodeMyLabel')
|
|
416
|
+
*/
|
|
417
|
+
updateComponentSymbolInGlobalScope(componentKey, componentName) {
|
|
418
|
+
const symbolName = componentName ? util_1.util.getSgNodeTypeName(componentName) : undefined;
|
|
419
|
+
if (!symbolName) {
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
const components = this.components[componentKey] || [];
|
|
423
|
+
const previousComponentType = this.componentsTable.getSymbolType(symbolName, { flags: 2 /* SymbolTypeFlag.typetime */ });
|
|
424
|
+
// Remove any existing symbols that match
|
|
425
|
+
this.componentsTable.removeSymbol(symbolName);
|
|
426
|
+
if (components.length > 0) {
|
|
427
|
+
// There is a component that can be added - use it.
|
|
428
|
+
const componentScope = components[0].scope;
|
|
429
|
+
this.componentsTable.removeSymbol(symbolName);
|
|
430
|
+
componentScope.linkSymbolTable();
|
|
431
|
+
const componentType = componentScope.getComponentType();
|
|
432
|
+
if (componentType) {
|
|
433
|
+
this.componentsTable.addSymbol(symbolName, {}, componentType, 2 /* SymbolTypeFlag.typetime */);
|
|
434
|
+
}
|
|
435
|
+
const typeData = {};
|
|
436
|
+
const isSameAsPrevious = previousComponentType && componentType.isEqual(previousComponentType, typeData);
|
|
437
|
+
const isComponentTypeDifferent = !previousComponentType || (0, reflection_1.isReferenceType)(previousComponentType) || !isSameAsPrevious;
|
|
438
|
+
componentScope.unlinkSymbolTable();
|
|
439
|
+
return isComponentTypeDifferent;
|
|
440
|
+
}
|
|
441
|
+
// There was a previous component type, but no new one, so it's different
|
|
442
|
+
return !!previousComponentType;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Adds a reference type to the global symbol table with the first component in this.components to have the same name as the component in the file
|
|
446
|
+
* This is so on a first validation, these types can be resolved in teh future (eg. when the actual component is created)
|
|
447
|
+
* If we don't add reference types at this top level, they will be created at the file level, and will never get resolved
|
|
448
|
+
* @param componentKey key getting a component from `this.components`
|
|
449
|
+
* @param componentName the unprefixed name of the component that will be added (e.g. 'MyLabel' NOT 'roSgNodeMyLabel')
|
|
450
|
+
*/
|
|
451
|
+
addComponentReferenceType(componentKey, componentName) {
|
|
452
|
+
const symbolName = componentName ? util_1.util.getSgNodeTypeName(componentName) : undefined;
|
|
453
|
+
if (!symbolName) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const components = this.components[componentKey] || [];
|
|
457
|
+
if (components.length > 0) {
|
|
458
|
+
// There is a component that can be added,
|
|
459
|
+
if (!this.componentsTable.hasSymbol(symbolName, 2 /* SymbolTypeFlag.typetime */)) {
|
|
460
|
+
// it doesn't already exist in the table
|
|
461
|
+
const componentRefType = new ReferenceType_1.ReferenceType(symbolName, symbolName, 2 /* SymbolTypeFlag.typetime */, () => this.componentsTable);
|
|
462
|
+
if (componentRefType) {
|
|
463
|
+
this.componentsTable.addSymbol(symbolName, {}, componentRefType, 2 /* SymbolTypeFlag.typetime */);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
else {
|
|
468
|
+
// there is no component. remove from table
|
|
469
|
+
this.componentsTable.removeSymbol(symbolName);
|
|
470
|
+
}
|
|
169
471
|
}
|
|
170
472
|
/**
|
|
171
473
|
* re-attach the dependency graph with a new key for any component who changed
|
|
@@ -179,6 +481,7 @@ class Program {
|
|
|
179
481
|
//attach (or re-attach) the dependencyGraph for every component whose position changed
|
|
180
482
|
if (file.dependencyGraphIndex !== i) {
|
|
181
483
|
file.dependencyGraphIndex = i;
|
|
484
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, file.dependencies);
|
|
182
485
|
file.attachDependencyGraph(this.dependencyGraph);
|
|
183
486
|
scope.attachDependencyGraph(this.dependencyGraph);
|
|
184
487
|
}
|
|
@@ -190,9 +493,10 @@ class Program {
|
|
|
190
493
|
*/
|
|
191
494
|
getUnreferencedFiles() {
|
|
192
495
|
let result = [];
|
|
193
|
-
for (let
|
|
194
|
-
|
|
195
|
-
|
|
496
|
+
for (let filePath in this.files) {
|
|
497
|
+
let file = this.files[filePath];
|
|
498
|
+
//is this file part of a scope
|
|
499
|
+
if (!this.getFirstScopeForFile(file)) {
|
|
196
500
|
//no scopes reference this file. add it to the list
|
|
197
501
|
result.push(file);
|
|
198
502
|
}
|
|
@@ -200,37 +504,14 @@ class Program {
|
|
|
200
504
|
return result;
|
|
201
505
|
}
|
|
202
506
|
/**
|
|
203
|
-
* Get the list of errors for the entire program.
|
|
204
|
-
* by walking through every file, so call this sparingly.
|
|
507
|
+
* Get the list of errors for the entire program.
|
|
205
508
|
*/
|
|
206
509
|
getDiagnostics() {
|
|
207
|
-
return this.
|
|
208
|
-
let diagnostics = [...this.diagnostics];
|
|
209
|
-
//get the diagnostics from all scopes
|
|
210
|
-
for (let scopeName in this.scopes) {
|
|
211
|
-
let scope = this.scopes[scopeName];
|
|
212
|
-
diagnostics.push(...scope.getDiagnostics());
|
|
213
|
-
}
|
|
214
|
-
//get the diagnostics from all unreferenced files
|
|
215
|
-
let unreferencedFiles = this.getUnreferencedFiles();
|
|
216
|
-
for (let file of unreferencedFiles) {
|
|
217
|
-
diagnostics.push(...file.getDiagnostics());
|
|
218
|
-
}
|
|
219
|
-
const filteredDiagnostics = this.logger.time(Logger_1.LogLevel.debug, ['filter diagnostics'], () => {
|
|
220
|
-
//filter out diagnostics based on our diagnostic filters
|
|
221
|
-
let finalDiagnostics = this.diagnosticFilterer.filter(Object.assign(Object.assign({}, this.options), { rootDir: this.options.rootDir }), diagnostics);
|
|
222
|
-
return finalDiagnostics;
|
|
223
|
-
});
|
|
224
|
-
this.logger.info(`diagnostic counts: total=${chalk_1.default.yellow(diagnostics.length.toString())}, after filter=${chalk_1.default.yellow(filteredDiagnostics.length.toString())}`);
|
|
225
|
-
return filteredDiagnostics;
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
addDiagnostics(diagnostics) {
|
|
229
|
-
this.diagnostics.push(...diagnostics);
|
|
510
|
+
return this.diagnostics.getDiagnostics();
|
|
230
511
|
}
|
|
231
512
|
/**
|
|
232
513
|
* Determine if the specified file is loaded in this program right now.
|
|
233
|
-
* @param filePath
|
|
514
|
+
* @param filePath the absolute or relative path to the file
|
|
234
515
|
* @param normalizePath should the provided path be normalized before use
|
|
235
516
|
*/
|
|
236
517
|
hasFile(filePath, normalizePath = true) {
|
|
@@ -238,12 +519,15 @@ class Program {
|
|
|
238
519
|
}
|
|
239
520
|
/**
|
|
240
521
|
* roku filesystem is case INsensitive, so find the scope by key case insensitive
|
|
241
|
-
* @param scopeName
|
|
522
|
+
* @param scopeName xml scope names are their `destPath`. Source scope is stored with the key `"source"`
|
|
242
523
|
*/
|
|
243
524
|
getScopeByName(scopeName) {
|
|
244
525
|
if (!scopeName) {
|
|
245
526
|
return undefined;
|
|
246
527
|
}
|
|
528
|
+
//most scopes are xml file pkg paths. however, the ones that are not are single names like "global" and "scope",
|
|
529
|
+
//so it's safe to run the standardizePkgPath method
|
|
530
|
+
scopeName = (0, util_1.standardizePath) `${scopeName}`;
|
|
247
531
|
let key = Object.keys(this.scopes).find(x => x.toLowerCase() === scopeName.toLowerCase());
|
|
248
532
|
return this.scopes[key];
|
|
249
533
|
}
|
|
@@ -264,113 +548,178 @@ class Program {
|
|
|
264
548
|
* Update internal maps with this file reference
|
|
265
549
|
*/
|
|
266
550
|
assignFile(file) {
|
|
551
|
+
const fileAddEvent = {
|
|
552
|
+
file: file,
|
|
553
|
+
program: this
|
|
554
|
+
};
|
|
555
|
+
this.plugins.emit('beforeAddFile', fileAddEvent);
|
|
267
556
|
this.files[file.srcPath.toLowerCase()] = file;
|
|
268
|
-
this.
|
|
557
|
+
this.destMap.set(file.destPath.toLowerCase(), file);
|
|
558
|
+
this.plugins.emit('afterAddFile', fileAddEvent);
|
|
559
|
+
return file;
|
|
269
560
|
}
|
|
270
561
|
/**
|
|
271
562
|
* Remove this file from internal maps
|
|
272
563
|
*/
|
|
273
564
|
unassignFile(file) {
|
|
274
565
|
delete this.files[file.srcPath.toLowerCase()];
|
|
275
|
-
|
|
566
|
+
this.destMap.delete(file.destPath.toLowerCase());
|
|
567
|
+
return file;
|
|
276
568
|
}
|
|
277
|
-
setFile(fileParam,
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
let
|
|
281
|
-
|
|
282
|
-
//is a pkg path
|
|
283
|
-
if (fileParam.startsWith('pkg:/')) {
|
|
284
|
-
//srcPath is the pkgPath relative to the rootDir
|
|
285
|
-
srcPath = util_1.standardizePath `${this.options.rootDir}/${fileParam.substring(5)}`;
|
|
286
|
-
pkgPath = fileParam;
|
|
287
|
-
//is a srcPath (absolute path to src file location)
|
|
288
|
-
}
|
|
289
|
-
else if (path.isAbsolute(fileParam)) {
|
|
290
|
-
srcPath = util_1.util.standardizePath(fileParam);
|
|
291
|
-
//assume the file path is a sub path of rootDir
|
|
292
|
-
pkgPath = util_1.util.sanitizePkgPath(roku_deploy_1.util.stringReplaceInsensitive(srcPath, this.options.rootDir, ''));
|
|
293
|
-
//is destPath (path relative to rootDir and `pkg:/`)
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
srcPath = util_1.standardizePath `${this.options.rootDir}/${fileParam}`;
|
|
297
|
-
pkgPath = util_1.util.sanitizePkgPath(fileParam);
|
|
298
|
-
}
|
|
299
|
-
//is a FileObj
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
302
|
-
srcPath = util_1.standardizePath `${fileParam.src}`;
|
|
303
|
-
pkgPath = util_1.util.sanitizePkgPath(fileParam.dest);
|
|
304
|
-
}
|
|
305
|
-
const lowerPkgPath = pkgPath.toLowerCase();
|
|
306
|
-
return this.logger.time(Logger_1.LogLevel.debug, ['Program.addOrReplaceFile()', chalk_1.default.green(srcPath)], () => {
|
|
307
|
-
assert.ok(srcPath, 'srcPath is required');
|
|
308
|
-
assert.ok(pkgPath, 'pkgPath is required');
|
|
569
|
+
setFile(fileParam, fileData) {
|
|
570
|
+
//normalize the file paths
|
|
571
|
+
const { srcPath, destPath } = this.getPaths(fileParam, this.options.rootDir);
|
|
572
|
+
let file = this.logger.time(logging_1.LogLevel.debug, ['Program.setFile()', chalk_1.default.green(srcPath)], () => {
|
|
573
|
+
var _a, _b, _c;
|
|
309
574
|
//if the file is already loaded, remove it
|
|
310
575
|
if (this.hasFile(srcPath)) {
|
|
311
|
-
this.removeFile(srcPath);
|
|
576
|
+
this.removeFile(srcPath, true, true);
|
|
312
577
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
578
|
+
const data = new LazyFileData_1.LazyFileData(fileData);
|
|
579
|
+
const event = new ProvideFileEventInternal(this, srcPath, destPath, data, this.fileFactory);
|
|
580
|
+
this.plugins.emit('beforeProvideFile', event);
|
|
581
|
+
this.plugins.emit('provideFile', event);
|
|
582
|
+
this.plugins.emit('afterProvideFile', event);
|
|
583
|
+
//if no files were provided, create a AssetFile to represent it.
|
|
584
|
+
if (event.files.length === 0) {
|
|
585
|
+
event.files.push(this.fileFactory.AssetFile({
|
|
586
|
+
srcPath: event.srcPath,
|
|
587
|
+
destPath: event.destPath,
|
|
588
|
+
pkgPath: event.destPath,
|
|
589
|
+
data: data
|
|
590
|
+
}));
|
|
591
|
+
}
|
|
592
|
+
//find the file instance for the srcPath that triggered this action.
|
|
593
|
+
const primaryFile = event.files.find(x => x.srcPath === srcPath);
|
|
594
|
+
if (!primaryFile) {
|
|
595
|
+
throw new Error(`No file provided for srcPath '${srcPath}'. Instead, received ${JSON.stringify(event.files.map(x => ({
|
|
596
|
+
type: x.type,
|
|
597
|
+
srcPath: x.srcPath,
|
|
598
|
+
destPath: x.destPath
|
|
599
|
+
})))}`);
|
|
600
|
+
}
|
|
601
|
+
//link the virtual files to the primary file
|
|
602
|
+
this.fileClusters.set((_a = primaryFile.srcPath) === null || _a === void 0 ? void 0 : _a.toLowerCase(), event.files);
|
|
603
|
+
for (const file of event.files) {
|
|
604
|
+
file.srcPath = (0, util_1.standardizePath)(file.srcPath);
|
|
605
|
+
if (file.destPath) {
|
|
606
|
+
file.destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(file.destPath, this.options.rootDir, '')}`;
|
|
607
|
+
}
|
|
608
|
+
if (file.pkgPath) {
|
|
609
|
+
file.pkgPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(file.pkgPath, this.options.rootDir, '')}`;
|
|
610
|
+
}
|
|
611
|
+
else {
|
|
612
|
+
file.pkgPath = file.destPath;
|
|
613
|
+
}
|
|
614
|
+
file.excludeFromOutput = file.excludeFromOutput === true;
|
|
615
|
+
//set the dependencyGraph key for every file to its destPath
|
|
616
|
+
file.dependencyGraphKey = file.destPath.toLowerCase();
|
|
617
|
+
this.assignFile(file);
|
|
618
|
+
//register a callback anytime this file's dependencies change
|
|
619
|
+
if (typeof file.onDependenciesChanged === 'function') {
|
|
620
|
+
(_b = file.disposables) !== null && _b !== void 0 ? _b : (file.disposables = []);
|
|
621
|
+
file.disposables.push(this.dependencyGraph.onchange(file.dependencyGraphKey, file.onDependenciesChanged.bind(file)));
|
|
622
|
+
}
|
|
623
|
+
//register this file (and its dependencies) with the dependency graph
|
|
624
|
+
this.dependencyGraph.addOrReplace(file.dependencyGraphKey, (_c = file.dependencies) !== null && _c !== void 0 ? _c : []);
|
|
625
|
+
//if this is a `source` file, add it to the source scope's dependency list
|
|
626
|
+
if (this.isSourceBrsFile(file)) {
|
|
324
627
|
this.createSourceScope();
|
|
325
|
-
this.dependencyGraph.addDependency('scope:source',
|
|
628
|
+
this.dependencyGraph.addDependency('scope:source', file.dependencyGraphKey);
|
|
629
|
+
}
|
|
630
|
+
//if this is an xml file in the components folder, register it as a component
|
|
631
|
+
if (this.isComponentsXmlFile(file)) {
|
|
632
|
+
this.plugins.emit('beforeProvideScope', {
|
|
633
|
+
program: this,
|
|
634
|
+
scope: undefined
|
|
635
|
+
});
|
|
636
|
+
//create a new scope for this xml file
|
|
637
|
+
let scope = new XmlScope_1.XmlScope(file, this);
|
|
638
|
+
this.addScope(scope);
|
|
639
|
+
//register this componet now that we have parsed it and know its component name
|
|
640
|
+
this.registerComponent(file, scope);
|
|
641
|
+
this.plugins.emit('provideScope', {
|
|
642
|
+
program: this,
|
|
643
|
+
scope: scope
|
|
644
|
+
});
|
|
645
|
+
//notify plugins that the scope is created and the component is registered
|
|
646
|
+
this.plugins.emit('afterProvideScope', {
|
|
647
|
+
program: this,
|
|
648
|
+
scope: scope
|
|
649
|
+
});
|
|
326
650
|
}
|
|
327
|
-
//add the file to the program
|
|
328
|
-
this.assignFile(brsFile);
|
|
329
|
-
this.plugins.emit('beforeFileParse', beforeFileParseEvent);
|
|
330
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
331
|
-
brsFile.parse(beforeFileParseEvent.source);
|
|
332
|
-
});
|
|
333
|
-
file = brsFile;
|
|
334
|
-
brsFile.attachDependencyGraph(this.dependencyGraph);
|
|
335
|
-
this.plugins.emit('afterFileParse', {
|
|
336
|
-
program: this,
|
|
337
|
-
file: brsFile
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
else if (
|
|
341
|
-
//is xml file
|
|
342
|
-
fileExtension === '.xml' &&
|
|
343
|
-
//resides in the components folder (Roku will only parse xml files in the components folder)
|
|
344
|
-
lowerPkgPath.startsWith('pkg:/components/')) {
|
|
345
|
-
let xmlFile = new XmlFile_1.XmlFile(srcPath, pkgPath, this);
|
|
346
|
-
this.assignFile(xmlFile);
|
|
347
|
-
//add the file to the program
|
|
348
|
-
this.plugins.emit('beforeFileParse', beforeFileParseEvent);
|
|
349
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parse', chalk_1.default.green(srcPath)], () => {
|
|
350
|
-
xmlFile.parse(beforeFileParseEvent.source);
|
|
351
|
-
});
|
|
352
|
-
file = xmlFile;
|
|
353
|
-
//create a new scope for this xml file
|
|
354
|
-
let scope = new XmlScope_1.XmlScope(xmlFile, this);
|
|
355
|
-
this.addScope(scope);
|
|
356
|
-
//register this compoent now that we have parsed it and know its component name
|
|
357
|
-
this.registerComponent(xmlFile, scope);
|
|
358
|
-
this.plugins.emit('afterFileParse', {
|
|
359
|
-
program: this,
|
|
360
|
-
file: xmlFile
|
|
361
|
-
});
|
|
362
651
|
}
|
|
363
|
-
|
|
364
|
-
//TODO do we actually need to implement this? Figure out how to handle img paths
|
|
365
|
-
// let genericFile = this.files[srcPath] = <any>{
|
|
366
|
-
// srcPath: srcPath,
|
|
367
|
-
// pkgPath: pkgPath,
|
|
368
|
-
// wasProcessed: true
|
|
369
|
-
// } as File;
|
|
370
|
-
// file = <any>genericFile;
|
|
371
|
-
}
|
|
372
|
-
return file;
|
|
652
|
+
return primaryFile;
|
|
373
653
|
});
|
|
654
|
+
return file;
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Given a srcPath, a destPath, or both, resolve whichever is missing, relative to rootDir.
|
|
658
|
+
* @param fileParam an object representing file paths
|
|
659
|
+
* @param rootDir must be a pre-normalized path
|
|
660
|
+
*/
|
|
661
|
+
getPaths(fileParam, rootDir) {
|
|
662
|
+
let srcPath;
|
|
663
|
+
let destPath;
|
|
664
|
+
assert.ok(fileParam, 'fileParam is required');
|
|
665
|
+
//lift the path vars from the incoming param
|
|
666
|
+
if (typeof fileParam === 'string') {
|
|
667
|
+
fileParam = this.removePkgPrefix(fileParam);
|
|
668
|
+
srcPath = (0, util_1.standardizePath) `${path.resolve(rootDir, fileParam)}`;
|
|
669
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
670
|
+
}
|
|
671
|
+
else {
|
|
672
|
+
let param = fileParam;
|
|
673
|
+
if (param.src) {
|
|
674
|
+
srcPath = (0, util_1.standardizePath) `${param.src}`;
|
|
675
|
+
}
|
|
676
|
+
if (param.srcPath) {
|
|
677
|
+
srcPath = (0, util_1.standardizePath) `${param.srcPath}`;
|
|
678
|
+
}
|
|
679
|
+
if (param.dest) {
|
|
680
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.dest)}`;
|
|
681
|
+
}
|
|
682
|
+
if (param.pkgPath) {
|
|
683
|
+
destPath = (0, util_1.standardizePath) `${this.removePkgPrefix(param.pkgPath)}`;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
//if there's no srcPath, use the destPath to build an absolute srcPath
|
|
687
|
+
if (!srcPath) {
|
|
688
|
+
srcPath = (0, util_1.standardizePath) `${rootDir}/${destPath}`;
|
|
689
|
+
}
|
|
690
|
+
//coerce srcPath to an absolute path
|
|
691
|
+
if (!path.isAbsolute(srcPath)) {
|
|
692
|
+
srcPath = util_1.util.standardizePath(srcPath);
|
|
693
|
+
}
|
|
694
|
+
//if destPath isn't set, compute it from the other paths
|
|
695
|
+
if (!destPath) {
|
|
696
|
+
destPath = (0, util_1.standardizePath) `${util_1.util.replaceCaseInsensitive(srcPath, rootDir, '')}`;
|
|
697
|
+
}
|
|
698
|
+
assert.ok(srcPath, 'fileEntry.src is required');
|
|
699
|
+
assert.ok(destPath, 'fileEntry.dest is required');
|
|
700
|
+
return {
|
|
701
|
+
srcPath: srcPath,
|
|
702
|
+
//remove leading slash
|
|
703
|
+
destPath: destPath.replace(/^[\/\\]+/, '')
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Remove any leading `pkg:/` found in the path
|
|
708
|
+
*/
|
|
709
|
+
removePkgPrefix(path) {
|
|
710
|
+
return path.replace(/^pkg:\//i, '');
|
|
711
|
+
}
|
|
712
|
+
/**
|
|
713
|
+
* Is this file a .brs file found somewhere within the `pkg:/source/` folder?
|
|
714
|
+
*/
|
|
715
|
+
isSourceBrsFile(file) {
|
|
716
|
+
return !!/^(pkg:\/)?source[\/\\]/.exec(file.destPath);
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* Is this file a .brs file found somewhere within the `pkg:/source/` folder?
|
|
720
|
+
*/
|
|
721
|
+
isComponentsXmlFile(file) {
|
|
722
|
+
return (0, reflection_1.isXmlFile)(file) && !!/^(pkg:\/)?components[\/\\]/.exec(file.destPath);
|
|
374
723
|
}
|
|
375
724
|
/**
|
|
376
725
|
* Ensure source scope is created.
|
|
@@ -381,238 +730,574 @@ class Program {
|
|
|
381
730
|
const sourceScope = new Scope_1.Scope('source', this, 'scope:source');
|
|
382
731
|
sourceScope.attachDependencyGraph(this.dependencyGraph);
|
|
383
732
|
this.addScope(sourceScope);
|
|
733
|
+
this.plugins.emit('afterProvideScope', {
|
|
734
|
+
program: this,
|
|
735
|
+
scope: sourceScope
|
|
736
|
+
});
|
|
384
737
|
}
|
|
385
738
|
}
|
|
386
739
|
/**
|
|
387
740
|
* Remove a set of files from the program
|
|
388
|
-
* @param srcPaths
|
|
741
|
+
* @param srcPaths can be an array of srcPath or destPath strings
|
|
742
|
+
* @param normalizePath should this function repair and standardize the filePaths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
|
|
389
743
|
*/
|
|
390
|
-
removeFiles(srcPaths) {
|
|
744
|
+
removeFiles(srcPaths, normalizePath = true) {
|
|
391
745
|
for (let srcPath of srcPaths) {
|
|
392
|
-
this.removeFile(srcPath);
|
|
746
|
+
this.removeFile(srcPath, normalizePath);
|
|
393
747
|
}
|
|
394
748
|
}
|
|
395
749
|
/**
|
|
396
750
|
* Remove a file from the program
|
|
397
|
-
* @param filePath can be a srcPath, a
|
|
751
|
+
* @param filePath can be a srcPath, a destPath, or a destPath with leading `pkg:/`
|
|
398
752
|
* @param normalizePath should this function repair and standardize the path? Passing false should have a performance boost if you can guarantee your path is already sanitized
|
|
399
|
-
|
|
400
753
|
*/
|
|
401
|
-
removeFile(filePath, normalizePath = true) {
|
|
754
|
+
removeFile(filePath, normalizePath = true, keepSymbolInformation = false) {
|
|
755
|
+
var _a, _b, _c, _d;
|
|
402
756
|
this.logger.debug('Program.removeFile()', filePath);
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
757
|
+
const paths = this.getPaths(filePath, this.options.rootDir);
|
|
758
|
+
//there can be one or more File entries for a single srcPath, so get all of them and remove them all
|
|
759
|
+
const files = (_b = this.fileClusters.get((_a = paths.srcPath) === null || _a === void 0 ? void 0 : _a.toLowerCase())) !== null && _b !== void 0 ? _b : [this.getFile(filePath, normalizePath)];
|
|
760
|
+
for (const file of files) {
|
|
761
|
+
//if a file has already been removed, nothing more needs to be done here
|
|
762
|
+
if (!file || !this.hasFile(file.srcPath)) {
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
this.diagnostics.clearForFile(file.srcPath);
|
|
766
|
+
const event = { file: file, program: this };
|
|
767
|
+
this.plugins.emit('beforeRemoveFile', event);
|
|
409
768
|
//if there is a scope named the same as this file's path, remove it (i.e. xml scopes)
|
|
410
|
-
let scope = this.scopes[file.
|
|
769
|
+
let scope = this.scopes[file.destPath];
|
|
411
770
|
if (scope) {
|
|
412
|
-
this.
|
|
771
|
+
this.logger.debug('Removing associated scope', scope.name);
|
|
772
|
+
const scopeRemoveEvent = {
|
|
413
773
|
program: this,
|
|
414
774
|
scope: scope
|
|
415
|
-
}
|
|
775
|
+
};
|
|
776
|
+
this.plugins.emit('beforeRemoveScope', scopeRemoveEvent);
|
|
777
|
+
this.plugins.emit('removeScope', scopeRemoveEvent);
|
|
416
778
|
scope.dispose();
|
|
417
779
|
//notify dependencies of this scope that it has been removed
|
|
418
780
|
this.dependencyGraph.remove(scope.dependencyGraphKey);
|
|
419
|
-
|
|
420
|
-
this.plugins.emit('
|
|
421
|
-
program: this,
|
|
422
|
-
scope: scope
|
|
423
|
-
});
|
|
781
|
+
this.removeScope(this.scopes[file.destPath]);
|
|
782
|
+
this.plugins.emit('afterRemoveScope', scopeRemoveEvent);
|
|
424
783
|
}
|
|
425
784
|
//remove the file from the program
|
|
426
785
|
this.unassignFile(file);
|
|
427
786
|
this.dependencyGraph.remove(file.dependencyGraphKey);
|
|
428
787
|
//if this is a pkg:/source file, notify the `source` scope that it has changed
|
|
429
|
-
if (
|
|
788
|
+
if (this.isSourceBrsFile(file)) {
|
|
430
789
|
this.dependencyGraph.removeDependency('scope:source', file.dependencyGraphKey);
|
|
431
790
|
}
|
|
791
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
792
|
+
this.logger.debug('Removing file symbol info', file.srcPath);
|
|
793
|
+
if (!keepSymbolInformation) {
|
|
794
|
+
this.fileSymbolInformation.delete(file.pkgPath);
|
|
795
|
+
}
|
|
796
|
+
this.crossScopeValidation.clearResolutionsForFile(file);
|
|
797
|
+
}
|
|
798
|
+
this.diagnostics.clearForFile(file.srcPath);
|
|
432
799
|
//if this is a component, remove it from our components map
|
|
433
|
-
if (reflection_1.isXmlFile(file)) {
|
|
800
|
+
if ((0, reflection_1.isXmlFile)(file)) {
|
|
801
|
+
this.logger.debug('Unregistering component', file.srcPath);
|
|
434
802
|
this.unregisterComponent(file);
|
|
435
803
|
}
|
|
436
|
-
this.
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
804
|
+
this.logger.debug('Disposing file', file.srcPath);
|
|
805
|
+
//dispose any disposable things on the file
|
|
806
|
+
for (const disposable of (_c = file === null || file === void 0 ? void 0 : file.disposables) !== null && _c !== void 0 ? _c : []) {
|
|
807
|
+
disposable();
|
|
808
|
+
}
|
|
809
|
+
//dispose file
|
|
810
|
+
(_d = file === null || file === void 0 ? void 0 : file.dispose) === null || _d === void 0 ? void 0 : _d.call(file);
|
|
811
|
+
this.plugins.emit('afterRemoveFile', event);
|
|
440
812
|
}
|
|
441
813
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
814
|
+
validate(options) {
|
|
815
|
+
var _a;
|
|
816
|
+
const validationRunId = this.validationRunSequence++;
|
|
817
|
+
let previousValidationPromise = this.validatePromise;
|
|
818
|
+
const deferred = new deferred_1.Deferred();
|
|
819
|
+
if (options === null || options === void 0 ? void 0 : options.async) {
|
|
820
|
+
//we're async, so create a new promise chain to resolve after this validation is done
|
|
821
|
+
this.validatePromise = Promise.resolve(previousValidationPromise).then(() => {
|
|
822
|
+
return deferred.promise;
|
|
823
|
+
});
|
|
824
|
+
//we are not async but there's a pending promise, then we cannot run this validation
|
|
450
825
|
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
const file = this.files[key];
|
|
454
|
-
const lowerSrcPath = file.srcPath.toLowerCase();
|
|
455
|
-
//if the file path starts with the parent path and the file path does not exactly match the folder path
|
|
456
|
-
if (lowerSrcPath.toLowerCase().startsWith(lowerFolderSrcPath) && lowerSrcPath !== lowerFolderSrcPath) {
|
|
457
|
-
this.removeFile(file.srcPath, false);
|
|
458
|
-
}
|
|
826
|
+
else if (previousValidationPromise !== undefined) {
|
|
827
|
+
throw new Error('Cannot run synchronous validation while an async validation is in progress');
|
|
459
828
|
}
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
829
|
+
let beforeValidateProgramWasEmitted = false;
|
|
830
|
+
const brsFilesValidated = this.validationDetails.brsFilesValidated;
|
|
831
|
+
const xmlFilesValidated = this.validationDetails.xmlFilesValidated;
|
|
832
|
+
const changedSymbols = this.validationDetails.changedSymbols;
|
|
833
|
+
const changedComponentTypes = this.validationDetails.changedComponentTypes;
|
|
834
|
+
const scopesToValidate = this.validationDetails.scopesToValidate;
|
|
835
|
+
const filesToBeValidatedInScopeContext = this.validationDetails.filesToBeValidatedInScopeContext;
|
|
836
|
+
//validate every file
|
|
837
|
+
let logValidateEnd = (status) => { };
|
|
838
|
+
//will be populated later on during the correspnding sequencer event
|
|
839
|
+
let filesToProcess;
|
|
840
|
+
const sequencer = new Sequencer_1.Sequencer({
|
|
841
|
+
name: 'program.validate',
|
|
842
|
+
cancellationToken: (_a = options === null || options === void 0 ? void 0 : options.cancellationToken) !== null && _a !== void 0 ? _a : new vscode_languageserver_1.CancellationTokenSource().token,
|
|
843
|
+
minSyncDuration: this.validationMinSyncDuration
|
|
844
|
+
});
|
|
845
|
+
//this sequencer allows us to run in both sync and async mode, depending on whether options.async is enabled.
|
|
846
|
+
//We use this to prevent starving the CPU during long validate cycles when running in a language server context
|
|
847
|
+
sequencer
|
|
848
|
+
.once('wait for previous run', () => {
|
|
849
|
+
//if running in async mode, return the previous validation promise to ensure we're only running one at a time
|
|
850
|
+
if (options === null || options === void 0 ? void 0 : options.async) {
|
|
851
|
+
return previousValidationPromise;
|
|
852
|
+
}
|
|
853
|
+
})
|
|
854
|
+
.once('before and on programValidate', () => {
|
|
855
|
+
logValidateEnd = this.logger.timeStart(logging_1.LogLevel.log, `Validating project${this.logger.logLevel > logging_1.LogLevel.log ? ` (run ${validationRunId})` : ''}`);
|
|
856
|
+
this.diagnostics.clearForTag(ProgramValidator_1.ProgramValidatorDiagnosticsTag);
|
|
857
|
+
this.plugins.emit('beforeValidateProgram', {
|
|
858
|
+
program: this
|
|
859
|
+
});
|
|
860
|
+
beforeValidateProgramWasEmitted = true;
|
|
861
|
+
this.plugins.emit('validateProgram', {
|
|
470
862
|
program: this
|
|
471
863
|
});
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
864
|
+
})
|
|
865
|
+
.once('get files to be validated', () => {
|
|
866
|
+
filesToProcess = Object.values(this.files).sort((0, thenby_1.firstBy)(x => x.srcPath)).filter(x => !x.isValidated);
|
|
867
|
+
for (const file of filesToProcess) {
|
|
868
|
+
filesToBeValidatedInScopeContext.add(file);
|
|
869
|
+
}
|
|
870
|
+
})
|
|
871
|
+
.once('add component reference types', () => {
|
|
872
|
+
// Create reference component types for any component that changes
|
|
873
|
+
for (let [componentKey, componentName] of this.componentSymbolsToUpdate.entries()) {
|
|
874
|
+
this.addComponentReferenceType(componentKey, componentName);
|
|
875
|
+
}
|
|
876
|
+
})
|
|
877
|
+
.forEach('beforeValidateFile', () => filesToProcess, (file) => {
|
|
878
|
+
//run the beforeFilevalidate event for every unvalidated file
|
|
879
|
+
this.plugins.emit('beforeValidateFile', {
|
|
880
|
+
program: this,
|
|
881
|
+
file: file
|
|
882
|
+
});
|
|
883
|
+
})
|
|
884
|
+
.forEach('validateFile', () => filesToProcess, (file) => {
|
|
885
|
+
//run the validateFile event for every unvalidated file
|
|
886
|
+
this.plugins.emit('validateFile', {
|
|
887
|
+
program: this,
|
|
888
|
+
file: file
|
|
889
|
+
});
|
|
890
|
+
file.isValidated = true;
|
|
891
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
892
|
+
brsFilesValidated.push(file);
|
|
893
|
+
}
|
|
894
|
+
else if ((0, reflection_1.isXmlFile)(file)) {
|
|
895
|
+
xmlFilesValidated.push(file);
|
|
896
|
+
}
|
|
897
|
+
})
|
|
898
|
+
.forEach('afterValidateFile', () => filesToProcess, (file) => {
|
|
899
|
+
//run the validateFile event for every unvalidated file
|
|
900
|
+
this.plugins.emit('afterValidateFile', {
|
|
901
|
+
program: this,
|
|
902
|
+
file: file
|
|
903
|
+
});
|
|
904
|
+
})
|
|
905
|
+
.forEach('do deferred component creation', () => [...brsFilesValidated, ...xmlFilesValidated], (file) => {
|
|
906
|
+
if ((0, reflection_1.isXmlFile)(file)) {
|
|
907
|
+
this.addDeferredComponentTypeSymbolCreation(file);
|
|
908
|
+
}
|
|
909
|
+
else if ((0, reflection_1.isBrsFile)(file)) {
|
|
910
|
+
const fileHasChanges = file.providedSymbols.changes.get(1 /* SymbolTypeFlag.runtime */).size > 0 || file.providedSymbols.changes.get(2 /* SymbolTypeFlag.typetime */).size > 0;
|
|
911
|
+
if (fileHasChanges) {
|
|
912
|
+
for (const scope of this.getScopesForFile(file)) {
|
|
913
|
+
if ((0, reflection_1.isXmlScope)(scope) && this.doesXmlFileRequireProvidedSymbols(scope.xmlFile, file.providedSymbols.changes)) {
|
|
914
|
+
this.addDeferredComponentTypeSymbolCreation(scope.xmlFile);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
479
917
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
(
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
918
|
+
}
|
|
919
|
+
})
|
|
920
|
+
.once('build component types for any component that changes', () => {
|
|
921
|
+
this.logger.time(logging_1.LogLevel.info, ['Build component types'], () => {
|
|
922
|
+
this.logger.debug(`Component Symbols to update:`, [...this.componentSymbolsToUpdate.entries()].sort());
|
|
923
|
+
this.lastValidationInfo.componentsRebuilt = new Set();
|
|
924
|
+
for (let [componentKey, componentName] of this.componentSymbolsToUpdate.entries()) {
|
|
925
|
+
this.lastValidationInfo.componentsRebuilt.add(componentName === null || componentName === void 0 ? void 0 : componentName.toLowerCase());
|
|
926
|
+
if (this.updateComponentSymbolInGlobalScope(componentKey, componentName)) {
|
|
927
|
+
changedComponentTypes.push(util_1.util.getSgNodeTypeName(componentName).toLowerCase());
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
this.componentSymbolsToUpdate.clear();
|
|
931
|
+
});
|
|
932
|
+
})
|
|
933
|
+
.once('track and update type-time and runtime symbol dependencies and changes', () => {
|
|
934
|
+
var _a, _b, _c, _d;
|
|
935
|
+
const changedSymbolsMapArr = (_a = [...brsFilesValidated, ...xmlFilesValidated]) === null || _a === void 0 ? void 0 : _a.map(f => {
|
|
936
|
+
if ((0, reflection_1.isBrsFile)(f)) {
|
|
937
|
+
return f.providedSymbols.changes;
|
|
938
|
+
}
|
|
939
|
+
return null;
|
|
940
|
+
}).filter(x => x);
|
|
941
|
+
// update the map of typetime dependencies
|
|
942
|
+
for (const file of brsFilesValidated) {
|
|
943
|
+
for (const [symbolName, provided] of file.providedSymbols.symbolMap.get(2 /* SymbolTypeFlag.typetime */).entries()) {
|
|
944
|
+
// clear existing dependencies
|
|
945
|
+
for (const values of this.symbolDependencies.values()) {
|
|
946
|
+
values.delete(symbolName);
|
|
947
|
+
}
|
|
948
|
+
// map types to the set of types that depend upon them
|
|
949
|
+
for (const dependentSymbol of (_c = (_b = provided.requiredSymbolNames) === null || _b === void 0 ? void 0 : _b.values()) !== null && _c !== void 0 ? _c : []) {
|
|
950
|
+
const dependentSymbolLower = dependentSymbol.toLowerCase();
|
|
951
|
+
if (!this.symbolDependencies.has(dependentSymbolLower)) {
|
|
952
|
+
this.symbolDependencies.set(dependentSymbolLower, new Set());
|
|
953
|
+
}
|
|
954
|
+
const symbolsDependentUpon = this.symbolDependencies.get(dependentSymbolLower);
|
|
955
|
+
symbolsDependentUpon.add(symbolName);
|
|
956
|
+
}
|
|
493
957
|
}
|
|
494
958
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
959
|
+
for (const flag of [1 /* SymbolTypeFlag.runtime */, 2 /* SymbolTypeFlag.typetime */]) {
|
|
960
|
+
const changedSymbolsSetArr = changedSymbolsMapArr.map(symMap => symMap.get(flag));
|
|
961
|
+
const changedSymbolSet = new Set();
|
|
962
|
+
for (const changeSet of changedSymbolsSetArr) {
|
|
963
|
+
for (const change of changeSet) {
|
|
964
|
+
changedSymbolSet.add(change);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
if (!changedSymbols.has(flag)) {
|
|
968
|
+
changedSymbols.set(flag, changedSymbolSet);
|
|
969
|
+
}
|
|
970
|
+
else {
|
|
971
|
+
changedSymbols.set(flag, new Set([...changedSymbols.get(flag), ...changedSymbolSet]));
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
// update changed symbol set with any changed component
|
|
975
|
+
for (const changedComponentType of changedComponentTypes) {
|
|
976
|
+
changedSymbols.get(2 /* SymbolTypeFlag.typetime */).add(changedComponentType);
|
|
977
|
+
}
|
|
978
|
+
// Add any additional types that depend on a changed type
|
|
979
|
+
// as each iteration of the loop might add new types, need to keep checking until nothing new is added
|
|
980
|
+
const dependentTypesChanged = new Set();
|
|
981
|
+
let foundDependentTypes = false;
|
|
982
|
+
const changedTypeSymbols = changedSymbols.get(2 /* SymbolTypeFlag.typetime */);
|
|
983
|
+
do {
|
|
984
|
+
foundDependentTypes = false;
|
|
985
|
+
const allChangedTypesSofar = [...Array.from(changedTypeSymbols), ...Array.from(dependentTypesChanged)];
|
|
986
|
+
for (const changedSymbol of allChangedTypesSofar) {
|
|
987
|
+
const symbolsDependentUponChangedSymbol = (_d = this.symbolDependencies.get(changedSymbol)) !== null && _d !== void 0 ? _d : [];
|
|
988
|
+
for (const symbolName of symbolsDependentUponChangedSymbol) {
|
|
989
|
+
if (!changedTypeSymbols.has(symbolName) && !dependentTypesChanged.has(symbolName)) {
|
|
990
|
+
foundDependentTypes = true;
|
|
991
|
+
dependentTypesChanged.add(symbolName);
|
|
992
|
+
}
|
|
509
993
|
}
|
|
510
994
|
}
|
|
995
|
+
} while (foundDependentTypes);
|
|
996
|
+
changedSymbols.set(2 /* SymbolTypeFlag.typetime */, new Set([...changedSymbols.get(2 /* SymbolTypeFlag.typetime */), ...changedTypeSymbols, ...dependentTypesChanged]));
|
|
997
|
+
this.lastValidationInfo.brsFilesSrcPath = new Set(this.validationDetails.brsFilesValidated.map(f => { var _a, _b; return (_b = (_a = f.srcPath) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : ''; }));
|
|
998
|
+
this.lastValidationInfo.xmlFilesSrcPath = new Set(this.validationDetails.xmlFilesValidated.map(f => { var _a, _b; return (_b = (_a = f.srcPath) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : ''; }));
|
|
999
|
+
// can reset filesValidatedList, because they are no longer needed
|
|
1000
|
+
this.validationDetails.brsFilesValidated = [];
|
|
1001
|
+
this.validationDetails.xmlFilesValidated = [];
|
|
1002
|
+
})
|
|
1003
|
+
.once('tracks changed symbols and prepares files and scopes for validation', () => {
|
|
1004
|
+
if (this.options.logLevel === logging_1.LogLevel.debug) {
|
|
1005
|
+
const changedRuntime = Array.from(changedSymbols.get(1 /* SymbolTypeFlag.runtime */)).sort();
|
|
1006
|
+
this.logger.debug('Changed Symbols (runTime):', changedRuntime.join(', '));
|
|
1007
|
+
const changedTypetime = Array.from(changedSymbols.get(2 /* SymbolTypeFlag.typetime */)).sort();
|
|
1008
|
+
this.logger.debug('Changed Symbols (typeTime):', changedTypetime.join(', '));
|
|
1009
|
+
}
|
|
1010
|
+
const didComponentChange = changedComponentTypes.length > 0;
|
|
1011
|
+
const didProvidedSymbolChange = changedSymbols.get(1 /* SymbolTypeFlag.runtime */).size > 0 || changedSymbols.get(2 /* SymbolTypeFlag.typetime */).size > 0;
|
|
1012
|
+
const scopesToCheck = this.getScopesForCrossScopeValidation(didComponentChange, didProvidedSymbolChange);
|
|
1013
|
+
this.crossScopeValidation.buildComponentsMap();
|
|
1014
|
+
this.logger.time(logging_1.LogLevel.info, ['addDiagnosticsForScopes'], () => {
|
|
1015
|
+
this.crossScopeValidation.addDiagnosticsForScopes(scopesToCheck);
|
|
511
1016
|
});
|
|
512
|
-
this.
|
|
513
|
-
|
|
514
|
-
|
|
1017
|
+
const filesToRevalidate = this.crossScopeValidation.getFilesRequiringChangedSymbol(scopesToCheck, changedSymbols);
|
|
1018
|
+
for (const file of filesToRevalidate) {
|
|
1019
|
+
filesToBeValidatedInScopeContext.add(file);
|
|
1020
|
+
}
|
|
1021
|
+
this.currentScopeValidationOptions = {
|
|
1022
|
+
filesToBeValidatedInScopeContext: filesToBeValidatedInScopeContext,
|
|
1023
|
+
changedSymbols: changedSymbols,
|
|
1024
|
+
changedFiles: Array.from(filesToBeValidatedInScopeContext),
|
|
1025
|
+
initialValidation: this.isFirstValidation
|
|
1026
|
+
};
|
|
1027
|
+
//can reset changedComponent types
|
|
1028
|
+
this.validationDetails.changedComponentTypes = [];
|
|
1029
|
+
})
|
|
1030
|
+
.forEach('invalidate affected scopes', () => filesToBeValidatedInScopeContext, (file) => {
|
|
1031
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
1032
|
+
file.validationSegmenter.unValidateAllSegments();
|
|
1033
|
+
for (const scope of this.getScopesForFile(file)) {
|
|
1034
|
+
scope.invalidate();
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
})
|
|
1038
|
+
.once('checking scopes to validate', () => {
|
|
1039
|
+
//sort the scope names so we get consistent results
|
|
1040
|
+
for (const scopeName of this.getSortedScopeNames()) {
|
|
1041
|
+
let scope = this.scopes[scopeName];
|
|
1042
|
+
if (scope.shouldValidate(this.currentScopeValidationOptions)) {
|
|
1043
|
+
scopesToValidate.push(scope);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
this.lastValidationInfo.scopeNames = new Set(scopesToValidate.map(s => { var _a, _b; return (_b = (_a = s.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : ''; }));
|
|
1047
|
+
})
|
|
1048
|
+
.forEach('beforeScopeValidate', () => scopesToValidate, (scope) => {
|
|
1049
|
+
this.plugins.emit('beforeValidateScope', {
|
|
1050
|
+
program: this,
|
|
1051
|
+
scope: scope
|
|
1052
|
+
});
|
|
1053
|
+
})
|
|
1054
|
+
.forEach('validate scope', () => scopesToValidate, (scope) => {
|
|
1055
|
+
scope.validate(this.currentScopeValidationOptions);
|
|
1056
|
+
})
|
|
1057
|
+
.forEach('afterValidateScope', () => scopesToValidate, (scope) => {
|
|
1058
|
+
this.plugins.emit('afterValidateScope', {
|
|
1059
|
+
program: this,
|
|
1060
|
+
scope: scope
|
|
515
1061
|
});
|
|
1062
|
+
})
|
|
1063
|
+
.once('detect duplicate component names', () => {
|
|
1064
|
+
this.detectDuplicateComponentNames();
|
|
1065
|
+
this.isFirstValidation = false;
|
|
1066
|
+
// can reset other validation details
|
|
1067
|
+
this.validationDetails.changedSymbols = new Map();
|
|
1068
|
+
this.validationDetails.scopesToValidate = [];
|
|
1069
|
+
this.validationDetails.filesToBeValidatedInScopeContext = new Set();
|
|
1070
|
+
})
|
|
1071
|
+
.onCancel(() => {
|
|
1072
|
+
logValidateEnd('cancelled');
|
|
1073
|
+
})
|
|
1074
|
+
.onSuccess(() => {
|
|
1075
|
+
logValidateEnd();
|
|
1076
|
+
})
|
|
1077
|
+
.onComplete(() => {
|
|
1078
|
+
var _a, _b;
|
|
1079
|
+
//if we emitted the beforeValidateProgram hook, emit the afterValidateProgram hook as well
|
|
1080
|
+
if (beforeValidateProgramWasEmitted) {
|
|
1081
|
+
const wasCancelled = (_b = (_a = options === null || options === void 0 ? void 0 : options.cancellationToken) === null || _a === void 0 ? void 0 : _a.isCancellationRequested) !== null && _b !== void 0 ? _b : false;
|
|
1082
|
+
this.plugins.emit('afterValidateProgram', {
|
|
1083
|
+
program: this,
|
|
1084
|
+
wasCancelled: wasCancelled
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
//log all the sequencer timing metrics if `info` logging is enabled
|
|
1088
|
+
this.logger.info(sequencer.formatMetrics({
|
|
1089
|
+
header: 'Program.validate metrics:',
|
|
1090
|
+
//only include loop iterations if `debug` logging is enabled
|
|
1091
|
+
includeLoopIterations: this.logger.isLogLevelEnabled(logging_1.LogLevel.debug)
|
|
1092
|
+
}));
|
|
1093
|
+
//regardless of the success of the validation, mark this run as complete
|
|
1094
|
+
deferred.resolve();
|
|
1095
|
+
//clear the validatePromise which means we're no longer running a validation
|
|
1096
|
+
this.validatePromise = undefined;
|
|
516
1097
|
});
|
|
1098
|
+
//run the sequencer in async mode if enabled
|
|
1099
|
+
if (options === null || options === void 0 ? void 0 : options.async) {
|
|
1100
|
+
return sequencer.run();
|
|
1101
|
+
//run the sequencer in sync mode
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
return sequencer.runSync();
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
getScopesForCrossScopeValidation(someComponentTypeChanged, didProvidedSymbolChange) {
|
|
1108
|
+
const scopesForCrossScopeValidation = [];
|
|
1109
|
+
for (let scopeName of this.getSortedScopeNames()) {
|
|
1110
|
+
let scope = this.scopes[scopeName];
|
|
1111
|
+
if (this.globalScope === scope) {
|
|
1112
|
+
continue;
|
|
1113
|
+
}
|
|
1114
|
+
if (someComponentTypeChanged) {
|
|
1115
|
+
scopesForCrossScopeValidation.push(scope);
|
|
1116
|
+
}
|
|
1117
|
+
if (didProvidedSymbolChange && !scope.isValidated) {
|
|
1118
|
+
scopesForCrossScopeValidation.push(scope);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
return scopesForCrossScopeValidation;
|
|
1122
|
+
}
|
|
1123
|
+
doesXmlFileRequireProvidedSymbols(file, providedSymbolsByFlag) {
|
|
1124
|
+
for (const required of file.requiredSymbols) {
|
|
1125
|
+
const symbolNameLower = required.name.toLowerCase();
|
|
1126
|
+
const requiredSymbolIsProvided = providedSymbolsByFlag.get(required.flags).has(symbolNameLower);
|
|
1127
|
+
if (requiredSymbolIsProvided) {
|
|
1128
|
+
return true;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return false;
|
|
517
1132
|
}
|
|
518
1133
|
/**
|
|
519
1134
|
* Flag all duplicate component names
|
|
520
1135
|
*/
|
|
521
1136
|
detectDuplicateComponentNames() {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
const file = this.files[key];
|
|
1137
|
+
const componentsByName = Object.keys(this.files).reduce((map, filePath) => {
|
|
1138
|
+
var _a;
|
|
1139
|
+
const file = this.files[filePath];
|
|
526
1140
|
//if this is an XmlFile, and it has a valid `componentName` property
|
|
527
|
-
if (reflection_1.isXmlFile(file)) {
|
|
528
|
-
|
|
529
|
-
if (
|
|
530
|
-
|
|
531
|
-
componentsByName.set(componentNameLower, [file]);
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
componentsByName.get(componentNameLower).push(file);
|
|
535
|
-
}
|
|
1141
|
+
if ((0, reflection_1.isXmlFile)(file) && ((_a = file.componentName) === null || _a === void 0 ? void 0 : _a.text)) {
|
|
1142
|
+
let lowerName = file.componentName.text.toLowerCase();
|
|
1143
|
+
if (!map[lowerName]) {
|
|
1144
|
+
map[lowerName] = [];
|
|
536
1145
|
}
|
|
1146
|
+
map[lowerName].push(file);
|
|
537
1147
|
}
|
|
538
|
-
|
|
539
|
-
|
|
1148
|
+
return map;
|
|
1149
|
+
}, {});
|
|
1150
|
+
for (let name in componentsByName) {
|
|
1151
|
+
const xmlFiles = componentsByName[name];
|
|
540
1152
|
//add diagnostics for every duplicate component with this name
|
|
541
1153
|
if (xmlFiles.length > 1) {
|
|
542
1154
|
for (let xmlFile of xmlFiles) {
|
|
543
1155
|
const { componentName } = xmlFile;
|
|
544
|
-
this.diagnostics.
|
|
1156
|
+
this.diagnostics.register(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateComponentName(componentName.text)), { location: xmlFile.componentName.location, relatedInformation: xmlFiles.filter(x => x !== xmlFile).map(x => {
|
|
545
1157
|
return {
|
|
546
|
-
location:
|
|
1158
|
+
location: x.componentName.location,
|
|
547
1159
|
message: 'Also defined here'
|
|
548
1160
|
};
|
|
549
|
-
}) }));
|
|
1161
|
+
}) }), { tags: [ProgramValidator_1.ProgramValidatorDiagnosticsTag] });
|
|
550
1162
|
}
|
|
551
1163
|
}
|
|
552
1164
|
}
|
|
553
1165
|
}
|
|
554
1166
|
/**
|
|
555
|
-
*
|
|
1167
|
+
* Get the files for a list of filePaths
|
|
1168
|
+
* @param filePaths can be an array of srcPath or a destPath strings
|
|
1169
|
+
* @param normalizePath should this function repair and standardize the paths? Passing false should have a performance boost if you can guarantee your paths are already sanitized
|
|
556
1170
|
*/
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
return false;
|
|
1171
|
+
getFiles(filePaths, normalizePath = true) {
|
|
1172
|
+
return filePaths
|
|
1173
|
+
.map(filePath => this.getFile(filePath, normalizePath))
|
|
1174
|
+
.filter(file => file !== undefined);
|
|
564
1175
|
}
|
|
565
1176
|
/**
|
|
566
1177
|
* Get the file at the given path
|
|
567
|
-
* @param filePath can be a srcPath
|
|
1178
|
+
* @param filePath can be a srcPath or a destPath
|
|
568
1179
|
* @param normalizePath should this function repair and standardize the path? Passing false should have a performance boost if you can guarantee your path is already sanitized
|
|
569
1180
|
*/
|
|
570
1181
|
getFile(filePath, normalizePath = true) {
|
|
1182
|
+
if (this.getFilePathCache.has(filePath)) {
|
|
1183
|
+
const cachedFilePath = this.getFilePathCache.get(filePath);
|
|
1184
|
+
if (cachedFilePath.isDestMap) {
|
|
1185
|
+
return this.destMap.get(cachedFilePath.path);
|
|
1186
|
+
}
|
|
1187
|
+
return this.files[cachedFilePath.path];
|
|
1188
|
+
}
|
|
571
1189
|
if (typeof filePath !== 'string') {
|
|
572
1190
|
return undefined;
|
|
1191
|
+
//is the path absolute (or the `virtual:` prefix)
|
|
1192
|
+
}
|
|
1193
|
+
else if (/^(?:(?:virtual:[\/\\])|(?:\w:)|(?:[\/\\]))/gmi.exec(filePath)) {
|
|
1194
|
+
const standardizedPath = (normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase();
|
|
1195
|
+
this.getFilePathCache.set(filePath, { path: standardizedPath });
|
|
1196
|
+
return this.files[standardizedPath];
|
|
573
1197
|
}
|
|
574
|
-
else if (
|
|
575
|
-
|
|
1198
|
+
else if (util_1.util.isUriLike(filePath)) {
|
|
1199
|
+
const path = vscode_uri_1.URI.parse(filePath).fsPath;
|
|
1200
|
+
const standardizedPath = (normalizePath ? util_1.util.standardizePath(path) : path).toLowerCase();
|
|
1201
|
+
this.getFilePathCache.set(filePath, { path: standardizedPath });
|
|
1202
|
+
return this.files[standardizedPath];
|
|
576
1203
|
}
|
|
577
1204
|
else {
|
|
578
|
-
|
|
1205
|
+
const standardizedPath = (normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase();
|
|
1206
|
+
this.getFilePathCache.set(filePath, { path: standardizedPath, isDestMap: true });
|
|
1207
|
+
return this.destMap.get(standardizedPath);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Gets a sorted list of all scopeNames, always beginning with "global", "source", then any others in alphabetical order
|
|
1212
|
+
*/
|
|
1213
|
+
getSortedScopeNames() {
|
|
1214
|
+
if (!this.sortedScopeNames) {
|
|
1215
|
+
this.sortedScopeNames = Object.keys(this.scopes).sort((a, b) => {
|
|
1216
|
+
if (a === 'global') {
|
|
1217
|
+
return -1;
|
|
1218
|
+
}
|
|
1219
|
+
else if (b === 'global') {
|
|
1220
|
+
return 1;
|
|
1221
|
+
}
|
|
1222
|
+
if (a === 'source') {
|
|
1223
|
+
return -1;
|
|
1224
|
+
}
|
|
1225
|
+
else if (b === 'source') {
|
|
1226
|
+
return 1;
|
|
1227
|
+
}
|
|
1228
|
+
if (a < b) {
|
|
1229
|
+
return -1;
|
|
1230
|
+
}
|
|
1231
|
+
else if (b < a) {
|
|
1232
|
+
return 1;
|
|
1233
|
+
}
|
|
1234
|
+
return 0;
|
|
1235
|
+
});
|
|
579
1236
|
}
|
|
1237
|
+
return this.sortedScopeNames;
|
|
580
1238
|
}
|
|
581
1239
|
/**
|
|
582
1240
|
* Get a list of all scopes the file is loaded into
|
|
583
|
-
* @param file
|
|
1241
|
+
* @param file the file
|
|
584
1242
|
*/
|
|
585
1243
|
getScopesForFile(file) {
|
|
1244
|
+
const resolvedFile = typeof file === 'string' ? this.getFile(file) : file;
|
|
586
1245
|
let result = [];
|
|
587
|
-
|
|
1246
|
+
if (resolvedFile) {
|
|
1247
|
+
const scopeKeys = this.getSortedScopeNames();
|
|
1248
|
+
for (let key of scopeKeys) {
|
|
1249
|
+
let scope = this.scopes[key];
|
|
1250
|
+
if (scope.hasFile(resolvedFile)) {
|
|
1251
|
+
result.push(scope);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
return result;
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Get the first found scope for a file.
|
|
1259
|
+
*/
|
|
1260
|
+
getFirstScopeForFile(file) {
|
|
1261
|
+
const scopeKeys = this.getSortedScopeNames();
|
|
1262
|
+
for (let key of scopeKeys) {
|
|
588
1263
|
let scope = this.scopes[key];
|
|
589
1264
|
if (scope.hasFile(file)) {
|
|
590
|
-
|
|
1265
|
+
return scope;
|
|
591
1266
|
}
|
|
592
1267
|
}
|
|
593
|
-
return result;
|
|
594
1268
|
}
|
|
595
1269
|
getStatementsByName(name, originFile, namespaceName) {
|
|
596
|
-
var _a, _b;
|
|
597
1270
|
let results = new Map();
|
|
598
1271
|
const filesSearched = new Set();
|
|
599
1272
|
let lowerNamespaceName = namespaceName === null || namespaceName === void 0 ? void 0 : namespaceName.toLowerCase();
|
|
600
1273
|
let lowerName = name === null || name === void 0 ? void 0 : name.toLowerCase();
|
|
1274
|
+
function addToResults(statement, file) {
|
|
1275
|
+
var _a, _b;
|
|
1276
|
+
let parentNamespaceName = (_b = (_a = statement.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(originFile.parseMode)) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
1277
|
+
if (statement.tokens.name.text.toLowerCase() === lowerName && (!lowerNamespaceName || parentNamespaceName === lowerNamespaceName)) {
|
|
1278
|
+
if (!results.has(statement)) {
|
|
1279
|
+
results.set(statement, { item: statement, file: file });
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
601
1283
|
//look through all files in scope for matches
|
|
602
1284
|
for (const scope of this.getScopesForFile(originFile)) {
|
|
603
1285
|
for (const file of scope.getAllFiles()) {
|
|
604
|
-
|
|
1286
|
+
//skip non-brs files, or files we've already processed
|
|
1287
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
605
1288
|
continue;
|
|
606
1289
|
}
|
|
607
1290
|
filesSearched.add(file);
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
1291
|
+
file.ast.walk((0, visitors_1.createVisitor)({
|
|
1292
|
+
FunctionStatement: (statement) => {
|
|
1293
|
+
addToResults(statement, file);
|
|
1294
|
+
},
|
|
1295
|
+
MethodStatement: (statement) => {
|
|
1296
|
+
addToResults(statement, file);
|
|
614
1297
|
}
|
|
615
|
-
}
|
|
1298
|
+
}), {
|
|
1299
|
+
walkMode: visitors_1.WalkMode.visitStatements
|
|
1300
|
+
});
|
|
616
1301
|
}
|
|
617
1302
|
}
|
|
618
1303
|
return [...results.values()];
|
|
@@ -624,136 +1309,165 @@ class Program {
|
|
|
624
1309
|
//get all function names for the xml file and parents
|
|
625
1310
|
let funcNames = new Set();
|
|
626
1311
|
let currentScope = scope;
|
|
627
|
-
while (reflection_1.isXmlScope(currentScope)) {
|
|
628
|
-
for (let
|
|
629
|
-
if (
|
|
630
|
-
|
|
631
|
-
if (!filterName || name === filterName) {
|
|
632
|
-
funcNames.add(name);
|
|
633
|
-
}
|
|
1312
|
+
while ((0, reflection_1.isXmlScope)(currentScope)) {
|
|
1313
|
+
for (let name of (_b = (_a = currentScope.xmlFile.ast.componentElement.interfaceElement) === null || _a === void 0 ? void 0 : _a.functions.map((f) => f.name)) !== null && _b !== void 0 ? _b : []) {
|
|
1314
|
+
if (!filterName || name === filterName) {
|
|
1315
|
+
funcNames.add(name);
|
|
634
1316
|
}
|
|
635
1317
|
}
|
|
636
1318
|
currentScope = currentScope.getParentScope();
|
|
637
1319
|
}
|
|
638
1320
|
//look through all files in scope for matches
|
|
639
1321
|
for (const file of scope.getOwnFiles()) {
|
|
640
|
-
|
|
1322
|
+
//skip non-brs files, or files we've already processed
|
|
1323
|
+
if (!(0, reflection_1.isBrsFile)(file) || filesSearched.has(file)) {
|
|
641
1324
|
continue;
|
|
642
1325
|
}
|
|
643
1326
|
filesSearched.add(file);
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
if (
|
|
647
|
-
results.
|
|
1327
|
+
file.ast.walk((0, visitors_1.createVisitor)({
|
|
1328
|
+
FunctionStatement: (statement) => {
|
|
1329
|
+
if (funcNames.has(statement.tokens.name.text)) {
|
|
1330
|
+
if (!results.has(statement)) {
|
|
1331
|
+
results.set(statement, { item: statement, file: file });
|
|
1332
|
+
}
|
|
648
1333
|
}
|
|
649
1334
|
}
|
|
650
|
-
}
|
|
1335
|
+
}), {
|
|
1336
|
+
walkMode: visitors_1.WalkMode.visitStatements
|
|
1337
|
+
});
|
|
651
1338
|
}
|
|
652
1339
|
return [...results.values()];
|
|
653
1340
|
}
|
|
654
1341
|
/**
|
|
655
1342
|
* Find all available completion items at the given position
|
|
656
|
-
* @param
|
|
657
|
-
* @param
|
|
658
|
-
* @param columnIndex
|
|
1343
|
+
* @param filePath can be a srcPath or a destPath
|
|
1344
|
+
* @param position the position (line & column) where completions should be found
|
|
659
1345
|
*/
|
|
660
|
-
getCompletions(
|
|
661
|
-
let file = this.getFile(
|
|
1346
|
+
getCompletions(filePath, position) {
|
|
1347
|
+
let file = this.getFile(filePath);
|
|
662
1348
|
if (!file) {
|
|
663
1349
|
return [];
|
|
664
1350
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
//find the scopes for this file
|
|
678
|
-
let scopes = this.getScopesForFile(file);
|
|
679
|
-
//if there are no scopes, include the global scope so we at least get the built-in functions
|
|
680
|
-
scopes = scopes.length > 0 ? scopes : [this.globalScope];
|
|
681
|
-
//get the completions from all scopes for this file
|
|
682
|
-
let allCompletions = util_1.util.flatMap(scopes.map(ctx => file.getCompletions(position, ctx)), c => c);
|
|
683
|
-
//only keep completions common to every scope for this file
|
|
684
|
-
let keyCounts = {};
|
|
685
|
-
for (let completion of allCompletions) {
|
|
686
|
-
let key = `${completion.label}-${completion.kind}`;
|
|
687
|
-
keyCounts[key] = keyCounts[key] ? keyCounts[key] + 1 : 1;
|
|
688
|
-
if (keyCounts[key] === scopes.length) {
|
|
689
|
-
result.push(completion);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
return result;
|
|
1351
|
+
const event = {
|
|
1352
|
+
program: this,
|
|
1353
|
+
file: file,
|
|
1354
|
+
scopes: this.getScopesForFile(file),
|
|
1355
|
+
position: position,
|
|
1356
|
+
completions: []
|
|
1357
|
+
};
|
|
1358
|
+
this.plugins.emit('beforeProvideCompletions', event);
|
|
1359
|
+
this.plugins.emit('provideCompletions', event);
|
|
1360
|
+
this.plugins.emit('afterProvideCompletions', event);
|
|
1361
|
+
return event.completions;
|
|
693
1362
|
}
|
|
694
1363
|
/**
|
|
695
1364
|
* Goes through each file and builds a list of workspace symbols for the program. Used by LanguageServer's onWorkspaceSymbol functionality
|
|
696
1365
|
*/
|
|
697
1366
|
getWorkspaceSymbols() {
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
return
|
|
1367
|
+
const event = {
|
|
1368
|
+
program: this,
|
|
1369
|
+
workspaceSymbols: []
|
|
1370
|
+
};
|
|
1371
|
+
this.plugins.emit('beforeProvideWorkspaceSymbols', event);
|
|
1372
|
+
this.plugins.emit('provideWorkspaceSymbols', event);
|
|
1373
|
+
this.plugins.emit('afterProvideWorkspaceSymbols', event);
|
|
1374
|
+
return event.workspaceSymbols;
|
|
706
1375
|
}
|
|
707
1376
|
/**
|
|
708
1377
|
* Given a position in a file, if the position is sitting on some type of identifier,
|
|
709
1378
|
* go to the definition of that identifier (where this thing was first defined)
|
|
710
|
-
* @param srcPath The absolute path to the source file on disk
|
|
711
1379
|
*/
|
|
712
1380
|
getDefinition(srcPath, position) {
|
|
713
1381
|
let file = this.getFile(srcPath);
|
|
714
1382
|
if (!file) {
|
|
715
1383
|
return [];
|
|
716
1384
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
}
|
|
1385
|
+
const event = {
|
|
1386
|
+
program: this,
|
|
1387
|
+
file: file,
|
|
1388
|
+
position: position,
|
|
1389
|
+
definitions: []
|
|
1390
|
+
};
|
|
1391
|
+
this.plugins.emit('beforeProvideDefinition', event);
|
|
1392
|
+
this.plugins.emit('provideDefinition', event);
|
|
1393
|
+
this.plugins.emit('afterProvideDefinition', event);
|
|
1394
|
+
return event.definitions;
|
|
728
1395
|
}
|
|
729
1396
|
/**
|
|
730
|
-
*
|
|
1397
|
+
* Get hover information for a file and position
|
|
731
1398
|
*/
|
|
732
1399
|
getHover(srcPath, position) {
|
|
733
|
-
//find the file
|
|
734
1400
|
let file = this.getFile(srcPath);
|
|
735
|
-
|
|
736
|
-
|
|
1401
|
+
let result;
|
|
1402
|
+
if (file) {
|
|
1403
|
+
const event = {
|
|
1404
|
+
program: this,
|
|
1405
|
+
file: file,
|
|
1406
|
+
position: position,
|
|
1407
|
+
scopes: this.getScopesForFile(file),
|
|
1408
|
+
hovers: []
|
|
1409
|
+
};
|
|
1410
|
+
this.plugins.emit('beforeProvideHover', event);
|
|
1411
|
+
this.plugins.emit('provideHover', event);
|
|
1412
|
+
this.plugins.emit('afterProvideHover', event);
|
|
1413
|
+
result = event.hovers;
|
|
1414
|
+
}
|
|
1415
|
+
return result !== null && result !== void 0 ? result : [];
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Get full list of document symbols for a file
|
|
1419
|
+
* @param srcPath path to the file
|
|
1420
|
+
*/
|
|
1421
|
+
getDocumentSymbols(srcPath) {
|
|
1422
|
+
let file = this.getFile(srcPath);
|
|
1423
|
+
if (file) {
|
|
1424
|
+
const event = {
|
|
1425
|
+
program: this,
|
|
1426
|
+
file: file,
|
|
1427
|
+
documentSymbols: []
|
|
1428
|
+
};
|
|
1429
|
+
this.plugins.emit('beforeProvideDocumentSymbols', event);
|
|
1430
|
+
this.plugins.emit('provideDocumentSymbols', event);
|
|
1431
|
+
this.plugins.emit('afterProvideDocumentSymbols', event);
|
|
1432
|
+
return event.documentSymbols;
|
|
1433
|
+
}
|
|
1434
|
+
else {
|
|
1435
|
+
return undefined;
|
|
737
1436
|
}
|
|
738
|
-
return Promise.resolve(file.getHover(position));
|
|
739
1437
|
}
|
|
740
1438
|
/**
|
|
741
1439
|
* Compute code actions for the given file and range
|
|
742
|
-
* @param srcPath The absolute path to the source file on disk
|
|
743
1440
|
*/
|
|
744
1441
|
getCodeActions(srcPath, range) {
|
|
745
1442
|
const codeActions = [];
|
|
746
1443
|
const file = this.getFile(srcPath);
|
|
747
1444
|
if (file) {
|
|
1445
|
+
const fileUri = util_1.util.pathToUri(file === null || file === void 0 ? void 0 : file.srcPath);
|
|
748
1446
|
const diagnostics = this
|
|
749
1447
|
//get all current diagnostics (filtered by diagnostic filters)
|
|
750
1448
|
.getDiagnostics()
|
|
751
1449
|
//only keep diagnostics related to this file
|
|
752
|
-
.filter(x => x.
|
|
1450
|
+
.filter(x => { var _a; return ((_a = x.location) === null || _a === void 0 ? void 0 : _a.uri) === fileUri; })
|
|
753
1451
|
//only keep diagnostics that touch this range
|
|
754
|
-
.filter(x => util_1.util.
|
|
1452
|
+
.filter(x => util_1.util.rangesIntersectOrTouch(x.location.range, range));
|
|
755
1453
|
const scopes = this.getScopesForFile(file);
|
|
756
|
-
this.plugins.emit('
|
|
1454
|
+
this.plugins.emit('beforeProvideCodeActions', {
|
|
1455
|
+
program: this,
|
|
1456
|
+
file: file,
|
|
1457
|
+
range: range,
|
|
1458
|
+
diagnostics: diagnostics,
|
|
1459
|
+
scopes: scopes,
|
|
1460
|
+
codeActions: codeActions
|
|
1461
|
+
});
|
|
1462
|
+
this.plugins.emit('provideCodeActions', {
|
|
1463
|
+
program: this,
|
|
1464
|
+
file: file,
|
|
1465
|
+
range: range,
|
|
1466
|
+
diagnostics: diagnostics,
|
|
1467
|
+
scopes: scopes,
|
|
1468
|
+
codeActions: codeActions
|
|
1469
|
+
});
|
|
1470
|
+
this.plugins.emit('afterProvideCodeActions', {
|
|
757
1471
|
program: this,
|
|
758
1472
|
file: file,
|
|
759
1473
|
range: range,
|
|
@@ -770,8 +1484,20 @@ class Program {
|
|
|
770
1484
|
getSemanticTokens(srcPath) {
|
|
771
1485
|
const file = this.getFile(srcPath);
|
|
772
1486
|
if (file) {
|
|
1487
|
+
this.plugins.emit('beforeProvideSemanticTokens', {
|
|
1488
|
+
program: this,
|
|
1489
|
+
file: file,
|
|
1490
|
+
scopes: this.getScopesForFile(file),
|
|
1491
|
+
semanticTokens: undefined
|
|
1492
|
+
});
|
|
773
1493
|
const result = [];
|
|
774
|
-
this.plugins.emit('
|
|
1494
|
+
this.plugins.emit('provideSemanticTokens', {
|
|
1495
|
+
program: this,
|
|
1496
|
+
file: file,
|
|
1497
|
+
scopes: this.getScopesForFile(file),
|
|
1498
|
+
semanticTokens: result
|
|
1499
|
+
});
|
|
1500
|
+
this.plugins.emit('afterProvideSemanticTokens', {
|
|
775
1501
|
program: this,
|
|
776
1502
|
file: file,
|
|
777
1503
|
scopes: this.getScopesForFile(file),
|
|
@@ -780,363 +1506,262 @@ class Program {
|
|
|
780
1506
|
return result;
|
|
781
1507
|
}
|
|
782
1508
|
}
|
|
783
|
-
getSignatureHelp(
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
if (!file || !reflection_1.isBrsFile(file)) {
|
|
1509
|
+
getSignatureHelp(filePath, position) {
|
|
1510
|
+
let file = this.getFile(filePath);
|
|
1511
|
+
if (!file || !(0, reflection_1.isBrsFile)(file)) {
|
|
787
1512
|
return [];
|
|
788
1513
|
}
|
|
789
|
-
|
|
790
|
-
let
|
|
791
|
-
|
|
792
|
-
if (identifierInfo.statementType === '') {
|
|
793
|
-
// just general function calls
|
|
794
|
-
let statements = file.program.getStatementsByName(identifierInfo.name, file);
|
|
795
|
-
for (let statement of statements) {
|
|
796
|
-
//TODO better handling of collisions - if it's a namespace, then don't show any other overrides
|
|
797
|
-
//if we're on m - then limit scope to the current class, if present
|
|
798
|
-
let sigHelp = statement.file.getSignatureHelpForStatement(statement.item);
|
|
799
|
-
if (sigHelp && !results.has[sigHelp.key]) {
|
|
800
|
-
sigHelp.index = identifierInfo.commaCount;
|
|
801
|
-
results.set(sigHelp.key, sigHelp);
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
else if (identifierInfo.statementType === '.') {
|
|
806
|
-
//if m class reference.. then
|
|
807
|
-
//only get statements from the class I am in..
|
|
808
|
-
if (functionExpression) {
|
|
809
|
-
let myClass = file.getClassFromMReference(position, file.parser.getTokenAt(position), functionExpression);
|
|
810
|
-
if (myClass) {
|
|
811
|
-
for (let scope of this.getScopesForFile(myClass.file)) {
|
|
812
|
-
let classes = scope.getClassHierarchy(myClass.item.getName(parser_1.ParseMode.BrighterScript).toLowerCase());
|
|
813
|
-
//and anything from any class in scope to a non m class
|
|
814
|
-
for (let statement of [...classes].filter((i) => reflection_1.isClassMethodStatement(i.item))) {
|
|
815
|
-
let sigHelp = statement.file.getSignatureHelpForStatement(statement.item);
|
|
816
|
-
if (sigHelp && !results.has[sigHelp.key]) {
|
|
817
|
-
results.set(sigHelp.key, sigHelp);
|
|
818
|
-
return;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
if (identifierInfo.dotPart) {
|
|
825
|
-
//potential namespaces
|
|
826
|
-
let statements = file.program.getStatementsByName(identifierInfo.name, file, identifierInfo.dotPart);
|
|
827
|
-
if (statements.length === 0) {
|
|
828
|
-
//was not a namespaced function, it could be any method on any class now
|
|
829
|
-
statements = file.program.getStatementsByName(identifierInfo.name, file);
|
|
830
|
-
}
|
|
831
|
-
for (let statement of statements) {
|
|
832
|
-
//TODO better handling of collisions - if it's a namespace, then don't show any other overrides
|
|
833
|
-
//if we're on m - then limit scope to the current class, if present
|
|
834
|
-
let sigHelp = statement.file.getSignatureHelpForStatement(statement.item);
|
|
835
|
-
if (sigHelp && !results.has[sigHelp.key]) {
|
|
836
|
-
sigHelp.index = identifierInfo.commaCount;
|
|
837
|
-
results.set(sigHelp.key, sigHelp);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
else if (identifierInfo.statementType === '@.') {
|
|
843
|
-
for (const scope of this.getScopes().filter((s) => reflection_1.isXmlScope(s))) {
|
|
844
|
-
let fileLinks = this.getStatementsForXmlFile(scope, identifierInfo.name);
|
|
845
|
-
for (let fileLink of fileLinks) {
|
|
846
|
-
let sigHelp = fileLink.file.getSignatureHelpForStatement(fileLink.item);
|
|
847
|
-
if (sigHelp && !results.has[sigHelp.key]) {
|
|
848
|
-
sigHelp.index = identifierInfo.commaCount;
|
|
849
|
-
results.set(sigHelp.key, sigHelp);
|
|
850
|
-
}
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
else if (identifierInfo.statementType === 'new') {
|
|
855
|
-
let classItem = file.getClassFileLink(identifierInfo.dotPart ? `${identifierInfo.dotPart}.${identifierInfo.name}` : identifierInfo.name);
|
|
856
|
-
let sigHelp = (_a = classItem === null || classItem === void 0 ? void 0 : classItem.file) === null || _a === void 0 ? void 0 : _a.getClassSignatureHelp(classItem === null || classItem === void 0 ? void 0 : classItem.item);
|
|
857
|
-
if (sigHelp && !results.has(sigHelp.key)) {
|
|
858
|
-
sigHelp.index = identifierInfo.commaCount;
|
|
859
|
-
results.set(sigHelp.key, sigHelp);
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
return [...results.values()];
|
|
1514
|
+
let callExpressionInfo = new CallExpressionInfo_1.CallExpressionInfo(file, position);
|
|
1515
|
+
let signatureHelpUtil = new SignatureHelpUtil_1.SignatureHelpUtil();
|
|
1516
|
+
return signatureHelpUtil.getSignatureHelpItems(callExpressionInfo);
|
|
863
1517
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
let
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1518
|
+
getReferences(srcPath, position) {
|
|
1519
|
+
//find the file
|
|
1520
|
+
let file = this.getFile(srcPath);
|
|
1521
|
+
const event = {
|
|
1522
|
+
program: this,
|
|
1523
|
+
file: file,
|
|
1524
|
+
position: position,
|
|
1525
|
+
references: []
|
|
1526
|
+
};
|
|
1527
|
+
this.plugins.emit('beforeProvideReferences', event);
|
|
1528
|
+
this.plugins.emit('provideReferences', event);
|
|
1529
|
+
this.plugins.emit('afterProvideReferences', event);
|
|
1530
|
+
return event.references;
|
|
1531
|
+
}
|
|
1532
|
+
/**
|
|
1533
|
+
* Transpile a single file and get the result as a string.
|
|
1534
|
+
* This does not write anything to the file system.
|
|
1535
|
+
*
|
|
1536
|
+
* This should only be called by `LanguageServer`.
|
|
1537
|
+
* Internal usage should call `_getTranspiledFileContents` instead.
|
|
1538
|
+
* @param filePath can be a srcPath or a destPath
|
|
1539
|
+
*/
|
|
1540
|
+
async getTranspiledFileContents(filePath) {
|
|
1541
|
+
const file = this.getFile(filePath);
|
|
1542
|
+
return this.getTranspiledFileContentsPipeline.run(async () => {
|
|
1543
|
+
const result = {
|
|
1544
|
+
destPath: file.destPath,
|
|
1545
|
+
pkgPath: file.pkgPath,
|
|
1546
|
+
srcPath: file.srcPath
|
|
1547
|
+
};
|
|
1548
|
+
const expectedPkgPath = file.pkgPath.toLowerCase();
|
|
1549
|
+
const expectedMapPath = `${expectedPkgPath}.map`;
|
|
1550
|
+
const expectedTypedefPkgPath = expectedPkgPath.replace(/\.brs$/i, '.d.bs');
|
|
1551
|
+
//add a temporary plugin to tap into the file writing process
|
|
1552
|
+
const plugin = this.plugins.addFirst({
|
|
1553
|
+
name: 'getTranspiledFileContents',
|
|
1554
|
+
beforeWriteFile: (event) => {
|
|
1555
|
+
const pkgPath = event.file.pkgPath.toLowerCase();
|
|
1556
|
+
switch (pkgPath) {
|
|
1557
|
+
//this is the actual transpiled file
|
|
1558
|
+
case expectedPkgPath:
|
|
1559
|
+
result.code = event.file.data.toString();
|
|
1560
|
+
break;
|
|
1561
|
+
//this is the sourcemap
|
|
1562
|
+
case expectedMapPath:
|
|
1563
|
+
result.map = event.file.data.toString();
|
|
1564
|
+
break;
|
|
1565
|
+
//this is the typedef
|
|
1566
|
+
case expectedTypedefPkgPath:
|
|
1567
|
+
result.typedef = event.file.data.toString();
|
|
1568
|
+
break;
|
|
1569
|
+
default:
|
|
1570
|
+
//no idea what this file is. just ignore it
|
|
913
1571
|
}
|
|
1572
|
+
//mark every file as processed so it they don't get written to the output directory
|
|
1573
|
+
event.processedFiles.add(event.file);
|
|
914
1574
|
}
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1575
|
+
});
|
|
1576
|
+
try {
|
|
1577
|
+
//now that the plugin has been registered, run the build with just this file
|
|
1578
|
+
await this.build({
|
|
1579
|
+
files: [file]
|
|
1580
|
+
});
|
|
921
1581
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
name = name || line.substring(index, argStartIndex);
|
|
925
|
-
argStartIndex = index;
|
|
1582
|
+
finally {
|
|
1583
|
+
this.plugins.remove(plugin);
|
|
926
1584
|
}
|
|
927
|
-
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
|
|
1585
|
+
return result;
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
/**
|
|
1589
|
+
* Get the absolute output path for a file
|
|
1590
|
+
*/
|
|
1591
|
+
getOutputPath(file, outDir = this.getOutDir()) {
|
|
1592
|
+
return (0, util_1.standardizePath) `${outDir}/${file.pkgPath}`;
|
|
1593
|
+
}
|
|
1594
|
+
getOutDir(outDir) {
|
|
1595
|
+
var _a, _b;
|
|
1596
|
+
let result = (_a = outDir !== null && outDir !== void 0 ? outDir : this.options.outDir) !== null && _a !== void 0 ? _a : this.options.outDir;
|
|
1597
|
+
if (!result) {
|
|
1598
|
+
result = roku_deploy_1.rokuDeploy.getOptions(this.options).outDir;
|
|
931
1599
|
}
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
statementType: statementType,
|
|
935
|
-
name: name,
|
|
936
|
-
dotPart: dotPart
|
|
937
|
-
};
|
|
1600
|
+
result = (0, util_1.standardizePath) `${path.resolve((_b = this.options.cwd) !== null && _b !== void 0 ? _b : process.cwd(), result !== null && result !== void 0 ? result : '/')}`;
|
|
1601
|
+
return result;
|
|
938
1602
|
}
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
isArgStartFound: false
|
|
1603
|
+
/**
|
|
1604
|
+
* Prepare the program for building
|
|
1605
|
+
* @param files the list of files that should be prepared
|
|
1606
|
+
*/
|
|
1607
|
+
async prepare(files) {
|
|
1608
|
+
const programEvent = {
|
|
1609
|
+
program: this,
|
|
1610
|
+
editor: this.editor,
|
|
1611
|
+
files: files
|
|
949
1612
|
};
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
if
|
|
953
|
-
|
|
954
|
-
|
|
1613
|
+
//assign an editor to every file
|
|
1614
|
+
for (const file of programEvent.files) {
|
|
1615
|
+
//if the file doesn't have an editor yet, assign one now
|
|
1616
|
+
if (!file.editor) {
|
|
1617
|
+
file.editor = new Editor_1.Editor();
|
|
955
1618
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1619
|
+
}
|
|
1620
|
+
//sort the entries to make transpiling more deterministic
|
|
1621
|
+
programEvent.files.sort((a, b) => {
|
|
1622
|
+
if (a.pkgPath < b.pkgPath) {
|
|
1623
|
+
return -1;
|
|
1624
|
+
}
|
|
1625
|
+
else if (a.pkgPath > b.pkgPath) {
|
|
1626
|
+
return 1;
|
|
960
1627
|
}
|
|
961
1628
|
else {
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
itemCounts.isArgStartFound = true;
|
|
977
|
-
itemCounts.argStartIndex = index;
|
|
978
|
-
}
|
|
979
|
-
else {
|
|
980
|
-
itemCounts.normal--;
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
if (currentChar === '[') {
|
|
984
|
-
itemCounts.square--;
|
|
985
|
-
}
|
|
986
|
-
if (currentChar === '{') {
|
|
987
|
-
itemCounts.curly--;
|
|
988
|
-
}
|
|
1629
|
+
return 1;
|
|
1630
|
+
}
|
|
1631
|
+
});
|
|
1632
|
+
await this.plugins.emitAsync('beforePrepareProgram', programEvent);
|
|
1633
|
+
await this.plugins.emitAsync('prepareProgram', programEvent);
|
|
1634
|
+
const outDir = this.getOutDir();
|
|
1635
|
+
const entries = [];
|
|
1636
|
+
for (const file of files) {
|
|
1637
|
+
const scope = this.getFirstScopeForFile(file);
|
|
1638
|
+
//link the symbol table for all the files in this scope
|
|
1639
|
+
scope === null || scope === void 0 ? void 0 : scope.linkSymbolTable();
|
|
1640
|
+
//if the file doesn't have an editor yet, assign one now
|
|
1641
|
+
if (!file.editor) {
|
|
1642
|
+
file.editor = new Editor_1.Editor();
|
|
989
1643
|
}
|
|
990
|
-
|
|
1644
|
+
const event = {
|
|
1645
|
+
program: this,
|
|
1646
|
+
file: file,
|
|
1647
|
+
editor: file.editor,
|
|
1648
|
+
scope: scope,
|
|
1649
|
+
outputPath: this.getOutputPath(file, outDir)
|
|
1650
|
+
};
|
|
1651
|
+
await this.plugins.emitAsync('beforePrepareFile', event);
|
|
1652
|
+
await this.plugins.emitAsync('prepareFile', event);
|
|
1653
|
+
await this.plugins.emitAsync('afterPrepareFile', event);
|
|
1654
|
+
//TODO remove this in v1
|
|
1655
|
+
entries.push(event);
|
|
1656
|
+
//unlink the symbolTable so the next loop iteration can link theirs
|
|
1657
|
+
scope === null || scope === void 0 ? void 0 : scope.unlinkSymbolTable();
|
|
991
1658
|
}
|
|
992
|
-
|
|
1659
|
+
await this.plugins.emitAsync('afterPrepareProgram', programEvent);
|
|
1660
|
+
return files;
|
|
993
1661
|
}
|
|
994
1662
|
/**
|
|
995
|
-
*
|
|
1663
|
+
* Generate the contents of every file
|
|
996
1664
|
*/
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
if (
|
|
1001
|
-
|
|
1665
|
+
async serialize(files) {
|
|
1666
|
+
const allFiles = new Map();
|
|
1667
|
+
//exclude prunable files if that option is enabled
|
|
1668
|
+
if (this.options.pruneEmptyCodeFiles === true) {
|
|
1669
|
+
files = files.filter(x => x.canBePruned !== true);
|
|
1002
1670
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
for (const key in this.files) {
|
|
1018
|
-
const file = this.files[key];
|
|
1019
|
-
if (
|
|
1020
|
-
//is a BrightScript or BrighterScript file
|
|
1021
|
-
(file.extension === '.bs' || file.extension === '.brs') &&
|
|
1022
|
-
//this file is not the current file
|
|
1023
|
-
lowerSourcePkgPath !== file.pkgPath.toLowerCase()) {
|
|
1024
|
-
//add the relative path
|
|
1025
|
-
let relativePath = util_1.util.getRelativePath(sourcePkgPath, file.pkgPath).replace(/\\/g, '/');
|
|
1026
|
-
const lowerPkgPath = file.pkgPath.toLowerCase();
|
|
1027
|
-
if (!resultPkgPaths[lowerPkgPath]) {
|
|
1028
|
-
resultPkgPaths[lowerPkgPath] = true;
|
|
1029
|
-
result.push({
|
|
1030
|
-
label: relativePath,
|
|
1031
|
-
detail: file.srcPath,
|
|
1032
|
-
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
1033
|
-
textEdit: {
|
|
1034
|
-
newText: relativePath,
|
|
1035
|
-
range: scriptImport.filePathRange
|
|
1036
|
-
}
|
|
1037
|
-
});
|
|
1038
|
-
//add the absolute path
|
|
1039
|
-
result.push({
|
|
1040
|
-
label: file.pkgPath,
|
|
1041
|
-
detail: file.srcPath,
|
|
1042
|
-
kind: vscode_languageserver_1.CompletionItemKind.File,
|
|
1043
|
-
textEdit: {
|
|
1044
|
-
newText: file.pkgPath,
|
|
1045
|
-
range: scriptImport.filePathRange
|
|
1046
|
-
}
|
|
1047
|
-
});
|
|
1048
|
-
}
|
|
1671
|
+
const serializeProgramEvent = await this.plugins.emitAsync('beforeSerializeProgram', {
|
|
1672
|
+
program: this,
|
|
1673
|
+
files: files,
|
|
1674
|
+
result: allFiles
|
|
1675
|
+
});
|
|
1676
|
+
await this.plugins.emitAsync('serializeProgram', serializeProgramEvent);
|
|
1677
|
+
// serialize each file
|
|
1678
|
+
for (const file of files) {
|
|
1679
|
+
let scope = this.getFirstScopeForFile(file);
|
|
1680
|
+
//if the file doesn't have a scope, create a temporary scope for the file so it can depend on scope-level items
|
|
1681
|
+
if (!scope) {
|
|
1682
|
+
scope = new Scope_1.Scope(`temporary-for-${file.pkgPath}`, this);
|
|
1683
|
+
scope.getAllFiles = () => [file];
|
|
1684
|
+
scope.getOwnFiles = scope.getAllFiles;
|
|
1049
1685
|
}
|
|
1686
|
+
//link the symbol table for all the files in this scope
|
|
1687
|
+
scope === null || scope === void 0 ? void 0 : scope.linkSymbolTable();
|
|
1688
|
+
const event = {
|
|
1689
|
+
program: this,
|
|
1690
|
+
file: file,
|
|
1691
|
+
scope: scope,
|
|
1692
|
+
result: allFiles
|
|
1693
|
+
};
|
|
1694
|
+
await this.plugins.emitAsync('beforeSerializeFile', event);
|
|
1695
|
+
await this.plugins.emitAsync('serializeFile', event);
|
|
1696
|
+
await this.plugins.emitAsync('afterSerializeFile', event);
|
|
1697
|
+
//unlink the symbolTable so the next loop iteration can link theirs
|
|
1698
|
+
scope === null || scope === void 0 ? void 0 : scope.unlinkSymbolTable();
|
|
1050
1699
|
}
|
|
1051
|
-
|
|
1700
|
+
this.plugins.emit('afterSerializeProgram', serializeProgramEvent);
|
|
1701
|
+
return allFiles;
|
|
1052
1702
|
}
|
|
1053
1703
|
/**
|
|
1054
|
-
*
|
|
1055
|
-
* This does not write anything to the file system.
|
|
1056
|
-
* @param srcPath The absolute path to the source file on disk
|
|
1704
|
+
* Write the entire project to disk
|
|
1057
1705
|
*/
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
let result = file.transpile();
|
|
1061
|
-
return Object.assign(Object.assign({}, result), { srcPath: file.srcPath, pkgPath: file.pkgPath });
|
|
1062
|
-
}
|
|
1063
|
-
async transpile(fileEntries, stagingFolderPath) {
|
|
1064
|
-
// map fileEntries using their path as key to avoid excessive "find()" operations
|
|
1065
|
-
const mappedFileEntries = fileEntries.reduce((collection, entry) => {
|
|
1066
|
-
collection[util_1.standardizePath `${entry.src}`] = entry;
|
|
1067
|
-
return collection;
|
|
1068
|
-
}, {});
|
|
1069
|
-
const entries = [];
|
|
1070
|
-
for (const key in this.files) {
|
|
1071
|
-
const file = this.files[key];
|
|
1072
|
-
let filePathObj = mappedFileEntries[util_1.standardizePath `${file.srcPath}`];
|
|
1073
|
-
if (!filePathObj) {
|
|
1074
|
-
//this file has been added in-memory, from a plugin, for example
|
|
1075
|
-
filePathObj = {
|
|
1076
|
-
//add an interpolated src path (since it doesn't actually exist in memory)
|
|
1077
|
-
src: `bsc-in-memory:/${util_1.util.removeProtocol(file.pkgPath)}`,
|
|
1078
|
-
dest: file.pkgPath
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
|
-
//prep the output path
|
|
1082
|
-
let outputPath = filePathObj.dest
|
|
1083
|
-
//replace any leading protocol
|
|
1084
|
-
.replace(/^[-a-z_]+:\//, '')
|
|
1085
|
-
//change any .bs file extension to .brs
|
|
1086
|
-
.replace(/\.bs$/gi, '.brs');
|
|
1087
|
-
//prepend the staging folder path
|
|
1088
|
-
outputPath = util_1.standardizePath `${stagingFolderPath}/${outputPath}`;
|
|
1089
|
-
entries.push({
|
|
1090
|
-
file: file,
|
|
1091
|
-
outputPath: outputPath
|
|
1092
|
-
});
|
|
1093
|
-
}
|
|
1094
|
-
this.plugins.emit('beforeProgramTranspile', {
|
|
1706
|
+
async write(outDir, files) {
|
|
1707
|
+
const programEvent = await this.plugins.emitAsync('beforeWriteProgram', {
|
|
1095
1708
|
program: this,
|
|
1096
|
-
|
|
1709
|
+
files: files,
|
|
1710
|
+
outDir: outDir
|
|
1097
1711
|
});
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1712
|
+
//empty the out directory
|
|
1713
|
+
await fsExtra.emptyDir(outDir);
|
|
1714
|
+
const serializedFiles = [...files]
|
|
1715
|
+
.map(([, serializedFiles]) => serializedFiles)
|
|
1716
|
+
.flat();
|
|
1717
|
+
//write all the files to disk (asynchronously)
|
|
1718
|
+
await Promise.all(serializedFiles.map(async (file) => {
|
|
1719
|
+
const event = await this.plugins.emitAsync('beforeWriteFile', {
|
|
1104
1720
|
program: this,
|
|
1105
|
-
file:
|
|
1106
|
-
outputPath:
|
|
1721
|
+
file: file,
|
|
1722
|
+
outputPath: this.getOutputPath(file, outDir),
|
|
1723
|
+
processedFiles: new Set()
|
|
1107
1724
|
});
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
await fsExtra.writeFile(typedefPath, typedef);
|
|
1124
|
-
}
|
|
1125
|
-
this.plugins.emit('afterFileTranspile', {
|
|
1725
|
+
await this.plugins.emitAsync('writeFile', event);
|
|
1726
|
+
await this.plugins.emitAsync('afterWriteFile', event);
|
|
1727
|
+
}));
|
|
1728
|
+
await this.plugins.emitAsync('afterWriteProgram', programEvent);
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Build the project. This transpiles/transforms/copies all files and moves them to the staging directory
|
|
1732
|
+
* @param options the list of options used to build the program
|
|
1733
|
+
*/
|
|
1734
|
+
async build(options) {
|
|
1735
|
+
//run a single build at a time
|
|
1736
|
+
await this.buildPipeline.run(async () => {
|
|
1737
|
+
var _a;
|
|
1738
|
+
const outDir = this.getOutDir(options === null || options === void 0 ? void 0 : options.outDir);
|
|
1739
|
+
const event = await this.plugins.emitAsync('beforeBuildProgram', {
|
|
1126
1740
|
program: this,
|
|
1127
|
-
|
|
1128
|
-
|
|
1741
|
+
editor: this.editor,
|
|
1742
|
+
files: (_a = options === null || options === void 0 ? void 0 : options.files) !== null && _a !== void 0 ? _a : Object.values(this.files)
|
|
1129
1743
|
});
|
|
1744
|
+
//prepare the program (and files) for building
|
|
1745
|
+
event.files = await this.prepare(event.files);
|
|
1746
|
+
//stage the entire program
|
|
1747
|
+
const serializedFilesByFile = await this.serialize(event.files);
|
|
1748
|
+
await this.write(outDir, serializedFilesByFile);
|
|
1749
|
+
await this.plugins.emitAsync('afterBuildProgram', event);
|
|
1750
|
+
//undo all edits for the program
|
|
1751
|
+
this.editor.undoAll();
|
|
1752
|
+
//undo all edits for each file
|
|
1753
|
+
for (const file of event.files) {
|
|
1754
|
+
file.editor.undoAll();
|
|
1755
|
+
}
|
|
1130
1756
|
});
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1757
|
+
this.logger.debug('Types Created', helpers_1.TypesCreated);
|
|
1758
|
+
let totalTypesCreated = 0;
|
|
1759
|
+
for (const key in helpers_1.TypesCreated) {
|
|
1760
|
+
if (helpers_1.TypesCreated.hasOwnProperty(key)) {
|
|
1761
|
+
totalTypesCreated += helpers_1.TypesCreated[key];
|
|
1762
|
+
}
|
|
1134
1763
|
}
|
|
1135
|
-
|
|
1136
|
-
this.plugins.emit('afterProgramTranspile', {
|
|
1137
|
-
program: this,
|
|
1138
|
-
entries: entries
|
|
1139
|
-
});
|
|
1764
|
+
this.logger.info('Total Types Created', totalTypesCreated);
|
|
1140
1765
|
}
|
|
1141
1766
|
/**
|
|
1142
1767
|
* Find a list of files in the program that have a function with the given name (case INsensitive)
|
|
@@ -1146,10 +1771,11 @@ class Program {
|
|
|
1146
1771
|
const lowerFunctionName = functionName.toLowerCase();
|
|
1147
1772
|
//find every file with this function defined
|
|
1148
1773
|
for (const file of Object.values(this.files)) {
|
|
1149
|
-
if (reflection_1.isBrsFile(file)) {
|
|
1774
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
1150
1775
|
//TODO handle namespace-relative function calls
|
|
1151
1776
|
//if the file has a function with this name
|
|
1152
|
-
|
|
1777
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1778
|
+
if (file['_cachedLookups'].functionStatementMap.get(lowerFunctionName)) {
|
|
1153
1779
|
files.push(file);
|
|
1154
1780
|
}
|
|
1155
1781
|
}
|
|
@@ -1157,55 +1783,144 @@ class Program {
|
|
|
1157
1783
|
return files;
|
|
1158
1784
|
}
|
|
1159
1785
|
/**
|
|
1160
|
-
* Find a list of files in the program that have a
|
|
1786
|
+
* Find a list of files in the program that have a class with the given name (case INsensitive)
|
|
1161
1787
|
*/
|
|
1162
1788
|
findFilesForClass(className) {
|
|
1163
1789
|
const files = [];
|
|
1164
1790
|
const lowerClassName = className.toLowerCase();
|
|
1165
1791
|
//find every file with this class defined
|
|
1166
1792
|
for (const file of Object.values(this.files)) {
|
|
1167
|
-
if (reflection_1.isBrsFile(file)) {
|
|
1793
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
1168
1794
|
//TODO handle namespace-relative classes
|
|
1169
1795
|
//if the file has a function with this name
|
|
1170
|
-
|
|
1796
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1797
|
+
if (file['_cachedLookups'].classStatementMap.get(lowerClassName) !== undefined) {
|
|
1798
|
+
files.push(file);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
return files;
|
|
1803
|
+
}
|
|
1804
|
+
findFilesForNamespace(name) {
|
|
1805
|
+
const files = [];
|
|
1806
|
+
const lowerName = name.toLowerCase();
|
|
1807
|
+
//find every file with this class defined
|
|
1808
|
+
for (const file of Object.values(this.files)) {
|
|
1809
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
1810
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1811
|
+
if (file['_cachedLookups'].namespaceStatements.find((x) => {
|
|
1812
|
+
const namespaceName = x.name.toLowerCase();
|
|
1813
|
+
return (
|
|
1814
|
+
//the namespace name matches exactly
|
|
1815
|
+
namespaceName === lowerName ||
|
|
1816
|
+
//the full namespace starts with the name (honoring the part boundary)
|
|
1817
|
+
namespaceName.startsWith(lowerName + '.'));
|
|
1818
|
+
})) {
|
|
1171
1819
|
files.push(file);
|
|
1172
1820
|
}
|
|
1173
1821
|
}
|
|
1174
1822
|
}
|
|
1175
1823
|
return files;
|
|
1176
1824
|
}
|
|
1825
|
+
findFilesForEnum(name) {
|
|
1826
|
+
const files = [];
|
|
1827
|
+
const lowerName = name.toLowerCase();
|
|
1828
|
+
//find every file with this enum defined
|
|
1829
|
+
for (const file of Object.values(this.files)) {
|
|
1830
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
1831
|
+
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
1832
|
+
if (file['_cachedLookups'].enumStatementMap.get(lowerName)) {
|
|
1833
|
+
files.push(file);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
return files;
|
|
1838
|
+
}
|
|
1839
|
+
/**
|
|
1840
|
+
* Modify a parsed manifest map by reading `bs_const` and injecting values from `options.manifest.bs_const`
|
|
1841
|
+
* @param parsedManifest The manifest map to read from and modify
|
|
1842
|
+
*/
|
|
1843
|
+
buildBsConstsIntoParsedManifest(parsedManifest) {
|
|
1844
|
+
var _a, _b;
|
|
1845
|
+
// Lift the bs_consts defined in the manifest
|
|
1846
|
+
let bsConsts = (0, Manifest_1.getBsConst)(parsedManifest, false);
|
|
1847
|
+
// Override or delete any bs_consts defined in the bs config
|
|
1848
|
+
for (const key in (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.manifest) === null || _b === void 0 ? void 0 : _b.bs_const) {
|
|
1849
|
+
const value = this.options.manifest.bs_const[key];
|
|
1850
|
+
if (value === null) {
|
|
1851
|
+
bsConsts.delete(key);
|
|
1852
|
+
}
|
|
1853
|
+
else {
|
|
1854
|
+
bsConsts.set(key, value);
|
|
1855
|
+
}
|
|
1856
|
+
}
|
|
1857
|
+
// convert the new list of bs consts back into a string for the rest of the down stream systems to use
|
|
1858
|
+
let constString = '';
|
|
1859
|
+
for (const [key, value] of bsConsts) {
|
|
1860
|
+
constString += `${constString !== '' ? ';' : ''}${key}=${value.toString()}`;
|
|
1861
|
+
}
|
|
1862
|
+
// Set the updated bs_const value
|
|
1863
|
+
parsedManifest.set('bs_const', constString);
|
|
1864
|
+
}
|
|
1865
|
+
/**
|
|
1866
|
+
* Try to find and load the manifest into memory
|
|
1867
|
+
* @param manifestFileObj A pointer to a potential manifest file object found during loading
|
|
1868
|
+
* @param replaceIfAlreadyLoaded should we overwrite the internal `_manifest` if it already exists
|
|
1869
|
+
*/
|
|
1870
|
+
loadManifest(manifestFileObj, replaceIfAlreadyLoaded = true) {
|
|
1871
|
+
//if we already have a manifest instance, and should not replace...then don't replace
|
|
1872
|
+
if (!replaceIfAlreadyLoaded && this._manifest) {
|
|
1873
|
+
return;
|
|
1874
|
+
}
|
|
1875
|
+
let manifestPath = manifestFileObj
|
|
1876
|
+
? manifestFileObj.src
|
|
1877
|
+
: path.join(this.options.rootDir, 'manifest');
|
|
1878
|
+
try {
|
|
1879
|
+
// we only load this manifest once, so do it sync to improve speed downstream
|
|
1880
|
+
const contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1881
|
+
const parsedManifest = (0, Manifest_1.parseManifest)(contents);
|
|
1882
|
+
this.buildBsConstsIntoParsedManifest(parsedManifest);
|
|
1883
|
+
this._manifest = parsedManifest;
|
|
1884
|
+
}
|
|
1885
|
+
catch (e) {
|
|
1886
|
+
this._manifest = new Map();
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1177
1889
|
/**
|
|
1178
1890
|
* Get a map of the manifest information
|
|
1179
1891
|
*/
|
|
1180
1892
|
getManifest() {
|
|
1181
1893
|
if (!this._manifest) {
|
|
1182
|
-
|
|
1183
|
-
//TODO update this to get the manifest from the files array or require it in the options...we shouldn't assume the location of the manifest
|
|
1184
|
-
let manifestPath = path.join(this.options.rootDir, 'manifest');
|
|
1185
|
-
let contents;
|
|
1186
|
-
try {
|
|
1187
|
-
//we only load this manifest once, so do it sync to improve speed downstream
|
|
1188
|
-
contents = fsExtra.readFileSync(manifestPath, 'utf-8');
|
|
1189
|
-
this._manifest = Manifest_1.parseManifest(contents);
|
|
1190
|
-
}
|
|
1191
|
-
catch (err) {
|
|
1192
|
-
this._manifest = new Map();
|
|
1193
|
-
}
|
|
1894
|
+
this.loadManifest();
|
|
1194
1895
|
}
|
|
1195
1896
|
return this._manifest;
|
|
1196
1897
|
}
|
|
1197
1898
|
dispose() {
|
|
1198
|
-
var _a, _b;
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
(_a =
|
|
1899
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1900
|
+
this.plugins.emit('beforeRemoveProgram', { program: this });
|
|
1901
|
+
for (let filePath in this.files) {
|
|
1902
|
+
(_b = (_a = this.files[filePath]) === null || _a === void 0 ? void 0 : _a.dispose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
1202
1903
|
}
|
|
1203
1904
|
for (let name in this.scopes) {
|
|
1204
|
-
(
|
|
1905
|
+
(_d = (_c = this.scopes[name]) === null || _c === void 0 ? void 0 : _c.dispose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
1205
1906
|
}
|
|
1206
|
-
this.globalScope.dispose();
|
|
1207
|
-
this.dependencyGraph.dispose();
|
|
1907
|
+
(_f = (_e = this.globalScope) === null || _e === void 0 ? void 0 : _e.dispose) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
1908
|
+
(_h = (_g = this.dependencyGraph) === null || _g === void 0 ? void 0 : _g.dispose) === null || _h === void 0 ? void 0 : _h.call(_g);
|
|
1909
|
+
this.plugins.emit('removeProgram', { program: this });
|
|
1910
|
+
this.plugins.emit('afterRemoveProgram', { program: this });
|
|
1208
1911
|
}
|
|
1209
1912
|
}
|
|
1210
1913
|
exports.Program = Program;
|
|
1914
|
+
class ProvideFileEventInternal {
|
|
1915
|
+
constructor(program, srcPath, destPath, data, fileFactory) {
|
|
1916
|
+
var _a;
|
|
1917
|
+
this.program = program;
|
|
1918
|
+
this.srcPath = srcPath;
|
|
1919
|
+
this.destPath = destPath;
|
|
1920
|
+
this.data = data;
|
|
1921
|
+
this.fileFactory = fileFactory;
|
|
1922
|
+
this.files = [];
|
|
1923
|
+
this.srcExtension = (_a = path.extname(srcPath)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1211
1926
|
//# sourceMappingURL=Program.js.map
|