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
|
@@ -0,0 +1,1323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScopeValidator = void 0;
|
|
4
|
+
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
5
|
+
const reflection_1 = require("../../astUtils/reflection");
|
|
6
|
+
const DiagnosticMessages_1 = require("../../DiagnosticMessages");
|
|
7
|
+
const util_1 = require("../../util");
|
|
8
|
+
const roku_types_1 = require("../../roku-types");
|
|
9
|
+
const AstNode_1 = require("../../parser/AstNode");
|
|
10
|
+
const Expression_1 = require("../../parser/Expression");
|
|
11
|
+
const visitors_1 = require("../../astUtils/visitors");
|
|
12
|
+
const AstValidationSegmenter_1 = require("../../AstValidationSegmenter");
|
|
13
|
+
const TokenKind_1 = require("../../lexer/TokenKind");
|
|
14
|
+
const Parser_1 = require("../../parser/Parser");
|
|
15
|
+
const ClassValidator_1 = require("../../validators/ClassValidator");
|
|
16
|
+
const globalCallables_1 = require("../../globalCallables");
|
|
17
|
+
const SGTypes_1 = require("../../parser/SGTypes");
|
|
18
|
+
const DynamicType_1 = require("../../types/DynamicType");
|
|
19
|
+
const BscTypeKind_1 = require("../../types/BscTypeKind");
|
|
20
|
+
const BrightScriptDocParser_1 = require("../../parser/BrightScriptDocParser");
|
|
21
|
+
const InvalidType_1 = require("../../types/InvalidType");
|
|
22
|
+
const VoidType_1 = require("../../types/VoidType");
|
|
23
|
+
const Logger_1 = require("../../Logger");
|
|
24
|
+
const Stopwatch_1 = require("../../Stopwatch");
|
|
25
|
+
const chalk_1 = require("chalk");
|
|
26
|
+
const IntegerType_1 = require("../../types/IntegerType");
|
|
27
|
+
/**
|
|
28
|
+
* The lower-case names of all platform-included scenegraph nodes
|
|
29
|
+
*/
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
31
|
+
const platformNodeNames = roku_types_1.nodes ? new Set(Object.values(roku_types_1.nodes).map(x => x === null || x === void 0 ? void 0 : x.name.toLowerCase())) : new Set();
|
|
32
|
+
const platformComponentNames = roku_types_1.components ? new Set(Object.values(roku_types_1.components).map(x => x === null || x === void 0 ? void 0 : x.name.toLowerCase())) : new Set();
|
|
33
|
+
var ScopeValidatorDiagnosticTag;
|
|
34
|
+
(function (ScopeValidatorDiagnosticTag) {
|
|
35
|
+
ScopeValidatorDiagnosticTag["Imports"] = "ScopeValidatorImports";
|
|
36
|
+
ScopeValidatorDiagnosticTag["NamespaceCollisions"] = "ScopeValidatorNamespaceCollisions";
|
|
37
|
+
ScopeValidatorDiagnosticTag["DuplicateFunctionDeclaration"] = "ScopeValidatorDuplicateFunctionDeclaration";
|
|
38
|
+
ScopeValidatorDiagnosticTag["FunctionCollisions"] = "ScopeValidatorFunctionCollisions";
|
|
39
|
+
ScopeValidatorDiagnosticTag["Classes"] = "ScopeValidatorClasses";
|
|
40
|
+
ScopeValidatorDiagnosticTag["XMLInterface"] = "ScopeValidatorXML";
|
|
41
|
+
ScopeValidatorDiagnosticTag["XMLImports"] = "ScopeValidatorXMLImports";
|
|
42
|
+
ScopeValidatorDiagnosticTag["Default"] = "ScopeValidator";
|
|
43
|
+
ScopeValidatorDiagnosticTag["Segment"] = "ScopeValidatorSegment";
|
|
44
|
+
})(ScopeValidatorDiagnosticTag || (ScopeValidatorDiagnosticTag = {}));
|
|
45
|
+
/**
|
|
46
|
+
* A validator that handles all scope validations for a program validation cycle.
|
|
47
|
+
* You should create ONE of these to handle all scope events between beforeValidateProgram and afterValidateProgram,
|
|
48
|
+
* and call reset() before using it again in the next cycle
|
|
49
|
+
*/
|
|
50
|
+
class ScopeValidator {
|
|
51
|
+
constructor() {
|
|
52
|
+
this.segmentsMetrics = new Map();
|
|
53
|
+
this.validationKindsMetrics = new Map();
|
|
54
|
+
}
|
|
55
|
+
processEvent(event) {
|
|
56
|
+
this.event = event;
|
|
57
|
+
if (this.event.program.globalScope === this.event.scope) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const logger = this.event.program.logger;
|
|
61
|
+
const metrics = {
|
|
62
|
+
fileWalkTime: '',
|
|
63
|
+
flagDuplicateFunctionTime: '',
|
|
64
|
+
classValidationTime: '',
|
|
65
|
+
scriptImportValidationTime: '',
|
|
66
|
+
xmlValidationTime: ''
|
|
67
|
+
};
|
|
68
|
+
this.segmentsMetrics.clear();
|
|
69
|
+
this.validationKindsMetrics.clear();
|
|
70
|
+
const validationStopwatch = new Stopwatch_1.Stopwatch();
|
|
71
|
+
logger.time(Logger_1.LogLevel.debug, ['Validating scope', this.event.scope.name], () => {
|
|
72
|
+
metrics.fileWalkTime = validationStopwatch.getDurationTextFor(() => {
|
|
73
|
+
this.walkFiles();
|
|
74
|
+
}).durationText;
|
|
75
|
+
this.currentSegmentBeingValidated = null;
|
|
76
|
+
metrics.flagDuplicateFunctionTime = validationStopwatch.getDurationTextFor(() => {
|
|
77
|
+
this.flagDuplicateFunctionDeclarations();
|
|
78
|
+
}).durationText;
|
|
79
|
+
metrics.scriptImportValidationTime = validationStopwatch.getDurationTextFor(() => {
|
|
80
|
+
this.validateScriptImportPaths();
|
|
81
|
+
}).durationText;
|
|
82
|
+
metrics.classValidationTime = validationStopwatch.getDurationTextFor(() => {
|
|
83
|
+
this.validateClasses();
|
|
84
|
+
}).durationText;
|
|
85
|
+
metrics.xmlValidationTime = validationStopwatch.getDurationTextFor(() => {
|
|
86
|
+
if ((0, reflection_1.isXmlScope)(this.event.scope)) {
|
|
87
|
+
//detect when the child imports a script that its ancestor also imports
|
|
88
|
+
this.diagnosticDetectDuplicateAncestorScriptImports(this.event.scope);
|
|
89
|
+
//validate component interface
|
|
90
|
+
this.validateXmlInterface(this.event.scope);
|
|
91
|
+
}
|
|
92
|
+
}).durationText;
|
|
93
|
+
});
|
|
94
|
+
logger.debug(this.event.scope.name, 'segment metrics:');
|
|
95
|
+
let totalSegments = 0;
|
|
96
|
+
for (const [filePath, metric] of this.segmentsMetrics) {
|
|
97
|
+
this.event.program.logger.debug(' - ', filePath, metric.segments, metric.time);
|
|
98
|
+
totalSegments += metric.segments;
|
|
99
|
+
}
|
|
100
|
+
logger.debug(this.event.scope.name, 'total segments validated', totalSegments);
|
|
101
|
+
this.logValidationMetrics(metrics);
|
|
102
|
+
}
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
|
|
104
|
+
logValidationMetrics(metrics) {
|
|
105
|
+
let logs = [];
|
|
106
|
+
for (let key in metrics) {
|
|
107
|
+
logs.push(`${key}=${chalk_1.default.yellow(metrics[key].toString())}`);
|
|
108
|
+
}
|
|
109
|
+
this.event.program.logger.debug(`Validation Metrics (Scope: ${this.event.scope.name}): ${logs.join(', ')}`);
|
|
110
|
+
let kindsLogs = [];
|
|
111
|
+
const kindsArray = Array.from(this.validationKindsMetrics.keys()).sort();
|
|
112
|
+
for (let key of kindsArray) {
|
|
113
|
+
const timeData = this.validationKindsMetrics.get(key);
|
|
114
|
+
kindsLogs.push(`${key}=${chalk_1.default.yellow(timeData.timeMs.toFixed(3).toString()) + 'ms'} (${timeData.count})`);
|
|
115
|
+
}
|
|
116
|
+
this.event.program.logger.debug(`Validation Walk Metrics (Scope: ${this.event.scope.name}): ${kindsLogs.join(', ')}`);
|
|
117
|
+
}
|
|
118
|
+
reset() {
|
|
119
|
+
this.event = undefined;
|
|
120
|
+
}
|
|
121
|
+
walkFiles() {
|
|
122
|
+
const hasChangeInfo = this.event.changedFiles && this.event.changedSymbols;
|
|
123
|
+
//do many per-file checks for every file in this (and parent) scopes
|
|
124
|
+
this.event.scope.enumerateBrsFiles((file) => {
|
|
125
|
+
if (!(0, reflection_1.isBrsFile)(file)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const thisFileHasChanges = this.event.changedFiles.includes(file);
|
|
129
|
+
if (thisFileHasChanges || this.doesFileProvideChangedSymbol(file, this.event.changedSymbols)) {
|
|
130
|
+
this.diagnosticDetectFunctionCollisions(file);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
const fileWalkStopWatch = new Stopwatch_1.Stopwatch();
|
|
134
|
+
this.event.scope.enumerateOwnFiles((file) => {
|
|
135
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
136
|
+
if (this.event.program.diagnostics.shouldFilterFile(file)) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
fileWalkStopWatch.reset();
|
|
140
|
+
fileWalkStopWatch.start();
|
|
141
|
+
const fileUri = util_1.util.pathToUri(file.srcPath);
|
|
142
|
+
const thisFileHasChanges = this.event.changedFiles.includes(file);
|
|
143
|
+
const hasUnvalidatedSegments = file.validationSegmenter.hasUnvalidatedSegments();
|
|
144
|
+
if (hasChangeInfo && !hasUnvalidatedSegments) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const validationVisitor = (0, visitors_1.createVisitor)({
|
|
148
|
+
VariableExpression: (varExpr) => {
|
|
149
|
+
this.addValidationKindMetric('VariableExpression', () => {
|
|
150
|
+
this.validateVariableAndDottedGetExpressions(file, varExpr);
|
|
151
|
+
});
|
|
152
|
+
},
|
|
153
|
+
DottedGetExpression: (dottedGet) => {
|
|
154
|
+
this.addValidationKindMetric('DottedGetExpression', () => {
|
|
155
|
+
this.validateVariableAndDottedGetExpressions(file, dottedGet);
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
CallExpression: (functionCall) => {
|
|
159
|
+
this.addValidationKindMetric('CallExpression', () => {
|
|
160
|
+
this.validateCallExpression(file, functionCall);
|
|
161
|
+
this.validateCreateObjectCall(file, functionCall);
|
|
162
|
+
this.validateComponentMethods(file, functionCall);
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
CallfuncExpression: (functionCall) => {
|
|
166
|
+
this.addValidationKindMetric('CallfuncExpression', () => {
|
|
167
|
+
this.validateCallFuncExpression(file, functionCall);
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
ReturnStatement: (returnStatement) => {
|
|
171
|
+
this.addValidationKindMetric('ReturnStatement', () => {
|
|
172
|
+
this.validateReturnStatement(file, returnStatement);
|
|
173
|
+
});
|
|
174
|
+
},
|
|
175
|
+
DottedSetStatement: (dottedSetStmt) => {
|
|
176
|
+
this.addValidationKindMetric('DottedSetStatement', () => {
|
|
177
|
+
this.validateDottedSetStatement(file, dottedSetStmt);
|
|
178
|
+
});
|
|
179
|
+
},
|
|
180
|
+
BinaryExpression: (binaryExpr) => {
|
|
181
|
+
this.addValidationKindMetric('BinaryExpression', () => {
|
|
182
|
+
this.validateBinaryExpression(file, binaryExpr);
|
|
183
|
+
});
|
|
184
|
+
},
|
|
185
|
+
UnaryExpression: (unaryExpr) => {
|
|
186
|
+
this.addValidationKindMetric('UnaryExpression', () => {
|
|
187
|
+
this.validateUnaryExpression(file, unaryExpr);
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
AssignmentStatement: (assignStmt) => {
|
|
191
|
+
this.addValidationKindMetric('AssignmentStatement', () => {
|
|
192
|
+
var _a;
|
|
193
|
+
this.validateAssignmentStatement(file, assignStmt);
|
|
194
|
+
// Note: this also includes For statements
|
|
195
|
+
this.detectShadowedLocalVar(file, {
|
|
196
|
+
expr: assignStmt,
|
|
197
|
+
name: assignStmt.tokens.name.text,
|
|
198
|
+
type: this.getNodeTypeWrapper(file, assignStmt, { flags: 1 /* SymbolTypeFlag.runtime */ }),
|
|
199
|
+
nameRange: (_a = assignStmt.tokens.name.location) === null || _a === void 0 ? void 0 : _a.range
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
},
|
|
203
|
+
AugmentedAssignmentStatement: (binaryExpr) => {
|
|
204
|
+
this.addValidationKindMetric('AugmentedAssignmentStatement', () => {
|
|
205
|
+
this.validateBinaryExpression(file, binaryExpr);
|
|
206
|
+
});
|
|
207
|
+
},
|
|
208
|
+
IncrementStatement: (stmt) => {
|
|
209
|
+
this.addValidationKindMetric('IncrementStatement', () => {
|
|
210
|
+
this.validateIncrementStatement(file, stmt);
|
|
211
|
+
});
|
|
212
|
+
},
|
|
213
|
+
NewExpression: (newExpr) => {
|
|
214
|
+
this.addValidationKindMetric('NewExpression', () => {
|
|
215
|
+
this.validateNewExpression(file, newExpr);
|
|
216
|
+
});
|
|
217
|
+
},
|
|
218
|
+
ForEachStatement: (forEachStmt) => {
|
|
219
|
+
this.addValidationKindMetric('ForEachStatement', () => {
|
|
220
|
+
var _a;
|
|
221
|
+
this.detectShadowedLocalVar(file, {
|
|
222
|
+
expr: forEachStmt,
|
|
223
|
+
name: forEachStmt.tokens.item.text,
|
|
224
|
+
type: this.getNodeTypeWrapper(file, forEachStmt, { flags: 1 /* SymbolTypeFlag.runtime */ }),
|
|
225
|
+
nameRange: (_a = forEachStmt.tokens.item.location) === null || _a === void 0 ? void 0 : _a.range
|
|
226
|
+
});
|
|
227
|
+
this.validateForEachStatement(file, forEachStmt);
|
|
228
|
+
});
|
|
229
|
+
},
|
|
230
|
+
FunctionParameterExpression: (funcParam) => {
|
|
231
|
+
this.addValidationKindMetric('FunctionParameterExpression', () => {
|
|
232
|
+
var _a;
|
|
233
|
+
this.detectShadowedLocalVar(file, {
|
|
234
|
+
expr: funcParam,
|
|
235
|
+
name: funcParam.tokens.name.text,
|
|
236
|
+
type: this.getNodeTypeWrapper(file, funcParam, { flags: 1 /* SymbolTypeFlag.runtime */ }),
|
|
237
|
+
nameRange: (_a = funcParam.tokens.name.location) === null || _a === void 0 ? void 0 : _a.range
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
FunctionExpression: (func) => {
|
|
242
|
+
if (file.isTypedef) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
this.addValidationKindMetric('FunctionExpression', () => {
|
|
246
|
+
this.validateFunctionExpressionForReturn(func);
|
|
247
|
+
});
|
|
248
|
+
},
|
|
249
|
+
ForStatement: (forStmt) => {
|
|
250
|
+
this.addValidationKindMetric('ForStatement', () => {
|
|
251
|
+
this.validateForStatement(file, forStmt);
|
|
252
|
+
});
|
|
253
|
+
},
|
|
254
|
+
AstNode: (node) => {
|
|
255
|
+
//check for doc comments
|
|
256
|
+
if (!node.leadingTrivia || node.leadingTrivia.filter(triviaToken => triviaToken.kind === TokenKind_1.TokenKind.Comment).length === 0) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
this.addValidationKindMetric('AstNode', () => {
|
|
260
|
+
this.validateDocComments(node);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
// validate only what's needed in the file
|
|
265
|
+
const segmentsToWalkForValidation = thisFileHasChanges
|
|
266
|
+
? file.validationSegmenter.getAllUnvalidatedSegments()
|
|
267
|
+
: file.validationSegmenter.getSegmentsWithChangedSymbols(this.event.changedSymbols);
|
|
268
|
+
let segmentsValidated = 0;
|
|
269
|
+
if (thisFileHasChanges) {
|
|
270
|
+
// clear all ScopeValidatorSegment diagnostics for this file
|
|
271
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: fileUri, tag: "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ });
|
|
272
|
+
}
|
|
273
|
+
for (const segment of segmentsToWalkForValidation) {
|
|
274
|
+
if (!thisFileHasChanges && !file.validationSegmenter.checkIfSegmentNeedsRevalidation(segment, this.event.changedSymbols)) {
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
this.currentSegmentBeingValidated = segment;
|
|
278
|
+
if (!thisFileHasChanges) {
|
|
279
|
+
// just clear the affected diagnostics
|
|
280
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: fileUri, segment: segment, tag: "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ });
|
|
281
|
+
}
|
|
282
|
+
segmentsValidated++;
|
|
283
|
+
segment.walk(validationVisitor, {
|
|
284
|
+
walkMode: AstValidationSegmenter_1.InsideSegmentWalkMode
|
|
285
|
+
});
|
|
286
|
+
file.markSegmentAsValidated(segment);
|
|
287
|
+
this.currentSegmentBeingValidated = null;
|
|
288
|
+
}
|
|
289
|
+
fileWalkStopWatch.stop();
|
|
290
|
+
const timeString = fileWalkStopWatch.getDurationText();
|
|
291
|
+
this.segmentsMetrics.set(file.pkgPath, { segments: segmentsValidated, time: timeString });
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
addValidationKindMetric(name, funcToTime) {
|
|
296
|
+
if (!this.validationKindsMetrics.has(name)) {
|
|
297
|
+
this.validationKindsMetrics.set(name, { timeMs: 0, count: 0 });
|
|
298
|
+
}
|
|
299
|
+
const timeData = this.validationKindsMetrics.get(name);
|
|
300
|
+
const validationKindStopWatch = new Stopwatch_1.Stopwatch();
|
|
301
|
+
validationKindStopWatch.start();
|
|
302
|
+
funcToTime();
|
|
303
|
+
validationKindStopWatch.stop();
|
|
304
|
+
this.validationKindsMetrics.set(name, { timeMs: timeData.timeMs + validationKindStopWatch.totalMilliseconds, count: timeData.count + 1 });
|
|
305
|
+
}
|
|
306
|
+
doesFileProvideChangedSymbol(file, changedSymbols) {
|
|
307
|
+
if (!changedSymbols) {
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
for (const flag of [1 /* SymbolTypeFlag.runtime */, 2 /* SymbolTypeFlag.typetime */]) {
|
|
311
|
+
const providedSymbolKeysFlag = file.providedSymbols.symbolMap.get(flag).keys();
|
|
312
|
+
const changedSymbolSetForFlag = changedSymbols.get(flag);
|
|
313
|
+
for (let providedKey of providedSymbolKeysFlag) {
|
|
314
|
+
if (changedSymbolSetForFlag.has(providedKey)) {
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
isTypeKnown(exprType) {
|
|
322
|
+
let isKnownType = exprType === null || exprType === void 0 ? void 0 : exprType.isResolvable();
|
|
323
|
+
return isKnownType;
|
|
324
|
+
}
|
|
325
|
+
getCircularReference(exprType) {
|
|
326
|
+
if (exprType === null || exprType === void 0 ? void 0 : exprType.isResolvable()) {
|
|
327
|
+
return { isCircularReference: false };
|
|
328
|
+
}
|
|
329
|
+
if ((0, reflection_1.isReferenceType)(exprType)) {
|
|
330
|
+
const info = exprType.getCircularReferenceInfo();
|
|
331
|
+
return info;
|
|
332
|
+
}
|
|
333
|
+
return { isCircularReference: false };
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* If this is the lhs of an assignment, we don't need to flag it as unresolved
|
|
337
|
+
*/
|
|
338
|
+
hasValidDeclaration(expression, exprType, definingNode) {
|
|
339
|
+
var _a, _b;
|
|
340
|
+
if (!(0, reflection_1.isVariableExpression)(expression)) {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
let assignmentAncestor;
|
|
344
|
+
if ((0, reflection_1.isAssignmentStatement)(definingNode) && definingNode.tokens.equals.kind === TokenKind_1.TokenKind.Equal) {
|
|
345
|
+
// this symbol was defined in a "normal" assignment (eg. not a compound assignment)
|
|
346
|
+
assignmentAncestor = definingNode;
|
|
347
|
+
return ((_a = assignmentAncestor === null || assignmentAncestor === void 0 ? void 0 : assignmentAncestor.tokens.name) === null || _a === void 0 ? void 0 : _a.text.toLowerCase()) === ((_b = expression === null || expression === void 0 ? void 0 : expression.tokens.name) === null || _b === void 0 ? void 0 : _b.text.toLowerCase());
|
|
348
|
+
}
|
|
349
|
+
else if ((0, reflection_1.isFunctionParameterExpression)(definingNode)) {
|
|
350
|
+
// this symbol was defined in a function param
|
|
351
|
+
return true;
|
|
352
|
+
}
|
|
353
|
+
else {
|
|
354
|
+
assignmentAncestor = expression === null || expression === void 0 ? void 0 : expression.findAncestor(reflection_1.isAssignmentStatement);
|
|
355
|
+
}
|
|
356
|
+
return (assignmentAncestor === null || assignmentAncestor === void 0 ? void 0 : assignmentAncestor.tokens.name) === (expression === null || expression === void 0 ? void 0 : expression.tokens.name) && (0, reflection_1.isUnionType)(exprType);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Validate every function call to `CreateObject`.
|
|
360
|
+
* Ideally we would create better type checking/handling for this, but in the mean time, we know exactly
|
|
361
|
+
* what these calls are supposed to look like, and this is a very common thing for brs devs to do, so just
|
|
362
|
+
* do this manually for now.
|
|
363
|
+
*/
|
|
364
|
+
validateCreateObjectCall(file, call) {
|
|
365
|
+
var _a, _b, _c, _d, _e;
|
|
366
|
+
//skip non CreateObject function calls
|
|
367
|
+
const callName = (_a = util_1.util.getAllDottedGetPartsAsString(call.callee)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
368
|
+
if (callName !== 'createobject' || !(0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[0])) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const firstParamToken = (_c = (_b = call === null || call === void 0 ? void 0 : call.args[0]) === null || _b === void 0 ? void 0 : _b.tokens) === null || _c === void 0 ? void 0 : _c.value;
|
|
372
|
+
const firstParamStringValue = (_d = firstParamToken === null || firstParamToken === void 0 ? void 0 : firstParamToken.text) === null || _d === void 0 ? void 0 : _d.replace(/"/g, '');
|
|
373
|
+
if (!firstParamStringValue) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const firstParamStringValueLower = firstParamStringValue.toLowerCase();
|
|
377
|
+
//if this is a `createObject('roSGNode'` call, only support known sg node types
|
|
378
|
+
if (firstParamStringValueLower === 'rosgnode' && (0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[1])) {
|
|
379
|
+
const componentName = (_e = call === null || call === void 0 ? void 0 : call.args[1]) === null || _e === void 0 ? void 0 : _e.tokens.value;
|
|
380
|
+
this.checkComponentName(componentName);
|
|
381
|
+
if ((call === null || call === void 0 ? void 0 : call.args.length) !== 2) {
|
|
382
|
+
// roSgNode should only ever have 2 args in `createObject`
|
|
383
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, [2], call === null || call === void 0 ? void 0 : call.args.length)), { location: call.location }));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
else if (!platformComponentNames.has(firstParamStringValueLower)) {
|
|
387
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownBrightScriptComponent(firstParamStringValue)), { location: firstParamToken.location }));
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
// This is valid brightscript component
|
|
391
|
+
// Test for invalid arg counts
|
|
392
|
+
const brightScriptComponent = roku_types_1.components[firstParamStringValueLower];
|
|
393
|
+
// Valid arg counts for createObject are 1+ number of args for constructor
|
|
394
|
+
let validArgCounts = brightScriptComponent === null || brightScriptComponent === void 0 ? void 0 : brightScriptComponent.constructors.map(cnstr => cnstr.params.length + 1);
|
|
395
|
+
if (validArgCounts.length === 0) {
|
|
396
|
+
// no constructors for this component, so createObject only takes 1 arg
|
|
397
|
+
validArgCounts = [1];
|
|
398
|
+
}
|
|
399
|
+
if (!validArgCounts.includes(call === null || call === void 0 ? void 0 : call.args.length)) {
|
|
400
|
+
// Incorrect number of arguments included in `createObject()`
|
|
401
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchCreateObjectArgumentCount(firstParamStringValue, validArgCounts, call === null || call === void 0 ? void 0 : call.args.length)), { location: call.location }));
|
|
402
|
+
}
|
|
403
|
+
// Test for deprecation
|
|
404
|
+
if (brightScriptComponent === null || brightScriptComponent === void 0 ? void 0 : brightScriptComponent.isDeprecated) {
|
|
405
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemIsDeprecated(firstParamStringValue, brightScriptComponent.deprecatedDescription)), { location: call.location }));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
checkComponentName(componentName) {
|
|
410
|
+
var _a, _b;
|
|
411
|
+
//don't validate any components with a colon in their name (probably component libraries, but regular components can have them too).
|
|
412
|
+
if (!componentName || ((_a = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _a === void 0 ? void 0 : _a.includes(':'))) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
//add diagnostic for unknown components
|
|
416
|
+
const unquotedComponentName = (_b = componentName === null || componentName === void 0 ? void 0 : componentName.text) === null || _b === void 0 ? void 0 : _b.replace(/"/g, '');
|
|
417
|
+
if (unquotedComponentName && !platformNodeNames.has(unquotedComponentName.toLowerCase()) && !this.event.program.getComponent(unquotedComponentName)) {
|
|
418
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unknownRoSGNode(unquotedComponentName)), { location: componentName.location }));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Validate every method call to `component.callfunc()`, `component.createChild()`, etc.
|
|
423
|
+
*/
|
|
424
|
+
validateComponentMethods(file, call) {
|
|
425
|
+
var _a, _b, _c, _d, _e;
|
|
426
|
+
const lowerMethodNamesChecked = ['callfunc', 'createchild'];
|
|
427
|
+
if (!(0, reflection_1.isDottedGetExpression)(call.callee)) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
const callName = (_c = (_b = (_a = call.callee.tokens) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.text) === null || _c === void 0 ? void 0 : _c.toLowerCase();
|
|
431
|
+
if (!callName || !lowerMethodNamesChecked.includes(callName) || !(0, reflection_1.isLiteralExpression)(call === null || call === void 0 ? void 0 : call.args[0])) {
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
const callerType = (_d = call.callee.obj) === null || _d === void 0 ? void 0 : _d.getType({ flags: 1 /* SymbolTypeFlag.runtime */ });
|
|
435
|
+
if (!(0, reflection_1.isCallFuncableTypeLike)(callerType)) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
const firstArgToken = (_e = call === null || call === void 0 ? void 0 : call.args[0]) === null || _e === void 0 ? void 0 : _e.tokens.value;
|
|
439
|
+
if (callName === 'createchild') {
|
|
440
|
+
this.checkComponentName(firstArgToken);
|
|
441
|
+
}
|
|
442
|
+
else if (callName === 'callfunc' && !util_1.util.isGenericNodeType(callerType)) {
|
|
443
|
+
const funcType = util_1.util.getCallFuncType(call, firstArgToken, { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: true });
|
|
444
|
+
if (!(funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable())) {
|
|
445
|
+
const functionName = firstArgToken.text.replace(/"/g, '');
|
|
446
|
+
const functionFullname = `${callerType.toString()}@.${functionName}`;
|
|
447
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction(functionName, functionFullname, callerType.toString())), { location: firstArgToken === null || firstArgToken === void 0 ? void 0 : firstArgToken.location }));
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
this.validateFunctionCall(file, call, funcType, firstArgToken.location, call.args, 1);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
validateCallExpression(file, expression) {
|
|
455
|
+
var _a;
|
|
456
|
+
const getTypeOptions = { flags: 1 /* SymbolTypeFlag.runtime */, data: {} };
|
|
457
|
+
let funcType = this.getNodeTypeWrapper(file, expression === null || expression === void 0 ? void 0 : expression.callee, getTypeOptions);
|
|
458
|
+
if ((funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable()) && (0, reflection_1.isClassType)(funcType)) {
|
|
459
|
+
// We're calling a class - get the constructor
|
|
460
|
+
funcType = funcType.getMemberType('new', getTypeOptions);
|
|
461
|
+
}
|
|
462
|
+
const callErrorLocation = (_a = expression === null || expression === void 0 ? void 0 : expression.callee) === null || _a === void 0 ? void 0 : _a.location;
|
|
463
|
+
return this.validateFunctionCall(file, expression.callee, funcType, callErrorLocation, expression.args);
|
|
464
|
+
}
|
|
465
|
+
validateCallFuncExpression(file, expression) {
|
|
466
|
+
var _a, _b;
|
|
467
|
+
const callerType = (_a = expression.callee) === null || _a === void 0 ? void 0 : _a.getType({ flags: 1 /* SymbolTypeFlag.runtime */ });
|
|
468
|
+
if ((0, reflection_1.isDynamicType)(callerType)) {
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const methodToken = expression.tokens.methodName;
|
|
472
|
+
const methodName = (_b = methodToken === null || methodToken === void 0 ? void 0 : methodToken.text) !== null && _b !== void 0 ? _b : '';
|
|
473
|
+
const functionFullname = `${callerType.toString()}@.${methodName}`;
|
|
474
|
+
const callErrorLocation = expression.location;
|
|
475
|
+
if (util_1.util.isGenericNodeType(callerType) || (0, reflection_1.isObjectType)(callerType) || (0, reflection_1.isDynamicType)(callerType)) {
|
|
476
|
+
// ignore "general" node
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
const funcType = util_1.util.getCallFuncType(expression, methodToken, { flags: 1 /* SymbolTypeFlag.runtime */, ignoreCall: true });
|
|
480
|
+
if (!(funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable())) {
|
|
481
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindCallFuncFunction(methodName, functionFullname, callerType.toString())), { location: callErrorLocation }));
|
|
482
|
+
}
|
|
483
|
+
return this.validateFunctionCall(file, expression, funcType, callErrorLocation, expression.args);
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Detect calls to functions with the incorrect number of parameters, or wrong types of arguments
|
|
487
|
+
*/
|
|
488
|
+
validateFunctionCall(file, callee, funcType, callErrorLocation, args, argOffset = 0) {
|
|
489
|
+
var _a, _b, _c;
|
|
490
|
+
if (!(funcType === null || funcType === void 0 ? void 0 : funcType.isResolvable()) || !(0, reflection_1.isCallableType)(funcType)) {
|
|
491
|
+
const funcName = util_1.util.getAllDottedGetPartsAsString(callee, Parser_1.ParseMode.BrighterScript, (0, reflection_1.isCallfuncExpression)(callee) ? '@.' : '.');
|
|
492
|
+
if ((0, reflection_1.isUnionType)(funcType)) {
|
|
493
|
+
if (!util_1.util.isUnionOfFunctions(funcType) && !(0, reflection_1.isCallfuncExpression)(callee)) {
|
|
494
|
+
// union of func and non func. not callable
|
|
495
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.notCallable(funcName)), { location: callErrorLocation }));
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
const callablesInUnion = funcType.types.filter(reflection_1.isCallableType);
|
|
499
|
+
const funcsInUnion = callablesInUnion.filter(reflection_1.isTypedFunctionType);
|
|
500
|
+
if (funcsInUnion.length < callablesInUnion.length) {
|
|
501
|
+
// potentially a non-typed func in union
|
|
502
|
+
// cannot validate
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
// check all funcs to see if they work
|
|
506
|
+
for (let i = 1; i < funcsInUnion.length; i++) {
|
|
507
|
+
const compatibilityData = {};
|
|
508
|
+
if (!funcsInUnion[0].isTypeCompatible(funcsInUnion[i], compatibilityData)) {
|
|
509
|
+
if (!compatibilityData.returnTypeMismatch) {
|
|
510
|
+
// param differences!
|
|
511
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incompatibleSymbolDefinition(funcName, { isUnion: true, data: compatibilityData })), { location: callErrorLocation }));
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
// The only thing different was return type
|
|
517
|
+
funcType = util_1.util.getFunctionTypeFromUnion(funcType);
|
|
518
|
+
}
|
|
519
|
+
if (funcType && !(0, reflection_1.isCallableType)(funcType) && !(0, reflection_1.isReferenceType)(funcType)) {
|
|
520
|
+
const globalFuncWithVarName = globalCallables_1.globalCallableMap.get(funcName.toLowerCase());
|
|
521
|
+
if (globalFuncWithVarName) {
|
|
522
|
+
funcType = globalFuncWithVarName.type;
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
525
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.notCallable(funcName)), { location: callErrorLocation }));
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
if (!(0, reflection_1.isTypedFunctionType)(funcType)) {
|
|
531
|
+
// non typed function. nothing to check
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
//get min/max parameter count for callable
|
|
535
|
+
let minParams = 0;
|
|
536
|
+
let maxParams = 0;
|
|
537
|
+
for (let param of funcType.params) {
|
|
538
|
+
maxParams++;
|
|
539
|
+
//optional parameters must come last, so we can assume that minParams won't increase once we hit
|
|
540
|
+
//the first isOptional
|
|
541
|
+
if (param.isOptional !== true) {
|
|
542
|
+
minParams++;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
if (funcType.isVariadic) {
|
|
546
|
+
// function accepts variable number of arguments
|
|
547
|
+
maxParams = Expression_1.CallExpression.MaximumArguments;
|
|
548
|
+
}
|
|
549
|
+
const argsForCall = argOffset < 1 ? args : args.slice(argOffset);
|
|
550
|
+
let expCallArgCount = argsForCall.length;
|
|
551
|
+
if (expCallArgCount > maxParams || expCallArgCount < minParams) {
|
|
552
|
+
let minMaxParamsText = minParams === maxParams ? maxParams + argOffset : `${minParams + argOffset}-${maxParams + argOffset}`;
|
|
553
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchArgumentCount(minMaxParamsText, expCallArgCount + argOffset)), { location: callErrorLocation }));
|
|
554
|
+
}
|
|
555
|
+
let paramIndex = 0;
|
|
556
|
+
for (let arg of argsForCall) {
|
|
557
|
+
const data = {};
|
|
558
|
+
let argType = this.getNodeTypeWrapper(file, arg, { flags: 1 /* SymbolTypeFlag.runtime */, data: data });
|
|
559
|
+
const paramType = (_a = funcType.params[paramIndex]) === null || _a === void 0 ? void 0 : _a.type;
|
|
560
|
+
if (!paramType) {
|
|
561
|
+
// unable to find a paramType -- maybe there are more args than params
|
|
562
|
+
break;
|
|
563
|
+
}
|
|
564
|
+
if ((0, reflection_1.isCallableType)(paramType) && (0, reflection_1.isClassType)(argType) && (0, reflection_1.isClassStatement)(data.definingNode)) {
|
|
565
|
+
argType = data.definingNode.getConstructorType();
|
|
566
|
+
}
|
|
567
|
+
const compatibilityData = {};
|
|
568
|
+
const isAllowedArgConversion = this.checkAllowedArgConversions(paramType, argType);
|
|
569
|
+
if (!isAllowedArgConversion && !(paramType === null || paramType === void 0 ? void 0 : paramType.isTypeCompatible(argType, compatibilityData))) {
|
|
570
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.argumentTypeMismatch((_b = argType === null || argType === void 0 ? void 0 : argType.toString()) !== null && _b !== void 0 ? _b : 'unknown', (_c = paramType === null || paramType === void 0 ? void 0 : paramType.toString()) !== null && _c !== void 0 ? _c : 'unknown', compatibilityData)), { location: arg.location }));
|
|
571
|
+
}
|
|
572
|
+
paramIndex++;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
checkAllowedArgConversions(paramType, argType) {
|
|
576
|
+
if ((0, reflection_1.isNumberTypeLike)(argType) && (0, reflection_1.isBooleanTypeLike)(paramType)) {
|
|
577
|
+
return true;
|
|
578
|
+
}
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Detect return statements with incompatible types vs. declared return type
|
|
583
|
+
*/
|
|
584
|
+
validateReturnStatement(file, returnStmt) {
|
|
585
|
+
var _a, _b, _c;
|
|
586
|
+
const data = {};
|
|
587
|
+
const getTypeOptions = { flags: 1 /* SymbolTypeFlag.runtime */, data: data };
|
|
588
|
+
let funcType = (_a = returnStmt.findAncestor(reflection_1.isFunctionExpression)) === null || _a === void 0 ? void 0 : _a.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
|
|
589
|
+
if ((0, reflection_1.isTypedFunctionType)(funcType)) {
|
|
590
|
+
let actualReturnType = (returnStmt === null || returnStmt === void 0 ? void 0 : returnStmt.value)
|
|
591
|
+
? this.getNodeTypeWrapper(file, returnStmt === null || returnStmt === void 0 ? void 0 : returnStmt.value, getTypeOptions)
|
|
592
|
+
: VoidType_1.VoidType.instance;
|
|
593
|
+
const compatibilityData = {};
|
|
594
|
+
// `return` statement by itself in non-built-in function will actually result in `invalid`
|
|
595
|
+
const valueReturnType = (0, reflection_1.isVoidType)(actualReturnType) ? InvalidType_1.InvalidType.instance : actualReturnType;
|
|
596
|
+
if (funcType.returnType.isResolvable()) {
|
|
597
|
+
if (!(returnStmt === null || returnStmt === void 0 ? void 0 : returnStmt.value) && (0, reflection_1.isVoidType)(funcType.returnType)) {
|
|
598
|
+
// allow empty return when function is return `as void`
|
|
599
|
+
// eslint-disable-next-line no-useless-return
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
else if (!funcType.returnType.isTypeCompatible(valueReturnType, compatibilityData)) {
|
|
603
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.returnTypeMismatch(actualReturnType.toString(), funcType.returnType.toString(), compatibilityData)), { location: (_c = (_b = returnStmt.value) === null || _b === void 0 ? void 0 : _b.location) !== null && _c !== void 0 ? _c : returnStmt.location }));
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Detect assigned type different from expected member type
|
|
610
|
+
*/
|
|
611
|
+
validateDottedSetStatement(file, dottedSetStmt) {
|
|
612
|
+
var _a, _b, _c;
|
|
613
|
+
const typeChainExpectedLHS = [];
|
|
614
|
+
const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
|
|
615
|
+
const expectedLHSType = this.getNodeTypeWrapper(file, dottedSetStmt, Object.assign(Object.assign({}, getTypeOpts), { data: {}, typeChain: typeChainExpectedLHS }));
|
|
616
|
+
const actualRHSType = this.getNodeTypeWrapper(file, dottedSetStmt === null || dottedSetStmt === void 0 ? void 0 : dottedSetStmt.value, getTypeOpts);
|
|
617
|
+
const compatibilityData = {};
|
|
618
|
+
const typeChainScan = util_1.util.processTypeChain(typeChainExpectedLHS);
|
|
619
|
+
// check if anything in typeChain is an AA - if so, just allow it
|
|
620
|
+
if (typeChainExpectedLHS.find(typeChainItem => (0, reflection_1.isAssociativeArrayType)(typeChainItem.type))) {
|
|
621
|
+
// something in the chain is an AA
|
|
622
|
+
// treat members as dynamic - they could have been set without the type system's knowledge
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
if (!expectedLHSType || !(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isResolvable())) {
|
|
626
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
let accessibilityIsOk = this.checkMemberAccessibility(file, dottedSetStmt, typeChainExpectedLHS);
|
|
630
|
+
//Most Component fields can be set with strings
|
|
631
|
+
//TODO: be more precise about which fields can actually accept strings
|
|
632
|
+
//TODO: if RHS is a string literal, we can do more validation to make sure it's the correct type
|
|
633
|
+
if ((0, reflection_1.isComponentType)((_a = dottedSetStmt.obj) === null || _a === void 0 ? void 0 : _a.getType({ flags: 1 /* SymbolTypeFlag.runtime */ }))) {
|
|
634
|
+
if ((0, reflection_1.isStringTypeLike)(actualRHSType)) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (accessibilityIsOk && !(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isTypeCompatible(actualRHSType, compatibilityData))) {
|
|
639
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch((_b = actualRHSType === null || actualRHSType === void 0 ? void 0 : actualRHSType.toString()) !== null && _b !== void 0 ? _b : 'unknown', (_c = expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.toString()) !== null && _c !== void 0 ? _c : 'unknown', compatibilityData)), { location: dottedSetStmt.location }));
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Detect when declared type does not match rhs type
|
|
644
|
+
*/
|
|
645
|
+
validateAssignmentStatement(file, assignStmt) {
|
|
646
|
+
if (!(assignStmt === null || assignStmt === void 0 ? void 0 : assignStmt.typeExpression)) {
|
|
647
|
+
// nothing to check
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
650
|
+
const typeChainExpectedLHS = [];
|
|
651
|
+
const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
|
|
652
|
+
const expectedLHSType = this.getNodeTypeWrapper(file, assignStmt.typeExpression, Object.assign(Object.assign({}, getTypeOpts), { data: {}, typeChain: typeChainExpectedLHS }));
|
|
653
|
+
const actualRHSType = this.getNodeTypeWrapper(file, assignStmt.value, getTypeOpts);
|
|
654
|
+
const compatibilityData = {};
|
|
655
|
+
if (!expectedLHSType || !expectedLHSType.isResolvable()) {
|
|
656
|
+
// LHS is not resolvable... handled elsewhere
|
|
657
|
+
}
|
|
658
|
+
else if (!(expectedLHSType === null || expectedLHSType === void 0 ? void 0 : expectedLHSType.isTypeCompatible(actualRHSType, compatibilityData))) {
|
|
659
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(actualRHSType.toString(), expectedLHSType.toString(), compatibilityData)), { location: assignStmt.location }));
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Detect invalid use of a binary operator
|
|
664
|
+
*/
|
|
665
|
+
validateBinaryExpression(file, binaryExpr) {
|
|
666
|
+
const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
|
|
667
|
+
if (util_1.util.isInTypeExpression(binaryExpr)) {
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
let leftType = (0, reflection_1.isBinaryExpression)(binaryExpr)
|
|
671
|
+
? this.getNodeTypeWrapper(file, binaryExpr.left, getTypeOpts)
|
|
672
|
+
: this.getNodeTypeWrapper(file, binaryExpr.item, getTypeOpts);
|
|
673
|
+
let rightType = (0, reflection_1.isBinaryExpression)(binaryExpr)
|
|
674
|
+
? this.getNodeTypeWrapper(file, binaryExpr.right, getTypeOpts)
|
|
675
|
+
: this.getNodeTypeWrapper(file, binaryExpr.value, getTypeOpts);
|
|
676
|
+
if (!leftType || !rightType || !leftType.isResolvable() || !rightType.isResolvable()) {
|
|
677
|
+
// Can not find the type. error handled elsewhere
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
let leftTypeToTest = leftType;
|
|
681
|
+
let rightTypeToTest = rightType;
|
|
682
|
+
if ((0, reflection_1.isEnumMemberType)(leftType) || (0, reflection_1.isEnumType)(leftType)) {
|
|
683
|
+
leftTypeToTest = leftType.underlyingType;
|
|
684
|
+
}
|
|
685
|
+
if ((0, reflection_1.isEnumMemberType)(rightType) || (0, reflection_1.isEnumType)(rightType)) {
|
|
686
|
+
rightTypeToTest = rightType.underlyingType;
|
|
687
|
+
}
|
|
688
|
+
if ((0, reflection_1.isUnionType)(leftType) || (0, reflection_1.isUnionType)(rightType)) {
|
|
689
|
+
// TODO: it is possible to validate based on innerTypes, but more complicated
|
|
690
|
+
// Because you need to verify each combination of types
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
const opResult = util_1.util.binaryOperatorResultType(leftTypeToTest, binaryExpr.tokens.operator, rightTypeToTest);
|
|
694
|
+
if (!opResult) {
|
|
695
|
+
// if the result was dynamic or void, that means there wasn't a valid operation
|
|
696
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(binaryExpr.tokens.operator.text, leftType.toString(), rightType.toString())), { location: binaryExpr.location }));
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* Detect invalid use of a Unary operator
|
|
701
|
+
*/
|
|
702
|
+
validateUnaryExpression(file, unaryExpr) {
|
|
703
|
+
const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
|
|
704
|
+
let rightType = this.getNodeTypeWrapper(file, unaryExpr.right, getTypeOpts);
|
|
705
|
+
if (!rightType.isResolvable()) {
|
|
706
|
+
// Can not find the type. error handled elsewhere
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
let rightTypeToTest = rightType;
|
|
710
|
+
if ((0, reflection_1.isEnumMemberType)(rightType)) {
|
|
711
|
+
rightTypeToTest = rightType.underlyingType;
|
|
712
|
+
}
|
|
713
|
+
if ((0, reflection_1.isUnionType)(rightTypeToTest)) {
|
|
714
|
+
// TODO: it is possible to validate based on innerTypes, but more complicated
|
|
715
|
+
// Because you need to verify each combination of types
|
|
716
|
+
}
|
|
717
|
+
else if ((0, reflection_1.isDynamicType)(rightTypeToTest) || (0, reflection_1.isObjectType)(rightTypeToTest)) {
|
|
718
|
+
// operand is basically "any" type... ignore;
|
|
719
|
+
}
|
|
720
|
+
else if ((0, reflection_1.isPrimitiveType)(rightType)) {
|
|
721
|
+
const opResult = util_1.util.unaryOperatorResultType(unaryExpr.tokens.operator, rightTypeToTest);
|
|
722
|
+
if (!opResult) {
|
|
723
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(unaryExpr.tokens.operator.text, rightType.toString())), { location: unaryExpr.location }));
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
// rhs is not a primitive, so no binary operator is allowed
|
|
728
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(unaryExpr.tokens.operator.text, rightType.toString())), { location: unaryExpr.location }));
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
validateIncrementStatement(file, incStmt) {
|
|
732
|
+
const getTypeOpts = { flags: 1 /* SymbolTypeFlag.runtime */ };
|
|
733
|
+
let rightType = this.getNodeTypeWrapper(file, incStmt.value, getTypeOpts);
|
|
734
|
+
if (!rightType.isResolvable()) {
|
|
735
|
+
// Can not find the type. error handled elsewhere
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
if ((0, reflection_1.isUnionType)(rightType)) {
|
|
739
|
+
// TODO: it is possible to validate based on innerTypes, but more complicated
|
|
740
|
+
// because you need to verify each combination of types
|
|
741
|
+
}
|
|
742
|
+
else if ((0, reflection_1.isDynamicType)(rightType) || (0, reflection_1.isObjectType)(rightType)) {
|
|
743
|
+
// operand is basically "any" type... ignore
|
|
744
|
+
}
|
|
745
|
+
else if ((0, reflection_1.isNumberTypeLike)(rightType)) {
|
|
746
|
+
// operand is a number.. this is ok
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
// rhs is not a number, so no increment operator is not allowed
|
|
750
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.operatorTypeMismatch(incStmt.tokens.operator.text, rightType.toString())), { location: incStmt.location }));
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
validateVariableAndDottedGetExpressions(file, expression) {
|
|
754
|
+
var _a, _b, _c, _d;
|
|
755
|
+
if ((0, reflection_1.isDottedGetExpression)(expression.parent)) {
|
|
756
|
+
// We validate dottedGetExpressions at the top-most level
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
if ((0, reflection_1.isVariableExpression)(expression)) {
|
|
760
|
+
if ((0, reflection_1.isAssignmentStatement)(expression.parent) && expression.parent.tokens.name === expression.tokens.name) {
|
|
761
|
+
// Don't validate LHS of assignments
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
else if ((0, reflection_1.isNamespaceStatement)(expression.parent)) {
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
let symbolType = 1 /* SymbolTypeFlag.runtime */;
|
|
769
|
+
let oppositeSymbolType = 2 /* SymbolTypeFlag.typetime */;
|
|
770
|
+
const isUsedAsType = util_1.util.isInTypeExpression(expression);
|
|
771
|
+
if (isUsedAsType) {
|
|
772
|
+
// This is used in a TypeExpression - only look up types from SymbolTable
|
|
773
|
+
symbolType = 2 /* SymbolTypeFlag.typetime */;
|
|
774
|
+
oppositeSymbolType = 1 /* SymbolTypeFlag.runtime */;
|
|
775
|
+
}
|
|
776
|
+
// Do a complete type check on all DottedGet and Variable expressions
|
|
777
|
+
// this will create a diagnostic if an invalid member is accessed
|
|
778
|
+
const typeChain = [];
|
|
779
|
+
const typeData = {};
|
|
780
|
+
let exprType = this.getNodeTypeWrapper(file, expression, {
|
|
781
|
+
flags: symbolType,
|
|
782
|
+
typeChain: typeChain,
|
|
783
|
+
data: typeData
|
|
784
|
+
});
|
|
785
|
+
const hasValidDeclaration = this.hasValidDeclaration(expression, exprType, typeData === null || typeData === void 0 ? void 0 : typeData.definingNode);
|
|
786
|
+
//include a hint diagnostic if this type is marked as deprecated
|
|
787
|
+
if (typeData.flags & 64 /* SymbolTypeFlag.deprecated */) { // eslint-disable-line no-bitwise
|
|
788
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemIsDeprecated()), { location: expression.tokens.name.location, tags: [vscode_languageserver_1.DiagnosticTag.Deprecated] }));
|
|
789
|
+
}
|
|
790
|
+
if (!this.isTypeKnown(exprType) && !hasValidDeclaration) {
|
|
791
|
+
if ((_a = this.getNodeTypeWrapper(file, expression, { flags: oppositeSymbolType, isExistenceTest: true })) === null || _a === void 0 ? void 0 : _a.isResolvable()) {
|
|
792
|
+
const oppoSiteTypeChain = [];
|
|
793
|
+
const invalidlyUsedResolvedType = this.getNodeTypeWrapper(file, expression, { flags: oppositeSymbolType, typeChain: oppoSiteTypeChain, isExistenceTest: true });
|
|
794
|
+
const typeChainScan = util_1.util.processTypeChain(oppoSiteTypeChain);
|
|
795
|
+
if (isUsedAsType) {
|
|
796
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsType(typeChainScan.fullChainName)), { location: expression.location }));
|
|
797
|
+
}
|
|
798
|
+
else if (invalidlyUsedResolvedType && !(0, reflection_1.isReferenceType)(invalidlyUsedResolvedType)) {
|
|
799
|
+
if (!(0, reflection_1.isAliasStatement)(expression.parent)) {
|
|
800
|
+
// alias rhs CAN be a type!
|
|
801
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable(invalidlyUsedResolvedType.toString())), { location: expression.location }));
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
else {
|
|
805
|
+
const typeChainScan = util_1.util.processTypeChain(typeChain);
|
|
806
|
+
//if this is a function call, provide a different diagnostic code
|
|
807
|
+
if ((0, reflection_1.isCallExpression)(typeChainScan.astNode.parent) && typeChainScan.astNode.parent.callee === expression) {
|
|
808
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindFunction(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
else if (!(typeData === null || typeData === void 0 ? void 0 : typeData.isFromDocComment)) {
|
|
816
|
+
// only show "cannot find... " errors if the type is not defined from a doc comment
|
|
817
|
+
const typeChainScan = util_1.util.processTypeChain(typeChain);
|
|
818
|
+
const circularReferenceInfo = this.getCircularReference(exprType);
|
|
819
|
+
if ((0, reflection_1.isCallExpression)(typeChainScan.astNode.parent) && typeChainScan.astNode.parent.callee === expression) {
|
|
820
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindFunction(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
|
|
821
|
+
}
|
|
822
|
+
else if (circularReferenceInfo === null || circularReferenceInfo === void 0 ? void 0 : circularReferenceInfo.isCircularReference) {
|
|
823
|
+
let diagnosticDetail = util_1.util.getCircularReferenceDiagnosticDetail(circularReferenceInfo, typeChainScan.fullNameOfItem);
|
|
824
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.circularReferenceDetected(diagnosticDetail)), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(typeChainScan.itemName, typeChainScan.fullNameOfItem, typeChainScan.itemParentTypeName, this.getParentTypeDescriptor(typeChainScan))), { location: typeChainScan === null || typeChainScan === void 0 ? void 0 : typeChainScan.location }));
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
if (isUsedAsType) {
|
|
832
|
+
return;
|
|
833
|
+
}
|
|
834
|
+
const containingNamespace = expression.findAncestor(reflection_1.isNamespaceStatement);
|
|
835
|
+
const containingNamespaceName = containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.getName(Parser_1.ParseMode.BrighterScript);
|
|
836
|
+
if (!((0, reflection_1.isCallExpression)(expression.parent) && (0, reflection_1.isNewExpression)((_b = expression.parent) === null || _b === void 0 ? void 0 : _b.parent))) {
|
|
837
|
+
const classUsedAsVarEntry = this.checkTypeChainForClassUsedAsVar(typeChain, containingNamespaceName);
|
|
838
|
+
const isClassInNamespace = containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.getSymbolTable().hasSymbol(typeChain[0].name, 1 /* SymbolTypeFlag.runtime */);
|
|
839
|
+
if (classUsedAsVarEntry && !isClassInNamespace) {
|
|
840
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable(classUsedAsVarEntry.toString())), { location: expression.location }));
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
const lastTypeInfo = typeChain[typeChain.length - 1];
|
|
845
|
+
const parentTypeInfo = typeChain[typeChain.length - 2];
|
|
846
|
+
this.checkMemberAccessibility(file, expression, typeChain);
|
|
847
|
+
if ((0, reflection_1.isNamespaceType)(exprType) && !(0, reflection_1.isAliasStatement)(expression.parent)) {
|
|
848
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('namespace')), { location: expression.location }));
|
|
849
|
+
}
|
|
850
|
+
else if ((0, reflection_1.isEnumType)(exprType) && !(0, reflection_1.isAliasStatement)(expression.parent)) {
|
|
851
|
+
const enumStatement = this.event.scope.getEnum(util_1.util.getAllDottedGetPartsAsString(expression));
|
|
852
|
+
if (enumStatement) {
|
|
853
|
+
// there's an enum with this name
|
|
854
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.itemCannotBeUsedAsVariable('enum')), { location: expression.location }));
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
else if ((0, reflection_1.isDynamicType)(exprType) && (0, reflection_1.isEnumType)(parentTypeInfo === null || parentTypeInfo === void 0 ? void 0 : parentTypeInfo.type) && (0, reflection_1.isDottedGetExpression)(expression)) {
|
|
858
|
+
const enumFileLink = this.event.scope.getEnumFileLink(util_1.util.getAllDottedGetPartsAsString(expression.obj));
|
|
859
|
+
const typeChainScanForItem = util_1.util.processTypeChain(typeChain);
|
|
860
|
+
const typeChainScanForParent = util_1.util.processTypeChain(typeChain.slice(0, -1));
|
|
861
|
+
if (enumFileLink) {
|
|
862
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(lastTypeInfo === null || lastTypeInfo === void 0 ? void 0 : lastTypeInfo.name, typeChainScanForItem.fullChainName, typeChainScanForParent.fullNameOfItem, 'enum')), { location: lastTypeInfo === null || lastTypeInfo === void 0 ? void 0 : lastTypeInfo.location, relatedInformation: [{
|
|
863
|
+
message: 'Enum declared here',
|
|
864
|
+
location: util_1.util.createLocationFromRange(util_1.util.pathToUri(enumFileLink === null || enumFileLink === void 0 ? void 0 : enumFileLink.file.srcPath), (_d = (_c = enumFileLink === null || enumFileLink === void 0 ? void 0 : enumFileLink.item) === null || _c === void 0 ? void 0 : _c.tokens.name.location) === null || _d === void 0 ? void 0 : _d.range)
|
|
865
|
+
}] }));
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
checkTypeChainForClassUsedAsVar(typeChain, containingNamespaceName) {
|
|
870
|
+
const ignoreKinds = [AstNode_1.AstNodeKind.TypecastExpression, AstNode_1.AstNodeKind.NewExpression];
|
|
871
|
+
let lowerNameSoFar = '';
|
|
872
|
+
let classUsedAsVar;
|
|
873
|
+
let isFirst = true;
|
|
874
|
+
for (let i = 0; i < typeChain.length - 1; i++) { // do not look at final entry - we CAN use the constructor as a variable
|
|
875
|
+
const tce = typeChain[i];
|
|
876
|
+
lowerNameSoFar += `${lowerNameSoFar ? '.' : ''}${tce.name.toLowerCase()}`;
|
|
877
|
+
if (!(0, reflection_1.isNamespaceType)(tce.type)) {
|
|
878
|
+
if (isFirst && containingNamespaceName) {
|
|
879
|
+
lowerNameSoFar = `${containingNamespaceName.toLowerCase()}.${lowerNameSoFar}`;
|
|
880
|
+
}
|
|
881
|
+
if (!tce.astNode || ignoreKinds.includes(tce.astNode.kind)) {
|
|
882
|
+
break;
|
|
883
|
+
}
|
|
884
|
+
else if ((0, reflection_1.isClassType)(tce.type) && lowerNameSoFar.toLowerCase() === tce.type.name.toLowerCase()) {
|
|
885
|
+
classUsedAsVar = tce.type;
|
|
886
|
+
}
|
|
887
|
+
break;
|
|
888
|
+
}
|
|
889
|
+
isFirst = false;
|
|
890
|
+
}
|
|
891
|
+
return classUsedAsVar;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Adds diagnostics for accibility mismatches
|
|
895
|
+
*
|
|
896
|
+
* @param file file
|
|
897
|
+
* @param expression containing expression
|
|
898
|
+
* @param typeChain type chain to check
|
|
899
|
+
* @returns true if member accesiibility is okay
|
|
900
|
+
*/
|
|
901
|
+
checkMemberAccessibility(file, expression, typeChain) {
|
|
902
|
+
var _a, _b, _c;
|
|
903
|
+
for (let i = 0; i < typeChain.length - 1; i++) {
|
|
904
|
+
const parentChainItem = typeChain[i];
|
|
905
|
+
const childChainItem = typeChain[i + 1];
|
|
906
|
+
if ((0, reflection_1.isClassType)(parentChainItem.type)) {
|
|
907
|
+
const containingClassStmt = expression.findAncestor(reflection_1.isClassStatement);
|
|
908
|
+
const classStmtThatDefinesChildMember = (_b = (_a = childChainItem.data) === null || _a === void 0 ? void 0 : _a.definingNode) === null || _b === void 0 ? void 0 : _b.findAncestor(reflection_1.isClassStatement);
|
|
909
|
+
if (classStmtThatDefinesChildMember) {
|
|
910
|
+
const definingClassName = classStmtThatDefinesChildMember.getName(Parser_1.ParseMode.BrighterScript);
|
|
911
|
+
const inMatchingClassStmt = (containingClassStmt === null || containingClassStmt === void 0 ? void 0 : containingClassStmt.getName(Parser_1.ParseMode.BrighterScript).toLowerCase()) === parentChainItem.type.name.toLowerCase();
|
|
912
|
+
// eslint-disable-next-line no-bitwise
|
|
913
|
+
if (childChainItem.data.flags & 8 /* SymbolTypeFlag.private */) {
|
|
914
|
+
if (!inMatchingClassStmt || childChainItem.data.memberOfAncestor) {
|
|
915
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch(childChainItem.name, childChainItem.data.flags, definingClassName)), { location: expression.location }));
|
|
916
|
+
// there's an error... don't worry about the rest of the chain
|
|
917
|
+
return false;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
// eslint-disable-next-line no-bitwise
|
|
921
|
+
if (childChainItem.data.flags & 16 /* SymbolTypeFlag.protected */) {
|
|
922
|
+
const containingClassName = containingClassStmt === null || containingClassStmt === void 0 ? void 0 : containingClassStmt.getName(Parser_1.ParseMode.BrighterScript);
|
|
923
|
+
const containingNamespaceName = (_c = expression.findAncestor(reflection_1.isNamespaceStatement)) === null || _c === void 0 ? void 0 : _c.getName(Parser_1.ParseMode.BrighterScript);
|
|
924
|
+
const ancestorClasses = this.event.scope.getClassHierarchy(containingClassName, containingNamespaceName).map(link => link.item);
|
|
925
|
+
const isSubClassOfDefiningClass = ancestorClasses.includes(classStmtThatDefinesChildMember);
|
|
926
|
+
if (!isSubClassOfDefiningClass) {
|
|
927
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.memberAccessibilityMismatch(childChainItem.name, childChainItem.data.flags, definingClassName)), { location: expression.location }));
|
|
928
|
+
// there's an error... don't worry about the rest of the chain
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
return true;
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Find all "new" statements in the program,
|
|
939
|
+
* and make sure we can find a class with that name
|
|
940
|
+
*/
|
|
941
|
+
validateNewExpression(file, newExpression) {
|
|
942
|
+
var _a;
|
|
943
|
+
const newExprType = this.getNodeTypeWrapper(file, newExpression, { flags: 2 /* SymbolTypeFlag.typetime */ });
|
|
944
|
+
if ((0, reflection_1.isClassType)(newExprType)) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
let potentialClassName = newExpression.className.getName(Parser_1.ParseMode.BrighterScript);
|
|
948
|
+
const namespaceName = (_a = newExpression.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript);
|
|
949
|
+
let newableClass = this.event.scope.getClass(potentialClassName, namespaceName);
|
|
950
|
+
if (!newableClass) {
|
|
951
|
+
//try and find functions with this name.
|
|
952
|
+
let fullName = util_1.util.getFullyQualifiedClassName(potentialClassName, namespaceName);
|
|
953
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expressionIsNotConstructable(fullName)), { location: newExpression.className.location }));
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
validateFunctionExpressionForReturn(func) {
|
|
957
|
+
var _a, _b;
|
|
958
|
+
const returnType = (_a = func === null || func === void 0 ? void 0 : func.returnTypeExpression) === null || _a === void 0 ? void 0 : _a.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
|
|
959
|
+
if (!returnType || !returnType.isResolvable() || (0, reflection_1.isVoidType)(returnType) || (0, reflection_1.isDynamicType)(returnType)) {
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
const returns = (_b = func.body) === null || _b === void 0 ? void 0 : _b.findChild(reflection_1.isReturnStatement, { walkMode: visitors_1.WalkMode.visitAll });
|
|
963
|
+
if (!returns && (0, reflection_1.isStringTypeLike)(returnType)) {
|
|
964
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.returnTypeCoercionMismatch(returnType.toString())), { location: func.location }));
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Create diagnostics for any duplicate function declarations
|
|
969
|
+
*/
|
|
970
|
+
flagDuplicateFunctionDeclarations() {
|
|
971
|
+
var _a;
|
|
972
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, tag: "ScopeValidatorDuplicateFunctionDeclaration" /* ScopeValidatorDiagnosticTag.DuplicateFunctionDeclaration */ });
|
|
973
|
+
//for each list of callables with the same name
|
|
974
|
+
for (let [lowerName, callableContainers] of this.event.scope.getCallableContainerMap()) {
|
|
975
|
+
let globalCallables = [];
|
|
976
|
+
let nonGlobalCallables = [];
|
|
977
|
+
let ownCallables = [];
|
|
978
|
+
let ancestorNonGlobalCallables = [];
|
|
979
|
+
for (let container of callableContainers) {
|
|
980
|
+
if (container.scope === this.event.program.globalScope) {
|
|
981
|
+
globalCallables.push(container);
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
nonGlobalCallables.push(container);
|
|
985
|
+
if (container.scope === this.event.scope) {
|
|
986
|
+
ownCallables.push(container);
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
ancestorNonGlobalCallables.push(container);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
//add info diagnostics about child shadowing parent functions
|
|
994
|
+
if (ownCallables.length > 0 && ancestorNonGlobalCallables.length > 0) {
|
|
995
|
+
for (let container of ownCallables) {
|
|
996
|
+
//skip the init function (because every component will have one of those){
|
|
997
|
+
if (lowerName !== 'init') {
|
|
998
|
+
let shadowedCallable = ancestorNonGlobalCallables[ancestorNonGlobalCallables.length - 1];
|
|
999
|
+
if (!!shadowedCallable && shadowedCallable.callable.file === container.callable.file) {
|
|
1000
|
+
//same file: skip redundant imports
|
|
1001
|
+
continue;
|
|
1002
|
+
}
|
|
1003
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.overridesAncestorFunction(container.callable.name, container.scope.name, shadowedCallable.callable.file.destPath,
|
|
1004
|
+
//grab the last item in the list, which should be the closest ancestor's version
|
|
1005
|
+
shadowedCallable.scope.name)), { location: util_1.util.createLocationFromFileRange(container.callable.file, container.callable.nameRange) }), "ScopeValidatorDuplicateFunctionDeclaration" /* ScopeValidatorDiagnosticTag.DuplicateFunctionDeclaration */);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
//add error diagnostics about duplicate functions in the same scope
|
|
1010
|
+
if (ownCallables.length > 1) {
|
|
1011
|
+
for (let callableContainer of ownCallables) {
|
|
1012
|
+
let callable = callableContainer.callable;
|
|
1013
|
+
const related = [];
|
|
1014
|
+
for (const ownCallable of ownCallables) {
|
|
1015
|
+
const thatNameRange = ownCallable.callable.nameRange;
|
|
1016
|
+
if (ownCallable.callable.nameRange !== callable.nameRange) {
|
|
1017
|
+
related.push({
|
|
1018
|
+
message: `Function declared here`,
|
|
1019
|
+
location: util_1.util.createLocationFromRange(util_1.util.pathToUri((_a = ownCallable.callable.file) === null || _a === void 0 ? void 0 : _a.srcPath), thatNameRange)
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateFunctionImplementation(callable.name)), { location: util_1.util.createLocationFromFileRange(callable.file, callable.nameRange), relatedInformation: related }), "ScopeValidatorDuplicateFunctionDeclaration" /* ScopeValidatorDiagnosticTag.DuplicateFunctionDeclaration */);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* Verify that all of the scripts imported by each file in this scope actually exist, and have the correct case
|
|
1030
|
+
*/
|
|
1031
|
+
validateScriptImportPaths() {
|
|
1032
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, tag: "ScopeValidatorImports" /* ScopeValidatorDiagnosticTag.Imports */ });
|
|
1033
|
+
let scriptImports = this.event.scope.getOwnScriptImports();
|
|
1034
|
+
//verify every script import
|
|
1035
|
+
for (let scriptImport of scriptImports) {
|
|
1036
|
+
let referencedFile = this.event.scope.getFileByRelativePath(scriptImport.destPath);
|
|
1037
|
+
//if we can't find the file
|
|
1038
|
+
if (!referencedFile) {
|
|
1039
|
+
//skip the default bslib file, it will exist at transpile time but should not show up in the program during validation cycle
|
|
1040
|
+
if (scriptImport.destPath === this.event.program.bslibPkgPath) {
|
|
1041
|
+
continue;
|
|
1042
|
+
}
|
|
1043
|
+
let dInfo;
|
|
1044
|
+
if (scriptImport.text.trim().length === 0) {
|
|
1045
|
+
dInfo = DiagnosticMessages_1.DiagnosticMessages.scriptSrcCannotBeEmpty();
|
|
1046
|
+
}
|
|
1047
|
+
else {
|
|
1048
|
+
dInfo = DiagnosticMessages_1.DiagnosticMessages.referencedFileDoesNotExist();
|
|
1049
|
+
}
|
|
1050
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, dInfo), { location: util_1.util.createLocationFromFileRange(scriptImport.sourceFile, scriptImport.filePathRange) }), "ScopeValidatorImports" /* ScopeValidatorDiagnosticTag.Imports */);
|
|
1051
|
+
//if the character casing of the script import path does not match that of the actual path
|
|
1052
|
+
}
|
|
1053
|
+
else if (scriptImport.destPath !== referencedFile.destPath) {
|
|
1054
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scriptImportCaseMismatch(referencedFile.destPath)), { location: util_1.util.createLocationFromFileRange(scriptImport.sourceFile, scriptImport.filePathRange) }), "ScopeValidatorImports" /* ScopeValidatorDiagnosticTag.Imports */);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* Validate all classes defined in this scope
|
|
1060
|
+
*/
|
|
1061
|
+
validateClasses() {
|
|
1062
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, tag: "ScopeValidatorClasses" /* ScopeValidatorDiagnosticTag.Classes */ });
|
|
1063
|
+
let validator = new ClassValidator_1.BsClassValidator(this.event.scope);
|
|
1064
|
+
validator.validate();
|
|
1065
|
+
for (const diagnostic of validator.diagnostics) {
|
|
1066
|
+
this.addMultiScopeDiagnostic(Object.assign({}, diagnostic), "ScopeValidatorClasses" /* ScopeValidatorDiagnosticTag.Classes */);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
/**
|
|
1070
|
+
* Find various function collisions
|
|
1071
|
+
*/
|
|
1072
|
+
diagnosticDetectFunctionCollisions(file) {
|
|
1073
|
+
const fileUri = util_1.util.pathToUri(file.srcPath);
|
|
1074
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: fileUri, tag: "ScopeValidatorFunctionCollisions" /* ScopeValidatorDiagnosticTag.FunctionCollisions */ });
|
|
1075
|
+
for (let func of file.callables) {
|
|
1076
|
+
const funcName = func.getName(Parser_1.ParseMode.BrighterScript);
|
|
1077
|
+
const lowerFuncName = funcName === null || funcName === void 0 ? void 0 : funcName.toLowerCase();
|
|
1078
|
+
if (lowerFuncName) {
|
|
1079
|
+
//find function declarations with the same name as a stdlib function
|
|
1080
|
+
if (globalCallables_1.globalCallableMap.has(lowerFuncName)) {
|
|
1081
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scopeFunctionShadowedByBuiltInFunction()), { location: util_1.util.createLocationFromRange(fileUri, func.nameRange) }));
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
detectShadowedLocalVar(file, varDeclaration) {
|
|
1087
|
+
var _a, _b;
|
|
1088
|
+
const varName = varDeclaration.name;
|
|
1089
|
+
const lowerVarName = varName.toLowerCase();
|
|
1090
|
+
const callableContainerMap = this.event.scope.getCallableContainerMap();
|
|
1091
|
+
const containingNamespace = (_a = varDeclaration.expr) === null || _a === void 0 ? void 0 : _a.findAncestor(reflection_1.isNamespaceStatement);
|
|
1092
|
+
const localVarIsInNamespace = util_1.util.isVariableMemberOfNamespace(varDeclaration.name, varDeclaration.expr, containingNamespace);
|
|
1093
|
+
const varIsFunction = () => {
|
|
1094
|
+
return (0, reflection_1.isCallableType)(varDeclaration.type) && !(0, reflection_1.isDynamicType)(varDeclaration.type);
|
|
1095
|
+
};
|
|
1096
|
+
if (
|
|
1097
|
+
//has same name as stdlib
|
|
1098
|
+
globalCallables_1.globalCallableMap.has(lowerVarName)) {
|
|
1099
|
+
//local var function with same name as stdlib function
|
|
1100
|
+
if (varIsFunction()) {
|
|
1101
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('stdlib')), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange) }));
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
else if (callableContainerMap.has(lowerVarName) && !localVarIsInNamespace) {
|
|
1105
|
+
const callable = callableContainerMap.get(lowerVarName);
|
|
1106
|
+
//is same name as a callable
|
|
1107
|
+
if (varIsFunction()) {
|
|
1108
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('scope')), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange), relatedInformation: [{
|
|
1109
|
+
message: 'Function declared here',
|
|
1110
|
+
location: util_1.util.createLocationFromFileRange(callable[0].callable.file, callable[0].callable.nameRange)
|
|
1111
|
+
}] }));
|
|
1112
|
+
}
|
|
1113
|
+
else {
|
|
1114
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange), relatedInformation: [{
|
|
1115
|
+
message: 'Function declared here',
|
|
1116
|
+
location: util_1.util.createLocationFromRange(util_1.util.pathToUri(callable[0].callable.file.srcPath), callable[0].callable.nameRange)
|
|
1117
|
+
}] }));
|
|
1118
|
+
}
|
|
1119
|
+
//has the same name as an in-scope class
|
|
1120
|
+
}
|
|
1121
|
+
else if (!localVarIsInNamespace) {
|
|
1122
|
+
const classStmtLink = this.event.scope.getClassFileLink(lowerVarName);
|
|
1123
|
+
if (classStmtLink) {
|
|
1124
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { location: util_1.util.createLocationFromFileRange(file, varDeclaration.nameRange), relatedInformation: [{
|
|
1125
|
+
message: 'Class declared here',
|
|
1126
|
+
location: util_1.util.createLocationFromRange(util_1.util.pathToUri(classStmtLink.file.srcPath), (_b = classStmtLink === null || classStmtLink === void 0 ? void 0 : classStmtLink.item.tokens.name.location) === null || _b === void 0 ? void 0 : _b.range)
|
|
1127
|
+
}] }));
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
validateForStatement(file, forStmt) {
|
|
1132
|
+
const assignStmt = forStmt.counterDeclaration;
|
|
1133
|
+
const assignValueType = this.getNodeTypeWrapper(file, assignStmt.value, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forStmt.statementIndex });
|
|
1134
|
+
if (!IntegerType_1.IntegerType.instance.isTypeCompatible(assignValueType)) {
|
|
1135
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(assignValueType.toString(), 'integer')), { location: assignStmt.location }));
|
|
1136
|
+
}
|
|
1137
|
+
if (forStmt.increment) {
|
|
1138
|
+
const incrementValueType = this.getNodeTypeWrapper(file, forStmt.increment, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forStmt.statementIndex });
|
|
1139
|
+
if (!IntegerType_1.IntegerType.instance.isTypeCompatible(incrementValueType)) {
|
|
1140
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(incrementValueType.toString(), 'integer')), { location: forStmt.increment.location }));
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
const finalValueType = this.getNodeTypeWrapper(file, forStmt.finalValue, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forStmt.statementIndex });
|
|
1144
|
+
if (!IntegerType_1.IntegerType.instance.isTypeCompatible(finalValueType)) {
|
|
1145
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(finalValueType.toString(), 'integer')), { location: forStmt.finalValue.location }));
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
validateForEachStatement(file, forEachStmt) {
|
|
1149
|
+
const targetType = this.getNodeTypeWrapper(file, forEachStmt.target, { flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forEachStmt.statementIndex });
|
|
1150
|
+
if ((0, reflection_1.isDynamicType)(targetType) || (0, reflection_1.isObjectType)(targetType)) {
|
|
1151
|
+
// unable to determine type, skip further validation
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1154
|
+
let targetItemType;
|
|
1155
|
+
if (!(0, reflection_1.isArrayType)(targetType)) {
|
|
1156
|
+
if ((0, reflection_1.isIterableType)(targetType)) {
|
|
1157
|
+
// this is enumerable
|
|
1158
|
+
targetItemType = util_1.util.getIteratorDefaultType(targetType);
|
|
1159
|
+
}
|
|
1160
|
+
else {
|
|
1161
|
+
// target is not an array nor enumerable
|
|
1162
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.notIterable(targetType.toString())), { location: forEachStmt.target.location }));
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
else {
|
|
1167
|
+
targetItemType = targetType.defaultType;
|
|
1168
|
+
}
|
|
1169
|
+
const loopType = forEachStmt.getLoopVariableType({ flags: 1 /* SymbolTypeFlag.runtime */, statementIndex: forEachStmt.statementIndex });
|
|
1170
|
+
if (loopType === null || loopType === void 0 ? void 0 : loopType.isResolvable()) {
|
|
1171
|
+
const data = {};
|
|
1172
|
+
if (!loopType.isTypeCompatible(targetItemType, data)) {
|
|
1173
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.assignmentTypeMismatch(targetItemType.toString(), loopType.toString(), data)), { location: forEachStmt.typeExpression.location }));
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
validateXmlInterface(scope) {
|
|
1178
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1179
|
+
if (!((_b = (_a = scope.xmlFile.parser.ast) === null || _a === void 0 ? void 0 : _a.componentElement) === null || _b === void 0 ? void 0 : _b.interfaceElement)) {
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: util_1.util.pathToUri((_c = scope.xmlFile) === null || _c === void 0 ? void 0 : _c.srcPath), tag: "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */ });
|
|
1183
|
+
const iface = scope.xmlFile.parser.ast.componentElement.interfaceElement;
|
|
1184
|
+
const callableContainerMap = scope.getCallableContainerMap();
|
|
1185
|
+
//validate functions
|
|
1186
|
+
for (const func of iface.functions) {
|
|
1187
|
+
const name = func.name;
|
|
1188
|
+
if (!name) {
|
|
1189
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlTagMissingAttribute(func.tokens.startTagName.text, 'name')), { location: func.tokens.startTagName.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
|
|
1190
|
+
}
|
|
1191
|
+
else if (!callableContainerMap.has(name.toLowerCase())) {
|
|
1192
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlFunctionNotFound(name)), { location: (_d = func.getAttribute('name')) === null || _d === void 0 ? void 0 : _d.tokens.value.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
//validate fields
|
|
1196
|
+
for (const field of iface.fields) {
|
|
1197
|
+
const { id, type, onChange } = field;
|
|
1198
|
+
if (!id) {
|
|
1199
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlTagMissingAttribute(field.tokens.startTagName.text, 'id')), { location: field.tokens.startTagName.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
|
|
1200
|
+
}
|
|
1201
|
+
if (!type) {
|
|
1202
|
+
if (!field.alias) {
|
|
1203
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlTagMissingAttribute(field.tokens.startTagName.text, 'type')), { location: field.tokens.startTagName.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
else if (!SGTypes_1.SGFieldTypes.includes(type.toLowerCase())) {
|
|
1207
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlInvalidFieldType(type)), { location: (_e = field.getAttribute('type')) === null || _e === void 0 ? void 0 : _e.tokens.value.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
|
|
1208
|
+
}
|
|
1209
|
+
if (onChange) {
|
|
1210
|
+
if (!callableContainerMap.has(onChange.toLowerCase())) {
|
|
1211
|
+
this.addDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.xmlFunctionNotFound(onChange)), { location: (_f = field.getAttribute('onchange')) === null || _f === void 0 ? void 0 : _f.tokens.value.location }), "ScopeValidatorXML" /* ScopeValidatorDiagnosticTag.XMLInterface */);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
validateDocComments(node) {
|
|
1217
|
+
var _a, _b;
|
|
1218
|
+
const doc = BrightScriptDocParser_1.default.parseNode(node);
|
|
1219
|
+
for (const docTag of doc.tags) {
|
|
1220
|
+
const docTypeTag = docTag;
|
|
1221
|
+
if (!docTypeTag.typeExpression || !docTypeTag.location) {
|
|
1222
|
+
continue;
|
|
1223
|
+
}
|
|
1224
|
+
const foundType = (_a = docTypeTag.typeExpression) === null || _a === void 0 ? void 0 : _a.getType({ flags: 2 /* SymbolTypeFlag.typetime */ });
|
|
1225
|
+
if (!(foundType === null || foundType === void 0 ? void 0 : foundType.isResolvable())) {
|
|
1226
|
+
this.addMultiScopeDiagnostic(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotFindName(docTypeTag.typeString)), { location: (_b = BrightScriptDocParser_1.default.getTypeLocationFromToken(docTypeTag.token)) !== null && _b !== void 0 ? _b : docTypeTag.location }));
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Detect when a child has imported a script that an ancestor also imported
|
|
1232
|
+
*/
|
|
1233
|
+
diagnosticDetectDuplicateAncestorScriptImports(scope) {
|
|
1234
|
+
var _a, _b, _c;
|
|
1235
|
+
this.event.program.diagnostics.clearByFilter({ scope: this.event.scope, fileUri: util_1.util.pathToUri((_a = scope.xmlFile) === null || _a === void 0 ? void 0 : _a.srcPath), tag: "ScopeValidatorXMLImports" /* ScopeValidatorDiagnosticTag.XMLImports */ });
|
|
1236
|
+
if (scope.xmlFile.parentComponent) {
|
|
1237
|
+
//build a lookup of pkg paths -> FileReference so we can more easily look up collisions
|
|
1238
|
+
let parentScriptImports = scope.xmlFile.getAncestorScriptTagImports();
|
|
1239
|
+
let lookup = {};
|
|
1240
|
+
for (let parentScriptImport of parentScriptImports) {
|
|
1241
|
+
//keep the first occurance of a pkgPath. Parent imports are first in the array
|
|
1242
|
+
if (!lookup[parentScriptImport.destPath]) {
|
|
1243
|
+
lookup[parentScriptImport.destPath] = parentScriptImport;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
//add warning for every script tag that this file shares with an ancestor
|
|
1247
|
+
for (let scriptImport of scope.xmlFile.scriptTagImports) {
|
|
1248
|
+
let ancestorScriptImport = lookup[scriptImport.destPath];
|
|
1249
|
+
if (ancestorScriptImport) {
|
|
1250
|
+
let ancestorComponent = ancestorScriptImport.sourceFile;
|
|
1251
|
+
let ancestorComponentName = (_c = (_b = ancestorComponent.componentName) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : ancestorComponent.destPath;
|
|
1252
|
+
this.addDiagnostic(Object.assign({ location: util_1.util.createLocationFromFileRange(scope.xmlFile, scriptImport.filePathRange) }, DiagnosticMessages_1.DiagnosticMessages.unnecessaryScriptImportInChildFromParent(ancestorComponentName)), "ScopeValidatorXMLImports" /* ScopeValidatorDiagnosticTag.XMLImports */);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Wraps the AstNode.getType() method, so that we can do extra processing on the result based on the current file
|
|
1259
|
+
* In particular, since BrightScript does not support Unions, and there's no way to cast them to something else
|
|
1260
|
+
* if the result of .getType() is a union, and we're in a .brs (brightScript) file, treat the result as Dynamic
|
|
1261
|
+
*
|
|
1262
|
+
* Also, for BrightScript parse-mode, if .getType() returns a node type, do not validate unknown members.
|
|
1263
|
+
*
|
|
1264
|
+
* In most cases, this returns the result of node.getType()
|
|
1265
|
+
*
|
|
1266
|
+
* @param file the current file being processed
|
|
1267
|
+
* @param node the node to get the type of
|
|
1268
|
+
* @param getTypeOpts any options to pass to node.getType()
|
|
1269
|
+
* @returns the processed result type
|
|
1270
|
+
*/
|
|
1271
|
+
getNodeTypeWrapper(file, node, getTypeOpts) {
|
|
1272
|
+
const type = node === null || node === void 0 ? void 0 : node.getType(getTypeOpts);
|
|
1273
|
+
if (file.parseMode === Parser_1.ParseMode.BrightScript) {
|
|
1274
|
+
// this is a brightscript file
|
|
1275
|
+
const typeChain = getTypeOpts.typeChain;
|
|
1276
|
+
if (typeChain) {
|
|
1277
|
+
const hasUnion = typeChain.reduce((hasUnion, tce) => {
|
|
1278
|
+
return hasUnion || (0, reflection_1.isUnionType)(tce.type);
|
|
1279
|
+
}, false);
|
|
1280
|
+
if (hasUnion) {
|
|
1281
|
+
// there was a union somewhere in the typechain
|
|
1282
|
+
return DynamicType_1.DynamicType.instance;
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
if ((0, reflection_1.isUnionType)(type)) {
|
|
1286
|
+
//this is a union
|
|
1287
|
+
return DynamicType_1.DynamicType.instance;
|
|
1288
|
+
}
|
|
1289
|
+
if ((0, reflection_1.isComponentType)(type)) {
|
|
1290
|
+
// modify type to allow any member access for Node types
|
|
1291
|
+
type.changeUnknownMemberToDynamic = true;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
// by default return the result of node.getType()
|
|
1295
|
+
return type;
|
|
1296
|
+
}
|
|
1297
|
+
getParentTypeDescriptor(typeChainResult) {
|
|
1298
|
+
if (typeChainResult.itemParentTypeKind === BscTypeKind_1.BscTypeKind.NamespaceType) {
|
|
1299
|
+
return 'namespace';
|
|
1300
|
+
}
|
|
1301
|
+
return 'type';
|
|
1302
|
+
}
|
|
1303
|
+
addDiagnostic(diagnostic, diagnosticTag) {
|
|
1304
|
+
diagnosticTag = diagnosticTag !== null && diagnosticTag !== void 0 ? diagnosticTag : (this.currentSegmentBeingValidated ? "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ : "ScopeValidator" /* ScopeValidatorDiagnosticTag.Default */);
|
|
1305
|
+
this.event.program.diagnostics.register(diagnostic, {
|
|
1306
|
+
tags: [diagnosticTag],
|
|
1307
|
+
segment: this.currentSegmentBeingValidated
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Add a diagnostic (to the first scope) that will have `relatedInformation` for each affected scope
|
|
1312
|
+
*/
|
|
1313
|
+
addMultiScopeDiagnostic(diagnostic, diagnosticTag) {
|
|
1314
|
+
diagnosticTag = diagnosticTag !== null && diagnosticTag !== void 0 ? diagnosticTag : (this.currentSegmentBeingValidated ? "ScopeValidatorSegment" /* ScopeValidatorDiagnosticTag.Segment */ : "ScopeValidator" /* ScopeValidatorDiagnosticTag.Default */);
|
|
1315
|
+
this.event.program.diagnostics.register(diagnostic, {
|
|
1316
|
+
tags: [diagnosticTag],
|
|
1317
|
+
segment: this.currentSegmentBeingValidated,
|
|
1318
|
+
scope: this.event.scope
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
exports.ScopeValidator = ScopeValidator;
|
|
1323
|
+
//# sourceMappingURL=ScopeValidator.js.map
|