brighterscript 1.0.0-alpha.24 → 1.0.0-alpha.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +521 -233
- package/README.md +45 -139
- package/bsconfig.schema.json +46 -0
- package/dist/ActionPipeline.d.ts +10 -0
- package/dist/ActionPipeline.js +40 -0
- package/dist/ActionPipeline.js.map +1 -0
- package/dist/AstValidationSegmenter.d.ts +25 -0
- package/dist/AstValidationSegmenter.js +152 -0
- package/dist/AstValidationSegmenter.js.map +1 -0
- package/dist/BsConfig.d.ts +40 -4
- package/dist/BusyStatusTracker.d.ts +31 -0
- package/dist/BusyStatusTracker.js +83 -0
- package/dist/BusyStatusTracker.js.map +1 -0
- package/dist/Cache.js +3 -3
- package/dist/Cache.js.map +1 -1
- package/dist/CacheVerifier.d.ts +7 -0
- package/dist/CacheVerifier.js +20 -0
- package/dist/CacheVerifier.js.map +1 -0
- package/dist/CodeActionUtil.d.ts +3 -3
- package/dist/CodeActionUtil.js.map +1 -1
- package/dist/CommentFlagProcessor.d.ts +3 -2
- package/dist/CommentFlagProcessor.js +5 -4
- package/dist/CommentFlagProcessor.js.map +1 -1
- package/dist/DependencyGraph.d.ts +3 -2
- package/dist/DependencyGraph.js +11 -10
- package/dist/DependencyGraph.js.map +1 -1
- package/dist/DiagnosticCollection.js +9 -5
- package/dist/DiagnosticCollection.js.map +1 -1
- package/dist/DiagnosticFilterer.d.ts +1 -0
- package/dist/DiagnosticFilterer.js +5 -3
- package/dist/DiagnosticFilterer.js.map +1 -1
- package/dist/DiagnosticMessages.d.ts +61 -13
- package/dist/DiagnosticMessages.js +116 -19
- package/dist/DiagnosticMessages.js.map +1 -1
- package/dist/DiagnosticSeverityAdjuster.d.ts +7 -0
- package/dist/DiagnosticSeverityAdjuster.js +41 -0
- package/dist/DiagnosticSeverityAdjuster.js.map +1 -0
- package/dist/FunctionScope.d.ts +28 -0
- package/dist/FunctionScope.js +52 -0
- package/dist/FunctionScope.js.map +1 -0
- package/dist/KeyedThrottler.d.ts +3 -3
- package/dist/KeyedThrottler.js +3 -3
- package/dist/KeyedThrottler.js.map +1 -1
- package/dist/LanguageServer.d.ts +23 -11
- package/dist/LanguageServer.js +150 -69
- package/dist/LanguageServer.js.map +1 -1
- package/dist/Logger.d.ts +3 -2
- package/dist/Logger.js +11 -3
- package/dist/Logger.js.map +1 -1
- package/dist/PluginInterface.d.ts +21 -3
- package/dist/PluginInterface.js +74 -6
- package/dist/PluginInterface.js.map +1 -1
- package/dist/Program.d.ts +158 -79
- package/dist/Program.js +841 -706
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +22 -12
- package/dist/ProgramBuilder.js +130 -103
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +86 -137
- package/dist/Scope.js +453 -519
- package/dist/Scope.js.map +1 -1
- package/dist/Stopwatch.js +1 -1
- package/dist/Stopwatch.js.map +1 -1
- package/dist/SymbolTable.d.ts +89 -34
- package/dist/SymbolTable.js +239 -114
- package/dist/SymbolTable.js.map +1 -1
- package/dist/Throttler.d.ts +12 -0
- package/dist/Throttler.js +39 -0
- package/dist/Throttler.js.map +1 -1
- package/dist/Watcher.d.ts +0 -3
- package/dist/Watcher.js +0 -3
- package/dist/Watcher.js.map +1 -1
- package/dist/XmlScope.d.ts +4 -11
- package/dist/XmlScope.js +75 -88
- package/dist/XmlScope.js.map +1 -1
- package/dist/astUtils/CachedLookups.d.ts +48 -0
- package/dist/astUtils/CachedLookups.js +323 -0
- package/dist/astUtils/CachedLookups.js.map +1 -0
- package/dist/astUtils/{AstEditor.d.ts → Editor.d.ts} +9 -5
- package/dist/astUtils/{AstEditor.js → Editor.js} +10 -4
- package/dist/astUtils/Editor.js.map +1 -0
- package/dist/astUtils/{AstEditor.spec.js → Editor.spec.js} +69 -65
- package/dist/astUtils/Editor.spec.js.map +1 -0
- package/dist/astUtils/creators.d.ts +10 -10
- package/dist/astUtils/creators.js +54 -24
- package/dist/astUtils/creators.js.map +1 -1
- package/dist/astUtils/creators.spec.js +5 -5
- package/dist/astUtils/creators.spec.js.map +1 -1
- package/dist/astUtils/reflection.d.ts +132 -104
- package/dist/astUtils/reflection.js +220 -174
- package/dist/astUtils/reflection.js.map +1 -1
- package/dist/astUtils/reflection.spec.js +256 -157
- package/dist/astUtils/reflection.spec.js.map +1 -1
- package/dist/astUtils/stackedVisitor.spec.js +12 -12
- package/dist/astUtils/stackedVisitor.spec.js.map +1 -1
- package/dist/astUtils/visitors.d.ts +53 -35
- package/dist/astUtils/visitors.js +29 -3
- package/dist/astUtils/visitors.js.map +1 -1
- package/dist/astUtils/visitors.spec.js +208 -52
- package/dist/astUtils/visitors.spec.js.map +1 -1
- package/dist/astUtils/xml.d.ts +9 -9
- package/dist/astUtils/xml.js +9 -9
- package/dist/astUtils/xml.js.map +1 -1
- package/dist/bscPlugin/BscPlugin.d.ts +11 -2
- package/dist/bscPlugin/BscPlugin.js +37 -3
- package/dist/bscPlugin/BscPlugin.js.map +1 -1
- package/dist/bscPlugin/CallExpressionInfo.d.ts +36 -0
- package/dist/bscPlugin/CallExpressionInfo.js +131 -0
- package/dist/bscPlugin/CallExpressionInfo.js.map +1 -0
- package/dist/bscPlugin/FileWriter.d.ts +6 -0
- package/dist/bscPlugin/FileWriter.js +24 -0
- package/dist/bscPlugin/FileWriter.js.map +1 -0
- package/dist/bscPlugin/SignatureHelpUtil.d.ts +10 -0
- package/dist/bscPlugin/SignatureHelpUtil.js +136 -0
- package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +16 -13
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +16 -16
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +52 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.js +517 -26
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.spec.js +1909 -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 +210 -0
- package/dist/bscPlugin/definition/DefinitionProvider.js.map +1 -0
- package/dist/bscPlugin/definition/DefinitionProvider.spec.js +88 -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 +7 -7
- package/dist/bscPlugin/hover/HoverProcessor.js +123 -125
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -1
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +371 -53
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +2 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +83 -23
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +83 -6
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
- package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
- package/dist/bscPlugin/serialize/BslibManager.js +40 -0
- package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
- package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
- package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
- package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
- package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.d.ts → BrsFileTranspileProcessor.d.ts} +4 -2
- package/dist/bscPlugin/transpile/{BrsFilePreTranspileProcessor.js → BrsFileTranspileProcessor.js} +38 -12
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +41 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.d.ts +12 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js +99 -0
- package/dist/bscPlugin/transpile/XmlFilePreTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.d.ts +13 -5
- package/dist/bscPlugin/validation/BrsFileValidator.js +262 -52
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +230 -14
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -1
- package/dist/bscPlugin/validation/ProgramValidator.d.ts +10 -0
- package/dist/bscPlugin/validation/ProgramValidator.js +32 -0
- package/dist/bscPlugin/validation/ProgramValidator.js.map +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.d.ts +58 -27
- package/dist/bscPlugin/validation/ScopeValidator.js +514 -286
- package/dist/bscPlugin/validation/ScopeValidator.js.map +1 -1
- package/dist/bscPlugin/validation/ScopeValidator.spec.d.ts +1 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js +2527 -0
- package/dist/bscPlugin/validation/ScopeValidator.spec.js.map +1 -0
- package/dist/bscPlugin/validation/XmlFileValidator.d.ts +8 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js +44 -0
- package/dist/bscPlugin/validation/XmlFileValidator.js.map +1 -0
- package/dist/cli.js +104 -13
- package/dist/cli.js.map +1 -1
- package/dist/deferred.d.ts +3 -3
- package/dist/deferred.js.map +1 -1
- package/dist/diagnosticUtils.d.ts +8 -2
- package/dist/diagnosticUtils.js +47 -17
- package/dist/diagnosticUtils.js.map +1 -1
- package/dist/examples/plugins/removePrint.js +8 -10
- package/dist/examples/plugins/removePrint.js.map +1 -1
- package/dist/files/AssetFile.d.ts +26 -0
- package/dist/files/AssetFile.js +26 -0
- package/dist/files/AssetFile.js.map +1 -0
- package/dist/files/BrsFile.Class.spec.js +523 -493
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +111 -117
- package/dist/files/BrsFile.js +684 -1142
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1783 -1233
- package/dist/files/BrsFile.spec.js.map +1 -1
- package/dist/files/BscFile.d.ts +104 -0
- package/dist/files/BscFile.js +16 -0
- package/dist/files/BscFile.js.map +1 -0
- package/dist/files/Factory.d.ts +25 -0
- package/dist/files/Factory.js +22 -0
- package/dist/files/Factory.js.map +1 -0
- package/dist/files/LazyFileData.d.ts +20 -0
- package/dist/files/LazyFileData.js +54 -0
- package/dist/files/LazyFileData.js.map +1 -0
- package/dist/files/LazyFileData.spec.d.ts +1 -0
- package/dist/files/LazyFileData.spec.js +27 -0
- package/dist/files/LazyFileData.spec.js.map +1 -0
- package/dist/files/XmlFile.d.ts +70 -32
- package/dist/files/XmlFile.js +106 -118
- package/dist/files/XmlFile.js.map +1 -1
- package/dist/files/XmlFile.spec.js +325 -262
- package/dist/files/XmlFile.spec.js.map +1 -1
- package/dist/files/tests/imports.spec.js +48 -40
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.js +84 -24
- package/dist/files/tests/optionalChaning.spec.js.map +1 -1
- package/dist/globalCallables.js +16 -21
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +421 -162
- package/dist/interfaces.js +27 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/lexer/Character.spec.js +5 -5
- package/dist/lexer/Character.spec.js.map +1 -1
- package/dist/lexer/Lexer.d.ts +12 -5
- package/dist/lexer/Lexer.js +28 -13
- package/dist/lexer/Lexer.js.map +1 -1
- package/dist/lexer/Lexer.spec.js +181 -135
- package/dist/lexer/Lexer.spec.js.map +1 -1
- package/dist/lexer/Token.d.ts +9 -1
- package/dist/lexer/Token.js +9 -1
- package/dist/lexer/Token.js.map +1 -1
- package/dist/lexer/TokenKind.d.ts +8 -0
- package/dist/lexer/TokenKind.js +24 -4
- package/dist/lexer/TokenKind.js.map +1 -1
- package/dist/parser/AstNode.d.ts +162 -0
- package/dist/parser/AstNode.js +225 -0
- package/dist/parser/AstNode.js.map +1 -0
- package/dist/parser/AstNode.spec.d.ts +1 -0
- package/dist/parser/AstNode.spec.js +165 -0
- package/dist/parser/AstNode.spec.js.map +1 -0
- package/dist/parser/BrsTranspileState.d.ts +4 -7
- package/dist/parser/BrsTranspileState.js +4 -12
- package/dist/parser/BrsTranspileState.js.map +1 -1
- package/dist/parser/Expression.d.ts +376 -283
- package/dist/parser/Expression.js +742 -585
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +151 -145
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +48 -201
- package/dist/parser/Parser.js +705 -1026
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.d.ts +3 -1
- package/dist/parser/Parser.spec.js +861 -848
- package/dist/parser/Parser.spec.js.map +1 -1
- package/dist/parser/SGParser.d.ts +9 -8
- package/dist/parser/SGParser.js +10 -8
- package/dist/parser/SGParser.js.map +1 -1
- package/dist/parser/SGParser.spec.js +27 -38
- package/dist/parser/SGParser.spec.js.map +1 -1
- package/dist/parser/SGTypes.d.ts +98 -35
- package/dist/parser/SGTypes.js +169 -99
- package/dist/parser/SGTypes.js.map +1 -1
- package/dist/parser/Statement.d.ts +468 -272
- package/dist/parser/Statement.js +904 -631
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +47 -23
- package/dist/parser/Statement.spec.js.map +1 -1
- package/dist/parser/TranspileState.d.ts +1 -1
- package/dist/parser/TranspileState.js +7 -12
- package/dist/parser/TranspileState.js.map +1 -1
- package/dist/parser/tests/Parser.spec.js +3 -2
- package/dist/parser/tests/Parser.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/For.spec.js +33 -23
- package/dist/parser/tests/controlFlow/For.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/ForEach.spec.js +25 -20
- package/dist/parser/tests/controlFlow/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/If.spec.js +96 -94
- package/dist/parser/tests/controlFlow/If.spec.js.map +1 -1
- package/dist/parser/tests/controlFlow/While.spec.js +22 -16
- package/dist/parser/tests/controlFlow/While.spec.js.map +1 -1
- package/dist/parser/tests/expression/Additive.spec.js +8 -8
- package/dist/parser/tests/expression/Additive.spec.js.map +1 -1
- package/dist/parser/tests/expression/ArrayLiterals.spec.js +58 -21
- package/dist/parser/tests/expression/ArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js +62 -21
- package/dist/parser/tests/expression/AssociativeArrayLiterals.spec.js.map +1 -1
- package/dist/parser/tests/expression/Boolean.spec.js +8 -8
- package/dist/parser/tests/expression/Boolean.spec.js.map +1 -1
- package/dist/parser/tests/expression/Call.spec.js +129 -21
- package/dist/parser/tests/expression/Call.spec.js.map +1 -1
- package/dist/parser/tests/expression/Exponential.spec.js +5 -5
- package/dist/parser/tests/expression/Exponential.spec.js.map +1 -1
- package/dist/parser/tests/expression/Function.spec.js +36 -36
- package/dist/parser/tests/expression/Function.spec.js.map +1 -1
- package/dist/parser/tests/expression/Indexing.spec.js +92 -22
- package/dist/parser/tests/expression/Indexing.spec.js.map +1 -1
- package/dist/parser/tests/expression/Multiplicative.spec.js +9 -9
- package/dist/parser/tests/expression/Multiplicative.spec.js.map +1 -1
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js +59 -59
- package/dist/parser/tests/expression/NullCoalescenceExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/PrefixUnary.spec.js +12 -12
- package/dist/parser/tests/expression/PrefixUnary.spec.js.map +1 -1
- package/dist/parser/tests/expression/Primary.spec.js +12 -12
- package/dist/parser/tests/expression/Primary.spec.js.map +1 -1
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js +10 -10
- package/dist/parser/tests/expression/RegexLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/Relational.spec.js +13 -13
- package/dist/parser/tests/expression/Relational.spec.js.map +1 -1
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js +24 -24
- package/dist/parser/tests/expression/SourceLiteralExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js +96 -57
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +89 -89
- package/dist/parser/tests/expression/TernaryExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TypeExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/TypeExpression.spec.js +127 -0
- package/dist/parser/tests/expression/TypeExpression.spec.js.map +1 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.d.ts +1 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.js +52 -0
- package/dist/parser/tests/expression/UnaryExpression.spec.js.map +1 -0
- package/dist/parser/tests/statement/AssignmentOperators.spec.js +15 -15
- package/dist/parser/tests/statement/AssignmentOperators.spec.js.map +1 -1
- package/dist/parser/tests/statement/ConstStatement.spec.js +82 -33
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Continue.spec.js +119 -0
- package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
- package/dist/parser/tests/statement/Declaration.spec.js +19 -19
- package/dist/parser/tests/statement/Declaration.spec.js.map +1 -1
- package/dist/parser/tests/statement/Dim.spec.js +22 -22
- package/dist/parser/tests/statement/Dim.spec.js.map +1 -1
- package/dist/parser/tests/statement/Enum.spec.js +98 -302
- package/dist/parser/tests/statement/Enum.spec.js.map +1 -1
- package/dist/parser/tests/statement/For.spec.js +9 -10
- package/dist/parser/tests/statement/For.spec.js.map +1 -1
- package/dist/parser/tests/statement/ForEach.spec.js +8 -9
- package/dist/parser/tests/statement/ForEach.spec.js.map +1 -1
- package/dist/parser/tests/statement/Function.spec.js +44 -35
- package/dist/parser/tests/statement/Function.spec.js.map +1 -1
- package/dist/parser/tests/statement/Goto.spec.js +5 -5
- package/dist/parser/tests/statement/Goto.spec.js.map +1 -1
- package/dist/parser/tests/statement/Increment.spec.js +20 -20
- package/dist/parser/tests/statement/Increment.spec.js.map +1 -1
- package/dist/parser/tests/statement/InterfaceStatement.spec.js +30 -196
- package/dist/parser/tests/statement/InterfaceStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/LibraryStatement.spec.js +11 -11
- package/dist/parser/tests/statement/LibraryStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Misc.spec.js +16 -78
- package/dist/parser/tests/statement/Misc.spec.js.map +1 -1
- package/dist/parser/tests/statement/PrintStatement.spec.js +36 -34
- package/dist/parser/tests/statement/PrintStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/ReturnStatement.spec.js +14 -12
- package/dist/parser/tests/statement/ReturnStatement.spec.js.map +1 -1
- package/dist/parser/tests/statement/Set.spec.js +48 -35
- package/dist/parser/tests/statement/Set.spec.js.map +1 -1
- package/dist/parser/tests/statement/Stop.spec.js +6 -6
- package/dist/parser/tests/statement/Stop.spec.js.map +1 -1
- package/dist/parser/tests/statement/Throw.spec.js +6 -6
- package/dist/parser/tests/statement/Throw.spec.js.map +1 -1
- package/dist/parser/tests/statement/TryCatch.spec.js +18 -16
- package/dist/parser/tests/statement/TryCatch.spec.js.map +1 -1
- package/dist/preprocessor/Manifest.d.ts +1 -1
- package/dist/preprocessor/Manifest.js +2 -2
- package/dist/preprocessor/Manifest.js.map +1 -1
- package/dist/preprocessor/Manifest.spec.js +8 -8
- package/dist/preprocessor/Manifest.spec.js.map +1 -1
- package/dist/preprocessor/Preprocessor.d.ts +5 -6
- package/dist/preprocessor/Preprocessor.js +5 -5
- package/dist/preprocessor/Preprocessor.js.map +1 -1
- package/dist/preprocessor/Preprocessor.spec.js +25 -25
- package/dist/preprocessor/Preprocessor.spec.js.map +1 -1
- package/dist/preprocessor/PreprocessorParser.d.ts +1 -1
- package/dist/preprocessor/PreprocessorParser.js +7 -1
- package/dist/preprocessor/PreprocessorParser.js.map +1 -1
- package/dist/preprocessor/PreprocessorParser.spec.js +13 -13
- package/dist/preprocessor/PreprocessorParser.spec.js.map +1 -1
- package/dist/roku-types/data.json +5892 -10081
- package/dist/roku-types/index.d.ts +622 -1719
- package/dist/types/ArrayType.d.ts +10 -9
- package/dist/types/ArrayType.js +65 -60
- package/dist/types/ArrayType.js.map +1 -1
- package/dist/types/ArrayType.spec.js +36 -68
- package/dist/types/ArrayType.spec.js.map +1 -1
- package/dist/types/AssociativeArrayType.d.ts +11 -0
- package/dist/types/AssociativeArrayType.js +52 -0
- package/dist/types/AssociativeArrayType.js.map +1 -0
- package/dist/types/BaseFunctionType.d.ts +9 -0
- package/dist/types/BaseFunctionType.js +25 -0
- package/dist/types/BaseFunctionType.js.map +1 -0
- package/dist/types/BooleanType.d.ts +8 -5
- package/dist/types/BooleanType.js +14 -7
- package/dist/types/BooleanType.js.map +1 -1
- package/dist/types/BooleanType.spec.js +10 -6
- package/dist/types/BooleanType.spec.js.map +1 -1
- package/dist/types/BscType.d.ts +32 -21
- package/dist/types/BscType.js +118 -21
- package/dist/types/BscType.js.map +1 -1
- package/dist/types/BscTypeKind.d.ts +25 -0
- package/dist/types/BscTypeKind.js +30 -0
- package/dist/types/BscTypeKind.js.map +1 -0
- package/dist/types/BuiltInInterfaceAdder.d.ts +23 -0
- package/dist/types/BuiltInInterfaceAdder.js +171 -0
- package/dist/types/BuiltInInterfaceAdder.js.map +1 -0
- package/dist/types/BuiltInInterfaceAdder.spec.d.ts +1 -0
- package/dist/types/BuiltInInterfaceAdder.spec.js +116 -0
- package/dist/types/BuiltInInterfaceAdder.spec.js.map +1 -0
- package/dist/types/ClassType.d.ts +17 -0
- package/dist/types/ClassType.js +58 -0
- package/dist/types/ClassType.js.map +1 -0
- package/dist/types/ClassType.spec.d.ts +1 -0
- package/dist/types/ClassType.spec.js +77 -0
- package/dist/types/ClassType.spec.js.map +1 -0
- package/dist/types/ComponentType.d.ts +26 -0
- package/dist/types/ComponentType.js +83 -0
- package/dist/types/ComponentType.js.map +1 -0
- package/dist/types/DoubleType.d.ts +8 -5
- package/dist/types/DoubleType.js +18 -16
- package/dist/types/DoubleType.js.map +1 -1
- package/dist/types/DoubleType.spec.js +12 -6
- package/dist/types/DoubleType.spec.js.map +1 -1
- package/dist/types/DynamicType.d.ts +9 -5
- package/dist/types/DynamicType.js +15 -4
- package/dist/types/DynamicType.js.map +1 -1
- package/dist/types/DynamicType.spec.js +16 -5
- package/dist/types/DynamicType.spec.js.map +1 -1
- package/dist/types/EnumType.d.ts +30 -12
- package/dist/types/EnumType.js +43 -17
- package/dist/types/EnumType.js.map +1 -1
- package/dist/types/EnumType.spec.d.ts +1 -0
- package/dist/types/EnumType.spec.js +33 -0
- package/dist/types/EnumType.spec.js.map +1 -0
- package/dist/types/FloatType.d.ts +8 -5
- package/dist/types/FloatType.js +18 -16
- package/dist/types/FloatType.js.map +1 -1
- package/dist/types/FloatType.spec.js +4 -6
- package/dist/types/FloatType.spec.js.map +1 -1
- package/dist/types/FunctionType.d.ts +13 -8
- package/dist/types/FunctionType.js +30 -14
- package/dist/types/FunctionType.js.map +1 -1
- package/dist/types/InheritableType.d.ts +28 -0
- package/dist/types/InheritableType.js +152 -0
- package/dist/types/InheritableType.js.map +1 -0
- package/dist/types/IntegerType.d.ts +8 -5
- package/dist/types/IntegerType.js +18 -16
- package/dist/types/IntegerType.js.map +1 -1
- package/dist/types/IntegerType.spec.js +8 -6
- package/dist/types/IntegerType.spec.js.map +1 -1
- package/dist/types/InterfaceType.d.ts +12 -13
- package/dist/types/InterfaceType.js +20 -48
- package/dist/types/InterfaceType.js.map +1 -1
- package/dist/types/InterfaceType.spec.js +90 -56
- package/dist/types/InterfaceType.spec.js.map +1 -1
- package/dist/types/InvalidType.d.ts +7 -5
- package/dist/types/InvalidType.js +13 -7
- package/dist/types/InvalidType.js.map +1 -1
- package/dist/types/InvalidType.spec.js +8 -6
- package/dist/types/InvalidType.spec.js.map +1 -1
- package/dist/types/LongIntegerType.d.ts +8 -5
- package/dist/types/LongIntegerType.js +17 -15
- package/dist/types/LongIntegerType.js.map +1 -1
- package/dist/types/LongIntegerType.spec.js +10 -6
- package/dist/types/LongIntegerType.spec.js.map +1 -1
- package/dist/types/NamespaceType.d.ts +12 -0
- package/dist/types/NamespaceType.js +28 -0
- package/dist/types/NamespaceType.js.map +1 -0
- package/dist/types/ObjectType.d.ts +9 -8
- package/dist/types/ObjectType.js +21 -11
- package/dist/types/ObjectType.js.map +1 -1
- package/dist/types/ObjectType.spec.js +3 -3
- package/dist/types/ObjectType.spec.js.map +1 -1
- package/dist/types/ReferenceType.d.ts +63 -0
- package/dist/types/ReferenceType.js +423 -0
- package/dist/types/ReferenceType.js.map +1 -0
- package/dist/types/ReferenceType.spec.d.ts +1 -0
- package/dist/types/ReferenceType.spec.js +137 -0
- package/dist/types/ReferenceType.spec.js.map +1 -0
- package/dist/types/StringType.d.ts +11 -5
- package/dist/types/StringType.js +18 -7
- package/dist/types/StringType.js.map +1 -1
- package/dist/types/StringType.spec.js +3 -5
- package/dist/types/StringType.spec.js.map +1 -1
- package/dist/types/TypedFunctionType.d.ts +22 -17
- package/dist/types/TypedFunctionType.js +78 -60
- package/dist/types/TypedFunctionType.js.map +1 -1
- package/dist/types/TypedFunctionType.spec.js +105 -20
- package/dist/types/TypedFunctionType.spec.js.map +1 -1
- package/dist/types/UninitializedType.d.ts +8 -6
- package/dist/types/UninitializedType.js +13 -7
- package/dist/types/UninitializedType.js.map +1 -1
- package/dist/types/UnionType.d.ts +20 -0
- package/dist/types/UnionType.js +123 -0
- package/dist/types/UnionType.js.map +1 -0
- package/dist/types/UnionType.spec.d.ts +1 -0
- package/dist/types/UnionType.spec.js +130 -0
- package/dist/types/UnionType.spec.js.map +1 -0
- package/dist/types/VoidType.d.ts +8 -5
- package/dist/types/VoidType.js +14 -7
- package/dist/types/VoidType.js.map +1 -1
- package/dist/types/VoidType.spec.js +3 -3
- package/dist/types/VoidType.spec.js.map +1 -1
- package/dist/types/helper.spec.d.ts +1 -0
- package/dist/types/helper.spec.js +145 -0
- package/dist/types/helper.spec.js.map +1 -0
- package/dist/types/helpers.d.ts +19 -37
- package/dist/types/helpers.js +159 -99
- package/dist/types/helpers.js.map +1 -1
- package/dist/types/index.d.ts +22 -0
- package/dist/types/index.js +39 -0
- package/dist/types/index.js.map +1 -0
- package/dist/util.d.ts +143 -139
- package/dist/util.js +864 -385
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +8 -25
- package/dist/validators/ClassValidator.js +99 -179
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +165 -152
- package/dist/astUtils/AstEditor.js.map +0 -1
- package/dist/astUtils/AstEditor.spec.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js +0 -32
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.spec.js.map +0 -1
- package/dist/parser/SGTypes.spec.js +0 -351
- package/dist/parser/SGTypes.spec.js.map +0 -1
- package/dist/types/CustomType.d.ts +0 -12
- package/dist/types/CustomType.js +0 -44
- package/dist/types/CustomType.js.map +0 -1
- package/dist/types/LazyType.d.ts +0 -16
- package/dist/types/LazyType.js +0 -44
- package/dist/types/LazyType.js.map +0 -1
- /package/dist/astUtils/{AstEditor.spec.d.ts → Editor.spec.d.ts} +0 -0
- /package/dist/bscPlugin/{transpile/BrsFilePreTranspileProcessor.spec.d.ts → completions/CompletionsProcessor.spec.d.ts} +0 -0
- /package/dist/{parser/SGTypes.spec.d.ts → bscPlugin/definition/DefinitionProvider.spec.d.ts} +0 -0
package/dist/Scope.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Scope = void 0;
|
|
4
|
-
|
|
4
|
+
/* eslint-disable @typescript-eslint/dot-notation */
|
|
5
|
+
const path = require("path");
|
|
5
6
|
const chalk_1 = require("chalk");
|
|
6
7
|
const DiagnosticMessages_1 = require("./DiagnosticMessages");
|
|
8
|
+
const interfaces_1 = require("./interfaces");
|
|
7
9
|
const ClassValidator_1 = require("./validators/ClassValidator");
|
|
8
10
|
const Parser_1 = require("./parser/Parser");
|
|
9
11
|
const util_1 = require("./util");
|
|
@@ -13,9 +15,18 @@ const vscode_uri_1 = require("vscode-uri");
|
|
|
13
15
|
const Logger_1 = require("./Logger");
|
|
14
16
|
const reflection_1 = require("./astUtils/reflection");
|
|
15
17
|
const SymbolTable_1 = require("./SymbolTable");
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
18
|
+
const NamespaceType_1 = require("./types/NamespaceType");
|
|
19
|
+
const ReferenceType_1 = require("./types/ReferenceType");
|
|
20
|
+
const UnionType_1 = require("./types/UnionType");
|
|
21
|
+
const AssociativeArrayType_1 = require("./types/AssociativeArrayType");
|
|
22
|
+
const AstNode_1 = require("./parser/AstNode");
|
|
23
|
+
const visitors_1 = require("./astUtils/visitors");
|
|
24
|
+
/**
|
|
25
|
+
* Assign some few factories to the SymbolTable to prevent cyclical imports. This file seems like the most intuitive place to do the linking
|
|
26
|
+
* since Scope will be used by pretty much everything
|
|
27
|
+
*/
|
|
28
|
+
SymbolTable_1.SymbolTable.referenceTypeFactory = ReferenceType_1.referenceTypeFactory;
|
|
29
|
+
SymbolTable_1.SymbolTable.unionTypeFactory = UnionType_1.unionTypeFactory;
|
|
19
30
|
/**
|
|
20
31
|
* A class to keep track of all declarations within a given scope (like source scope, component scope)
|
|
21
32
|
*/
|
|
@@ -29,6 +40,11 @@ class Scope {
|
|
|
29
40
|
* The list of diagnostics found specifically for this scope. Individual file diagnostics are stored on the files themselves.
|
|
30
41
|
*/
|
|
31
42
|
this.diagnostics = [];
|
|
43
|
+
/**
|
|
44
|
+
* A list of functions that will be called whenever `unlinkSymbolTable` is called
|
|
45
|
+
*/
|
|
46
|
+
this.linkSymbolTableDisposables = [];
|
|
47
|
+
this.symbolsAddedDuringLinking = [];
|
|
32
48
|
this.isValidated = false;
|
|
33
49
|
//used for improved logging performance
|
|
34
50
|
this._debugLogComponentName = `Scope '${chalk_1.default.redBright(this.name)}'`;
|
|
@@ -42,8 +58,52 @@ class Scope {
|
|
|
42
58
|
* "namea", "namea.nameb", "namea.nameb.namec"
|
|
43
59
|
*/
|
|
44
60
|
get namespaceLookup() {
|
|
61
|
+
let allFilesValidated = true;
|
|
62
|
+
for (const file of this.getAllFiles()) {
|
|
63
|
+
if ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef) {
|
|
64
|
+
allFilesValidated = allFilesValidated && file.isValidated;
|
|
65
|
+
if (!allFilesValidated) {
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!allFilesValidated) {
|
|
71
|
+
// This is not fit to cache
|
|
72
|
+
// Since the files have not been validated, all namespace info might not have been available
|
|
73
|
+
return this.buildNamespaceLookup();
|
|
74
|
+
}
|
|
45
75
|
return this.cache.getOrAdd('namespaceLookup', () => this.buildNamespaceLookup());
|
|
46
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Get a NamespaceContainer by its name, looking for a fully qualified version first, then global version next if not found
|
|
79
|
+
*/
|
|
80
|
+
getNamespace(name, containingNamespace) {
|
|
81
|
+
const nameLower = name === null || name === void 0 ? void 0 : name.toLowerCase();
|
|
82
|
+
const lookup = this.namespaceLookup;
|
|
83
|
+
let ns;
|
|
84
|
+
if (containingNamespace) {
|
|
85
|
+
ns = lookup.get(`${containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()}.${nameLower}`);
|
|
86
|
+
}
|
|
87
|
+
//if we couldn't find the namespace by its full namespaced name, look for a global version
|
|
88
|
+
if (!ns) {
|
|
89
|
+
ns = lookup.get(nameLower);
|
|
90
|
+
}
|
|
91
|
+
return ns;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get a NamespaceContainer by its name, looking for a fully qualified version first, then global version next if not found
|
|
95
|
+
*/
|
|
96
|
+
getNamespacesWithRoot(rootName, containingNamespace) {
|
|
97
|
+
const nameLower = rootName === null || rootName === void 0 ? void 0 : rootName.toLowerCase();
|
|
98
|
+
const lookup = this.namespaceLookup;
|
|
99
|
+
const lookupKeys = [...lookup.keys()];
|
|
100
|
+
let lookupName = nameLower;
|
|
101
|
+
if (containingNamespace) {
|
|
102
|
+
lookupName = `${containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()}.${nameLower}`;
|
|
103
|
+
}
|
|
104
|
+
const nsList = lookupKeys.filter(key => key === lookupName).map(key => lookup.get(key));
|
|
105
|
+
return nsList;
|
|
106
|
+
}
|
|
47
107
|
/**
|
|
48
108
|
* Get the class with the specified name.
|
|
49
109
|
* @param className - The class name, including the namespace of the class if possible
|
|
@@ -62,23 +122,6 @@ class Scope {
|
|
|
62
122
|
var _a;
|
|
63
123
|
return (_a = this.getInterfaceFileLink(ifaceName, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
|
|
64
124
|
}
|
|
65
|
-
/**
|
|
66
|
-
* Get either the class or interface, etc. with a given name
|
|
67
|
-
* @param name - The name, including the namespace of the interface if possible
|
|
68
|
-
* @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find the interface or class)
|
|
69
|
-
*/
|
|
70
|
-
getNamedTypeStatement(name, containingNamespace) {
|
|
71
|
-
var _a;
|
|
72
|
-
return (_a = this.getNamedTypeFileLink(name, containingNamespace)) === null || _a === void 0 ? void 0 : _a.item;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* A cache of a map of tokens -> TokenSymbolLookups, which are the result of getSymbolTypeFromToken()
|
|
76
|
-
* Sometimes the lookup of symbols may take a while if there are lazyTypes or multiple tokens in a chain
|
|
77
|
-
* By caching the result of this lookup, subsequent lookups of the same tokens are quicker
|
|
78
|
-
*/
|
|
79
|
-
get symbolCache() {
|
|
80
|
-
return this.cache.getOrAdd('symbolCache', () => new Map());
|
|
81
|
-
}
|
|
82
125
|
/**
|
|
83
126
|
* Get the enum with the specified name.
|
|
84
127
|
* @param enumName - The enum name, including the namespace if possible
|
|
@@ -104,10 +147,10 @@ class Scope {
|
|
|
104
147
|
return cls;
|
|
105
148
|
}
|
|
106
149
|
/**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
150
|
+
* Get an interface and its containing file by the interface name
|
|
151
|
+
* @param ifaceName - The interface name, including the namespace of the interface if possible
|
|
152
|
+
* @param containingNamespace - The namespace used to resolve relative interface names. (i.e. the namespace around the current statement trying to find a interface)
|
|
153
|
+
*/
|
|
111
154
|
getInterfaceFileLink(ifaceName, containingNamespace) {
|
|
112
155
|
const lowerName = ifaceName === null || ifaceName === void 0 ? void 0 : ifaceName.toLowerCase();
|
|
113
156
|
const ifaceMap = this.getInterfaceMap();
|
|
@@ -134,34 +177,24 @@ class Scope {
|
|
|
134
177
|
return enumeration;
|
|
135
178
|
}
|
|
136
179
|
/**
|
|
137
|
-
* Get
|
|
138
|
-
* @param
|
|
139
|
-
* @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find a
|
|
140
|
-
*/
|
|
141
|
-
getNamedTypeFileLink(name, containingNamespace) {
|
|
142
|
-
return this.getInheritableFileLink(name, containingNamespace) || this.getEnumFileLink(name, containingNamespace);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Get a InheritableStatement and its containing file by the name of the interface or class
|
|
146
|
-
* @param name - The name of the interface or class, including the namespace of the class if possible
|
|
147
|
-
* @param containingNamespace - The namespace used to resolve relative names. (i.e. the namespace around the current statement trying to find a class)
|
|
148
|
-
*/
|
|
149
|
-
getInheritableFileLink(name, containingNamespace) {
|
|
150
|
-
return this.getClassFileLink(name, containingNamespace) || this.getInterfaceFileLink(name, containingNamespace);
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Gets the parent class of the given class
|
|
154
|
-
* @param klass - The class to get the parent of, if possible
|
|
180
|
+
* Get an Enum and its containing file by the Enum name
|
|
181
|
+
* @param enumMemberName - The Enum name, including the namespace of the enum if possible
|
|
182
|
+
* @param containingNamespace - The namespace used to resolve relative enum names. (i.e. the namespace around the current statement trying to find a enum)
|
|
155
183
|
*/
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
184
|
+
getEnumMemberFileLink(enumMemberName, containingNamespace) {
|
|
185
|
+
var _a, _b;
|
|
186
|
+
let lowerNameParts = (_a = enumMemberName === null || enumMemberName === void 0 ? void 0 : enumMemberName.toLowerCase()) === null || _a === void 0 ? void 0 : _a.split('.');
|
|
187
|
+
let memberName = (_b = lowerNameParts === null || lowerNameParts === void 0 ? void 0 : lowerNameParts.splice(lowerNameParts.length - 1, 1)) === null || _b === void 0 ? void 0 : _b[0];
|
|
188
|
+
let lowerName = lowerNameParts === null || lowerNameParts === void 0 ? void 0 : lowerNameParts.join('.');
|
|
189
|
+
const enumMap = this.getEnumMap();
|
|
190
|
+
let enumeration = enumMap.get(util_1.util.getFullyQualifiedClassName(lowerName, containingNamespace === null || containingNamespace === void 0 ? void 0 : containingNamespace.toLowerCase()));
|
|
191
|
+
//if we couldn't find the enum by its full namespaced name, look for a global enum with that name
|
|
192
|
+
if (!enumeration) {
|
|
193
|
+
enumeration = enumMap.get(lowerName);
|
|
194
|
+
}
|
|
195
|
+
if (enumeration) {
|
|
196
|
+
let member = enumeration.item.findChild((child) => { var _a; return (0, reflection_1.isEnumMemberStatement)(child) && ((_a = child.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === memberName; });
|
|
197
|
+
return member ? { item: member, file: enumeration.file } : undefined;
|
|
165
198
|
}
|
|
166
199
|
}
|
|
167
200
|
/**
|
|
@@ -179,38 +212,33 @@ class Scope {
|
|
|
179
212
|
}
|
|
180
213
|
return result;
|
|
181
214
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (foundParent) {
|
|
192
|
-
return foundParent.item;
|
|
193
|
-
}
|
|
215
|
+
getAllFileLinks(name, containingNamespace) {
|
|
216
|
+
var _a, _b, _c, _d, _e, _f;
|
|
217
|
+
let links = [];
|
|
218
|
+
links.push((_a = this.getClassFileLink(name)) !== null && _a !== void 0 ? _a : this.getClassFileLink(name, containingNamespace), (_b = this.getInterfaceFileLink(name)) !== null && _b !== void 0 ? _b : this.getInterfaceFileLink(name, containingNamespace), (_c = this.getConstFileLink(name)) !== null && _c !== void 0 ? _c : this.getConstFileLink(name, containingNamespace), (_d = this.getEnumFileLink(name)) !== null && _d !== void 0 ? _d : this.getEnumFileLink(name, containingNamespace));
|
|
219
|
+
const nameSpaces = this.getNamespacesWithRoot(name, containingNamespace);
|
|
220
|
+
if ((nameSpaces === null || nameSpaces === void 0 ? void 0 : nameSpaces.length) > 0) {
|
|
221
|
+
const nsContainersWithStatement = (_e = nameSpaces.filter(nsContainer => { var _a; return ((_a = nsContainer === null || nsContainer === void 0 ? void 0 : nsContainer.namespaceStatements) === null || _a === void 0 ? void 0 : _a.length) > 0; })) === null || _e === void 0 ? void 0 : _e[0];
|
|
222
|
+
if (nsContainersWithStatement) {
|
|
223
|
+
links.push({ item: (_f = nsContainersWithStatement === null || nsContainersWithStatement === void 0 ? void 0 : nsContainersWithStatement.namespaceStatements) === null || _f === void 0 ? void 0 : _f[0], file: nsContainersWithStatement === null || nsContainersWithStatement === void 0 ? void 0 : nsContainersWithStatement.file });
|
|
194
224
|
}
|
|
195
225
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
return this.getParentInterface(stmt);
|
|
204
|
-
}
|
|
205
|
-
else if ((0, reflection_1.isClassStatement)(stmt)) {
|
|
206
|
-
return this.getParentClass(stmt);
|
|
226
|
+
const fullNameLower = (containingNamespace ? `${containingNamespace}.${name}` : name).toLowerCase();
|
|
227
|
+
const callable = this.getCallableByName(name);
|
|
228
|
+
if (callable) {
|
|
229
|
+
if (!callable.hasNamespace || callable.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === fullNameLower) {
|
|
230
|
+
// this callable has no namespace, or has same namespace
|
|
231
|
+
links.push({ item: callable.functionStatement, file: callable.file });
|
|
232
|
+
}
|
|
207
233
|
}
|
|
234
|
+
// remove empty links
|
|
235
|
+
return links.filter(link => link);
|
|
208
236
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
237
|
+
/**
|
|
238
|
+
* Get a map of all enums by their member name.
|
|
239
|
+
* The keys are lower-case fully-qualified paths to the enum and its member. For example:
|
|
240
|
+
* namespace.enum.value
|
|
241
|
+
*/
|
|
214
242
|
getEnumMemberMap() {
|
|
215
243
|
return this.cache.getOrAdd('enumMemberMap', () => {
|
|
216
244
|
const result = new Map();
|
|
@@ -223,36 +251,28 @@ class Scope {
|
|
|
223
251
|
});
|
|
224
252
|
}
|
|
225
253
|
/**
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
254
|
+
* Tests if a class exists with the specified name
|
|
255
|
+
* @param className - the all-lower-case namespace-included class name
|
|
256
|
+
* @param namespaceName - The namespace used to resolve relative class names. (i.e. the namespace around the current statement trying to find a class)
|
|
257
|
+
*/
|
|
230
258
|
hasClass(className, namespaceName) {
|
|
231
259
|
return !!this.getClass(className, namespaceName);
|
|
232
260
|
}
|
|
233
261
|
/**
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
262
|
+
* Tests if an interface exists with the specified name
|
|
263
|
+
* @param ifaceName - the all-lower-case namespace-included interface name
|
|
264
|
+
* @param namespaceName - the current namespace name
|
|
265
|
+
*/
|
|
238
266
|
hasInterface(ifaceName, namespaceName) {
|
|
239
267
|
return !!this.getInterface(ifaceName, namespaceName);
|
|
240
268
|
}
|
|
241
269
|
/**
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
* @param namespaceName - the current namespace name
|
|
245
|
-
*/
|
|
246
|
-
hasEnum(enumName, namespaceName) {
|
|
247
|
-
return !!this.getEnum(enumName, namespaceName);
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Tests if a class OR an interface, etc. exists with the specified name
|
|
251
|
-
* @param name - the all-lower-case namespace-included class or interface name
|
|
270
|
+
* Tests if an enum exists with the specified name
|
|
271
|
+
* @param enumName - the all-lower-case namespace-included enum name
|
|
252
272
|
* @param namespaceName - the current namespace name
|
|
253
273
|
*/
|
|
254
|
-
|
|
255
|
-
return !!this.
|
|
274
|
+
hasEnum(enumName, namespaceName) {
|
|
275
|
+
return !!this.getEnum(enumName, namespaceName);
|
|
256
276
|
}
|
|
257
277
|
/**
|
|
258
278
|
* A dictionary of all classes in this scope. This includes namespaced classes always with their full name.
|
|
@@ -262,13 +282,12 @@ class Scope {
|
|
|
262
282
|
return this.cache.getOrAdd('classMap', () => {
|
|
263
283
|
const map = new Map();
|
|
264
284
|
this.enumerateBrsFiles((file) => {
|
|
265
|
-
var _a;
|
|
266
285
|
if ((0, reflection_1.isBrsFile)(file)) {
|
|
267
|
-
for (let cls of file.
|
|
268
|
-
const
|
|
286
|
+
for (let cls of file['_cachedLookups'].classStatements) {
|
|
287
|
+
const className = cls.getName(Parser_1.ParseMode.BrighterScript);
|
|
269
288
|
//only track classes with a defined name (i.e. exclude nameless malformed classes)
|
|
270
|
-
if (
|
|
271
|
-
map.set(
|
|
289
|
+
if (className) {
|
|
290
|
+
map.set(className.toLowerCase(), { item: cls, file: file });
|
|
272
291
|
}
|
|
273
292
|
}
|
|
274
293
|
}
|
|
@@ -276,29 +295,20 @@ class Scope {
|
|
|
276
295
|
return map;
|
|
277
296
|
});
|
|
278
297
|
}
|
|
279
|
-
getAncestorTypeListByContext(thisType, context) {
|
|
280
|
-
var _a;
|
|
281
|
-
const funcExpr = (_a = context === null || context === void 0 ? void 0 : context.file) === null || _a === void 0 ? void 0 : _a.getFunctionExpressionAtPosition(context === null || context === void 0 ? void 0 : context.position);
|
|
282
|
-
if ((0, reflection_1.isCustomType)(thisType) || (0, reflection_1.isInterfaceType)(thisType)) {
|
|
283
|
-
return this.getAncestorTypeList(thisType.name, funcExpr);
|
|
284
|
-
}
|
|
285
|
-
return [];
|
|
286
|
-
}
|
|
287
298
|
/**
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
299
|
+
* A dictionary of all Interfaces in this scope. This includes namespaced Interfaces always with their full name.
|
|
300
|
+
* The key is stored in lower case
|
|
301
|
+
*/
|
|
291
302
|
getInterfaceMap() {
|
|
292
303
|
return this.cache.getOrAdd('interfaceMap', () => {
|
|
293
304
|
const map = new Map();
|
|
294
305
|
this.enumerateBrsFiles((file) => {
|
|
295
|
-
var _a;
|
|
296
306
|
if ((0, reflection_1.isBrsFile)(file)) {
|
|
297
|
-
for (let iface of file.
|
|
298
|
-
const
|
|
307
|
+
for (let iface of file['_cachedLookups'].interfaceStatements) {
|
|
308
|
+
const ifaceName = iface.getName(Parser_1.ParseMode.BrighterScript);
|
|
299
309
|
//only track classes with a defined name (i.e. exclude nameless malformed classes)
|
|
300
|
-
if (
|
|
301
|
-
map.set(
|
|
310
|
+
if (ifaceName) {
|
|
311
|
+
map.set(ifaceName.toLowerCase(), { item: iface, file: file });
|
|
302
312
|
}
|
|
303
313
|
}
|
|
304
314
|
}
|
|
@@ -306,21 +316,6 @@ class Scope {
|
|
|
306
316
|
return map;
|
|
307
317
|
});
|
|
308
318
|
}
|
|
309
|
-
getAncestorTypeList(className, functionExpression) {
|
|
310
|
-
var _a, _b;
|
|
311
|
-
const lowerNamespaceName = (_a = functionExpression.namespaceName) === null || _a === void 0 ? void 0 : _a.getName().toLowerCase();
|
|
312
|
-
const ancestors = [];
|
|
313
|
-
let currentClassOrIFace = (_b = this.getInheritableFileLink(className, lowerNamespaceName)) === null || _b === void 0 ? void 0 : _b.item;
|
|
314
|
-
if (currentClassOrIFace) {
|
|
315
|
-
ancestors.push(currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.getThisBscType());
|
|
316
|
-
}
|
|
317
|
-
while (currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.hasParent()) {
|
|
318
|
-
currentClassOrIFace = this.getParentStatement(currentClassOrIFace);
|
|
319
|
-
ancestors.push(currentClassOrIFace === null || currentClassOrIFace === void 0 ? void 0 : currentClassOrIFace.getThisBscType());
|
|
320
|
-
}
|
|
321
|
-
// TODO TYPES: this should probably be cached
|
|
322
|
-
return ancestors;
|
|
323
|
-
}
|
|
324
319
|
/**
|
|
325
320
|
* A dictionary of all enums in this scope. This includes namespaced enums always with their full name.
|
|
326
321
|
* The key is stored in lower case
|
|
@@ -329,11 +324,10 @@ class Scope {
|
|
|
329
324
|
return this.cache.getOrAdd('enumMap', () => {
|
|
330
325
|
const map = new Map();
|
|
331
326
|
this.enumerateBrsFiles((file) => {
|
|
332
|
-
for (let enumStmt of file.
|
|
333
|
-
const lowerEnumName = enumStmt.fullName.toLowerCase();
|
|
327
|
+
for (let enumStmt of file['_cachedLookups'].enumStatements) {
|
|
334
328
|
//only track enums with a defined name (i.e. exclude nameless malformed enums)
|
|
335
|
-
if (
|
|
336
|
-
map.set(
|
|
329
|
+
if (enumStmt.fullName) {
|
|
330
|
+
map.set(enumStmt.fullName.toLowerCase(), { item: enumStmt, file: file });
|
|
337
331
|
}
|
|
338
332
|
}
|
|
339
333
|
});
|
|
@@ -348,11 +342,10 @@ class Scope {
|
|
|
348
342
|
return this.cache.getOrAdd('constMap', () => {
|
|
349
343
|
const map = new Map();
|
|
350
344
|
this.enumerateBrsFiles((file) => {
|
|
351
|
-
for (let stmt of file.
|
|
352
|
-
const lowerEnumName = stmt.fullName.toLowerCase();
|
|
345
|
+
for (let stmt of file['_cachedLookups'].constStatements) {
|
|
353
346
|
//only track enums with a defined name (i.e. exclude nameless malformed enums)
|
|
354
|
-
if (
|
|
355
|
-
map.set(
|
|
347
|
+
if (stmt.fullName) {
|
|
348
|
+
map.set(stmt.fullName.toLowerCase(), { item: stmt, file: file });
|
|
356
349
|
}
|
|
357
350
|
}
|
|
358
351
|
});
|
|
@@ -377,7 +370,7 @@ class Scope {
|
|
|
377
370
|
isKnownNamespace(namespaceName) {
|
|
378
371
|
let namespaceNameLower = namespaceName.toLowerCase();
|
|
379
372
|
this.enumerateBrsFiles((file) => {
|
|
380
|
-
for (let namespace of file.
|
|
373
|
+
for (let namespace of file['_cachedLookups'].namespaceStatements) {
|
|
381
374
|
let loopNamespaceNameLower = namespace.name.toLowerCase();
|
|
382
375
|
if (loopNamespaceNameLower === namespaceNameLower || loopNamespaceNameLower.startsWith(namespaceNameLower + '.')) {
|
|
383
376
|
return true;
|
|
@@ -393,7 +386,7 @@ class Scope {
|
|
|
393
386
|
*/
|
|
394
387
|
getParentScope() {
|
|
395
388
|
let scope;
|
|
396
|
-
//use the global scope if we didn't find a
|
|
389
|
+
//use the global scope if we didn't find a sope and this is not the global scope
|
|
397
390
|
if (this.program.globalScope !== this) {
|
|
398
391
|
scope = this.program.globalScope;
|
|
399
392
|
}
|
|
@@ -416,20 +409,23 @@ class Scope {
|
|
|
416
409
|
this.invalidate();
|
|
417
410
|
}
|
|
418
411
|
/**
|
|
419
|
-
* Get the file with the
|
|
420
|
-
* @param filePath can be a srcPath
|
|
412
|
+
* Get the file from this scope with the given path.
|
|
413
|
+
* @param filePath can be a srcPath or destPath
|
|
421
414
|
* @param normalizePath should this function repair and standardize the path? Passing false should have a performance boost if you can guarantee your path is already sanitized
|
|
422
415
|
*/
|
|
423
|
-
getFile(
|
|
424
|
-
if (
|
|
425
|
-
|
|
416
|
+
getFile(filePath, normalizePath = true) {
|
|
417
|
+
if (typeof filePath !== 'string') {
|
|
418
|
+
return undefined;
|
|
426
419
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
420
|
+
const key = path.isAbsolute(filePath) ? 'srcPath' : 'destPath';
|
|
421
|
+
let map = this.cache.getOrAdd('fileMaps-srcPath', () => {
|
|
422
|
+
const result = new Map();
|
|
423
|
+
for (const file of this.getAllFiles()) {
|
|
424
|
+
result.set(file[key].toLowerCase(), file);
|
|
431
425
|
}
|
|
432
|
-
|
|
426
|
+
return result;
|
|
427
|
+
});
|
|
428
|
+
return map.get((normalizePath ? util_1.util.standardizePath(filePath) : filePath).toLowerCase());
|
|
433
429
|
}
|
|
434
430
|
/**
|
|
435
431
|
* Get the list of files referenced by this scope that are actually loaded in the program.
|
|
@@ -456,32 +452,32 @@ class Scope {
|
|
|
456
452
|
}
|
|
457
453
|
}
|
|
458
454
|
else {
|
|
459
|
-
let file = this.program.getFile(dependency
|
|
455
|
+
let file = this.program.getFile(dependency);
|
|
460
456
|
if (file) {
|
|
461
457
|
result.push(file);
|
|
462
458
|
}
|
|
463
459
|
}
|
|
464
460
|
}
|
|
465
|
-
this.logDebug('getAllFiles', () => result.map(x => x.
|
|
461
|
+
this.logDebug('getAllFiles', () => result.map(x => x.destPath));
|
|
466
462
|
return result;
|
|
467
463
|
});
|
|
468
464
|
}
|
|
469
465
|
/**
|
|
470
|
-
* Get the list of errors for this scope. It's calculated on the fly, so
|
|
471
|
-
* call this sparingly.
|
|
466
|
+
* Get the list of errors for this scope. It's calculated on the fly, so call this sparingly.
|
|
472
467
|
*/
|
|
473
468
|
getDiagnostics() {
|
|
474
|
-
let diagnosticLists = [this.diagnostics];
|
|
475
469
|
//add diagnostics from every referenced file
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
470
|
+
const diagnostics = [
|
|
471
|
+
//diagnostics raised on this scope
|
|
472
|
+
...this.diagnostics,
|
|
473
|
+
//get diagnostics from all files
|
|
474
|
+
...this.getOwnFiles().map(x => { var _a; return (_a = x.diagnostics) !== null && _a !== void 0 ? _a : []; }).flat()
|
|
475
|
+
]
|
|
476
|
+
//exclude diagnostics that match any of the comment flags
|
|
477
|
+
.filter((x) => {
|
|
481
478
|
return !util_1.util.diagnosticIsSuppressed(x);
|
|
482
479
|
});
|
|
483
|
-
|
|
484
|
-
return filteredDiagnostics;
|
|
480
|
+
return diagnostics;
|
|
485
481
|
}
|
|
486
482
|
addDiagnostics(diagnostics) {
|
|
487
483
|
this.diagnostics.push(...diagnostics);
|
|
@@ -502,27 +498,23 @@ class Scope {
|
|
|
502
498
|
/**
|
|
503
499
|
* Get the callable with the specified name.
|
|
504
500
|
* If there are overridden callables with the same name, the closest callable to this scope is returned
|
|
505
|
-
* @param name
|
|
506
501
|
*/
|
|
507
502
|
getCallableByName(name) {
|
|
508
|
-
|
|
509
|
-
let lowerName = name.toLowerCase();
|
|
510
|
-
let callables = this.getAllCallables();
|
|
511
|
-
for (let callable of callables) {
|
|
512
|
-
const callableName = callable.callable.getName(Parser_1.ParseMode.BrighterScript);
|
|
513
|
-
// Split by `.` and check the last term to consider namespaces.
|
|
514
|
-
if (callableName.toLowerCase() === lowerName || ((_a = callableName.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === lowerName) {
|
|
515
|
-
return callable.callable;
|
|
516
|
-
}
|
|
517
|
-
}
|
|
503
|
+
return this.getCallableMap().get(name.toLowerCase());
|
|
518
504
|
}
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
505
|
+
getCallableMap() {
|
|
506
|
+
return this.cache.getOrAdd('callableMap', () => {
|
|
507
|
+
var _a, _b;
|
|
508
|
+
const result = new Map();
|
|
509
|
+
for (let callable of this.getAllCallables()) {
|
|
510
|
+
const callableName = (_a = callable.callable.getName(Parser_1.ParseMode.BrighterScript)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
511
|
+
result.set(callableName, callable.callable);
|
|
512
|
+
result.set(
|
|
513
|
+
// Split by `.` and check the last term to consider namespaces.
|
|
514
|
+
(_b = callableName.split('.').pop()) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callable.callable);
|
|
515
|
+
}
|
|
516
|
+
return result;
|
|
517
|
+
});
|
|
526
518
|
}
|
|
527
519
|
/**
|
|
528
520
|
* Iterate over Brs files not shadowed by typedefs
|
|
@@ -543,7 +535,7 @@ class Scope {
|
|
|
543
535
|
const files = this.getOwnFiles();
|
|
544
536
|
for (const file of files) {
|
|
545
537
|
//either XML components or files without a typedef
|
|
546
|
-
if ((0, reflection_1.isXmlFile)(file) || !file.hasTypedef) {
|
|
538
|
+
if ((0, reflection_1.isXmlFile)(file) || ((0, reflection_1.isBrsFile)(file) && !file.hasTypedef)) {
|
|
547
539
|
callback(file);
|
|
548
540
|
}
|
|
549
541
|
}
|
|
@@ -554,14 +546,16 @@ class Scope {
|
|
|
554
546
|
*/
|
|
555
547
|
getOwnCallables() {
|
|
556
548
|
let result = [];
|
|
557
|
-
this.logDebug('getOwnCallables() files: ', () => this.getOwnFiles().map(x => x.
|
|
549
|
+
this.logDebug('getOwnCallables() files: ', () => this.getOwnFiles().map(x => x.destPath));
|
|
558
550
|
//get callables from own files
|
|
559
551
|
this.enumerateOwnFiles((file) => {
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
552
|
+
if ((0, reflection_1.isBrsFile)(file)) {
|
|
553
|
+
for (let callable of file.callables) {
|
|
554
|
+
result.push({
|
|
555
|
+
callable: callable,
|
|
556
|
+
scope: this
|
|
557
|
+
});
|
|
558
|
+
}
|
|
565
559
|
}
|
|
566
560
|
});
|
|
567
561
|
return result;
|
|
@@ -569,68 +563,27 @@ class Scope {
|
|
|
569
563
|
/**
|
|
570
564
|
* Builds a tree of namespace objects
|
|
571
565
|
*/
|
|
572
|
-
buildNamespaceLookup() {
|
|
566
|
+
buildNamespaceLookup(options = { okToCache: true }) {
|
|
573
567
|
let namespaceLookup = new Map();
|
|
568
|
+
options.okToCache = true;
|
|
574
569
|
this.enumerateBrsFiles((file) => {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
for (let part of nameParts) {
|
|
583
|
-
loopName = loopName === null ? part : `${loopName}.${part}`;
|
|
584
|
-
let lowerLoopName = loopName.toLowerCase();
|
|
585
|
-
if (!namespaceLookup.has(lowerLoopName)) {
|
|
586
|
-
namespaceLookup.set(lowerLoopName, {
|
|
587
|
-
file: file,
|
|
588
|
-
fullName: loopName,
|
|
589
|
-
nameRange: namespaceStatement.nameExpression.range,
|
|
590
|
-
lastPartName: part,
|
|
591
|
-
namespaces: new Map(),
|
|
592
|
-
classStatements: {},
|
|
593
|
-
functionStatements: {},
|
|
594
|
-
interfaceStatements: {},
|
|
595
|
-
enumStatements: new Map(),
|
|
596
|
-
constStatements: new Map(),
|
|
597
|
-
statements: [],
|
|
598
|
-
symbolTable: new SymbolTable_1.SymbolTable(this.symbolTable, `Namespace ${loopName}`)
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
let ns = namespaceLookup.get(name.toLowerCase());
|
|
603
|
-
ns.statements.push(...namespaceStatement.body.statements);
|
|
604
|
-
for (let statement of namespaceStatement.body.statements) {
|
|
605
|
-
if ((0, reflection_1.isClassStatement)(statement) && statement.name) {
|
|
606
|
-
ns.classStatements[statement.name.text.toLowerCase()] = statement;
|
|
607
|
-
}
|
|
608
|
-
else if ((0, reflection_1.isInterfaceStatement)(statement) && statement.name) {
|
|
609
|
-
ns.interfaceStatements[statement.name.text.toLowerCase()] = statement;
|
|
610
|
-
}
|
|
611
|
-
else if ((0, reflection_1.isFunctionStatement)(statement) && statement.name) {
|
|
612
|
-
ns.functionStatements[statement.name.text.toLowerCase()] = statement;
|
|
613
|
-
}
|
|
614
|
-
else if ((0, reflection_1.isEnumStatement)(statement) && statement.fullName) {
|
|
615
|
-
ns.enumStatements.set(statement.fullName.toLowerCase(), statement);
|
|
616
|
-
}
|
|
617
|
-
else if ((0, reflection_1.isConstStatement)(statement) && statement.fullName) {
|
|
618
|
-
ns.constStatements.set(statement.fullName.toLowerCase(), statement);
|
|
619
|
-
}
|
|
570
|
+
options.okToCache = options.okToCache && file.isValidated;
|
|
571
|
+
const fileNamespaceLookup = file.getNamespaceLookupObject();
|
|
572
|
+
for (const [lowerNamespaceName, nsContainer] of fileNamespaceLookup) {
|
|
573
|
+
if (!namespaceLookup.has(lowerNamespaceName)) {
|
|
574
|
+
const clonedNsContainer = Object.assign(Object.assign({}, nsContainer), { namespaceStatements: [...nsContainer.namespaceStatements], symbolTable: new SymbolTable_1.SymbolTable(`Namespace Aggregate: '${nsContainer.fullName}'`) });
|
|
575
|
+
clonedNsContainer.symbolTable.mergeSymbolTable(nsContainer.symbolTable);
|
|
576
|
+
namespaceLookup.set(lowerNamespaceName, clonedNsContainer);
|
|
620
577
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
parts.pop();
|
|
631
|
-
let parentName = parts.join('.');
|
|
632
|
-
const parent = namespaceLookup.get(parentName.toLowerCase());
|
|
633
|
-
parent.namespaces.set(ns.lastPartName.toLowerCase(), ns);
|
|
578
|
+
else {
|
|
579
|
+
const existingContainer = namespaceLookup.get(lowerNamespaceName);
|
|
580
|
+
existingContainer.classStatements = new Map([...existingContainer.classStatements, ...nsContainer.classStatements]);
|
|
581
|
+
existingContainer.constStatements = new Map([...existingContainer.constStatements, ...nsContainer.constStatements]);
|
|
582
|
+
existingContainer.enumStatements = new Map([...existingContainer.enumStatements, ...nsContainer.enumStatements]);
|
|
583
|
+
existingContainer.functionStatements = new Map([...existingContainer.functionStatements, ...nsContainer.functionStatements]);
|
|
584
|
+
existingContainer.namespaces = new Map([...existingContainer.namespaces, ...nsContainer.namespaces]);
|
|
585
|
+
existingContainer.namespaceStatements.push(...nsContainer.namespaceStatements);
|
|
586
|
+
existingContainer.symbolTable.mergeSymbolTable(nsContainer.symbolTable);
|
|
634
587
|
}
|
|
635
588
|
}
|
|
636
589
|
});
|
|
@@ -639,87 +592,96 @@ class Scope {
|
|
|
639
592
|
getAllNamespaceStatements() {
|
|
640
593
|
let result = [];
|
|
641
594
|
this.enumerateBrsFiles((file) => {
|
|
642
|
-
result.push(...file.
|
|
595
|
+
result.push(...file['_cachedLookups'].namespaceStatements);
|
|
643
596
|
});
|
|
644
597
|
return result;
|
|
645
598
|
}
|
|
646
599
|
logDebug(...args) {
|
|
647
600
|
this.program.logger.debug(this._debugLogComponentName, ...args);
|
|
648
601
|
}
|
|
649
|
-
validate() {
|
|
602
|
+
validate(validationOptions = { force: false }) {
|
|
603
|
+
//if this scope is already validated, no need to revalidate
|
|
604
|
+
if (this.isValidated === true && !validationOptions.force) {
|
|
605
|
+
this.logDebug('validate(): already validated');
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
650
608
|
this.program.logger.time(Logger_1.LogLevel.debug, [this._debugLogComponentName, 'validate()'], () => {
|
|
651
609
|
let parentScope = this.getParentScope();
|
|
652
610
|
//validate our parent before we validate ourself
|
|
653
|
-
if (
|
|
611
|
+
if (parentScope && parentScope.isValidated === false) {
|
|
654
612
|
this.logDebug('validate(): validating parent first');
|
|
655
|
-
parentScope.validate();
|
|
613
|
+
parentScope.validate(validationOptions);
|
|
656
614
|
}
|
|
657
615
|
//clear the scope's errors list (we will populate them from this method)
|
|
658
|
-
this.
|
|
616
|
+
this.clearScopeLevelDiagnostics();
|
|
617
|
+
let callables = this.getAllCallables();
|
|
618
|
+
//sort the callables by filepath and then method name, so the errors will be consistent
|
|
619
|
+
// eslint-disable-next-line prefer-arrow-callback
|
|
620
|
+
callables = callables.sort((a, b) => {
|
|
621
|
+
const pathA = a.callable.file.srcPath;
|
|
622
|
+
const pathB = b.callable.file.srcPath;
|
|
623
|
+
//sort by path
|
|
624
|
+
if (pathA < pathB) {
|
|
625
|
+
return -1;
|
|
626
|
+
}
|
|
627
|
+
else if (pathA > pathB) {
|
|
628
|
+
return 1;
|
|
629
|
+
}
|
|
630
|
+
//sort by function name
|
|
631
|
+
const funcA = b.callable.name;
|
|
632
|
+
const funcB = b.callable.name;
|
|
633
|
+
if (funcA < funcB) {
|
|
634
|
+
return -1;
|
|
635
|
+
}
|
|
636
|
+
else if (funcA > funcB) {
|
|
637
|
+
return 1;
|
|
638
|
+
}
|
|
639
|
+
return 0;
|
|
640
|
+
});
|
|
641
|
+
//get a list of all callables, indexed by their lower case names
|
|
642
|
+
let callableContainerMap = util_1.util.getCallableContainersByLowerName(callables);
|
|
659
643
|
//Since statements from files are shared across multiple scopes, we need to link those statements to the current scope
|
|
660
644
|
this.linkSymbolTable();
|
|
661
|
-
|
|
662
|
-
program: this.program,
|
|
663
|
-
scope: this
|
|
664
|
-
});
|
|
665
|
-
this.program.plugins.emit('onScopeValidate', {
|
|
645
|
+
const scopeValidateEvent = {
|
|
666
646
|
program: this.program,
|
|
667
|
-
scope: this
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
647
|
+
scope: this,
|
|
648
|
+
changedFiles: validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.changedFiles,
|
|
649
|
+
changedSymbols: validationOptions === null || validationOptions === void 0 ? void 0 : validationOptions.changedSymbols
|
|
650
|
+
};
|
|
651
|
+
this.program.plugins.emit('beforeScopeValidate', scopeValidateEvent);
|
|
652
|
+
this.program.plugins.emit('onScopeValidate', scopeValidateEvent);
|
|
653
|
+
this._validate(callableContainerMap);
|
|
654
|
+
this.program.plugins.emit('afterScopeValidate', scopeValidateEvent);
|
|
674
655
|
//unlink all symbol tables from this scope (so they don't accidentally stick around)
|
|
675
656
|
this.unlinkSymbolTable();
|
|
676
657
|
this.isValidated = true;
|
|
677
658
|
});
|
|
678
659
|
}
|
|
679
|
-
//Get a list of all callables, indexed by their lower case name
|
|
680
|
-
getCallableContainerMap() {
|
|
681
|
-
let callables = this.getAllCallables();
|
|
682
|
-
//sort the callables by filepath and then method name, so the errors will be consistent
|
|
683
|
-
// eslint-disable-next-line prefer-arrow-callback
|
|
684
|
-
callables = callables.sort((a, b) => {
|
|
685
|
-
const pathA = a.callable.file.srcPath;
|
|
686
|
-
const pathB = b.callable.file.srcPath;
|
|
687
|
-
//sort by path
|
|
688
|
-
if (pathA < pathB) {
|
|
689
|
-
return -1;
|
|
690
|
-
}
|
|
691
|
-
else if (pathA > pathB) {
|
|
692
|
-
return 1;
|
|
693
|
-
}
|
|
694
|
-
//sort by function name
|
|
695
|
-
const funcA = b.callable.name;
|
|
696
|
-
const funcB = b.callable.name;
|
|
697
|
-
if (funcA < funcB) {
|
|
698
|
-
return -1;
|
|
699
|
-
}
|
|
700
|
-
else if (funcA > funcB) {
|
|
701
|
-
return 1;
|
|
702
|
-
}
|
|
703
|
-
return 0;
|
|
704
|
-
});
|
|
705
|
-
//get a list of all callables, indexed by their lower case names
|
|
706
|
-
return util_1.util.getCallableContainersByLowerName(callables);
|
|
707
|
-
}
|
|
708
660
|
_validate(callableContainerMap) {
|
|
709
661
|
//find all duplicate function declarations
|
|
710
662
|
this.diagnosticFindDuplicateFunctionDeclarations(callableContainerMap);
|
|
711
663
|
//detect missing and incorrect-case script imports
|
|
712
664
|
this.diagnosticValidateScriptImportPaths();
|
|
665
|
+
//enforce a series of checks on the bodies of class methods
|
|
666
|
+
this.validateClasses();
|
|
713
667
|
//do many per-file checks
|
|
714
668
|
this.enumerateBrsFiles((file) => {
|
|
715
|
-
//enforce a series of checks on the bodies of class methods
|
|
716
|
-
this.validateClasses(file);
|
|
717
669
|
this.diagnosticDetectShadowedLocalVars(file, callableContainerMap);
|
|
718
670
|
this.diagnosticDetectFunctionCollisions(file);
|
|
719
671
|
this.detectVariableNamespaceCollisions(file);
|
|
720
|
-
this.
|
|
672
|
+
this.detectNameCollisions(file);
|
|
721
673
|
});
|
|
722
674
|
}
|
|
675
|
+
clearAstSegmentDiagnostics(astSegment) {
|
|
676
|
+
this.diagnostics = this.diagnostics.filter(diag => !(diag.origin === interfaces_1.DiagnosticOrigin.ASTSegment && diag.astSegment === astSegment));
|
|
677
|
+
}
|
|
678
|
+
clearAstSegmentDiagnosticsByFile(file) {
|
|
679
|
+
const lowerSrcPath = file.srcPath.toLowerCase();
|
|
680
|
+
this.diagnostics = this.diagnostics.filter(diag => !(diag.origin === interfaces_1.DiagnosticOrigin.ASTSegment && diag.file.srcPath.toLowerCase() === lowerSrcPath));
|
|
681
|
+
}
|
|
682
|
+
clearScopeLevelDiagnostics() {
|
|
683
|
+
this.diagnostics = this.diagnostics.filter(diag => diag.origin !== interfaces_1.DiagnosticOrigin.Scope);
|
|
684
|
+
}
|
|
723
685
|
/**
|
|
724
686
|
* Mark this scope as invalid, which means its `validate()` function needs to be called again before use.
|
|
725
687
|
*/
|
|
@@ -727,119 +689,129 @@ class Scope {
|
|
|
727
689
|
this.isValidated = false;
|
|
728
690
|
//clear out various lookups (they'll get regenerated on demand the next time they're requested)
|
|
729
691
|
this.cache.clear();
|
|
730
|
-
this.clearSymbolTable();
|
|
731
|
-
this.symbolCache.clear();
|
|
732
692
|
}
|
|
733
693
|
get symbolTable() {
|
|
734
694
|
return this.cache.getOrAdd('symbolTable', () => {
|
|
735
|
-
var _a
|
|
736
|
-
const result = new SymbolTable_1.SymbolTable((_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.symbolTable
|
|
737
|
-
result.addSymbol('m',
|
|
695
|
+
var _a;
|
|
696
|
+
const result = new SymbolTable_1.SymbolTable(`Scope: '${this.name}'`, () => { var _a; return (_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.symbolTable; });
|
|
697
|
+
result.addSymbol('m', undefined, new AssociativeArrayType_1.AssociativeArrayType(), SymbolTable_1.SymbolTypeFlag.runtime);
|
|
738
698
|
for (let file of this.getOwnFiles()) {
|
|
739
699
|
if ((0, reflection_1.isBrsFile)(file)) {
|
|
740
|
-
result.mergeSymbolTable((
|
|
700
|
+
result.mergeSymbolTable((_a = file.parser) === null || _a === void 0 ? void 0 : _a.symbolTable);
|
|
741
701
|
}
|
|
742
702
|
}
|
|
743
703
|
return result;
|
|
744
704
|
});
|
|
745
705
|
}
|
|
746
|
-
get memberTable() {
|
|
747
|
-
var _a;
|
|
748
|
-
if (!this._memberTable) {
|
|
749
|
-
this._memberTable = new SymbolTable_1.SymbolTable((_a = this.getParentScope()) === null || _a === void 0 ? void 0 : _a.memberTable);
|
|
750
|
-
if (!this.getParentScope()) {
|
|
751
|
-
this._memberTable.addSymbol('global', null, new ObjectType_1.ObjectType());
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
return this._memberTable;
|
|
755
|
-
}
|
|
756
|
-
clearSymbolTable() {
|
|
757
|
-
this.cache.delete('symbolTable');
|
|
758
|
-
this._memberTable = null;
|
|
759
|
-
}
|
|
760
706
|
/**
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
707
|
+
* Builds the current symbol table for the scope, by merging the tables for all the files in this scope.
|
|
708
|
+
* Also links all file symbols tables to this new table
|
|
709
|
+
* This will only rebuilt if the symbol table has not been built before
|
|
710
|
+
*
|
|
711
|
+
* Tree of symbol tables:
|
|
712
|
+
* ```
|
|
713
|
+
* Global Scope Symbol Table
|
|
714
|
+
* - Source Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
|
|
715
|
+
* - File 1 Symbol Table
|
|
716
|
+
* - File 2 Symbol Table
|
|
717
|
+
* - Component A Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
|
|
718
|
+
* - File 1 Symbol Table
|
|
719
|
+
* - File 2 Symbol Table
|
|
720
|
+
* - Component B Scope Symbol Table :: Aggregate Namespaces Symbol Table (Siblings)
|
|
721
|
+
* - File 1 Symbol Table
|
|
722
|
+
* - File 2 Symbol Table
|
|
723
|
+
* ```
|
|
724
|
+
*/
|
|
765
725
|
linkSymbolTable() {
|
|
766
|
-
var _a
|
|
726
|
+
var _a;
|
|
727
|
+
SymbolTable_1.SymbolTable.cacheVerifier.generateToken();
|
|
767
728
|
for (const file of this.getAllFiles()) {
|
|
768
729
|
if ((0, reflection_1.isBrsFile)(file)) {
|
|
769
|
-
file.parser.symbolTable.
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
730
|
+
this.linkSymbolTableDisposables.push(file.parser.symbolTable.pushParentProvider(() => this.symbolTable));
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
//Add namespace aggregates to namespace member tables
|
|
734
|
+
const namespaceTypesKnown = new Map();
|
|
735
|
+
// eslint-disable-next-line no-bitwise
|
|
736
|
+
let getTypeOptions = { flags: SymbolTable_1.SymbolTypeFlag.runtime | SymbolTable_1.SymbolTypeFlag.typetime };
|
|
737
|
+
for (const [nsName, nsContainer] of this.namespaceLookup) {
|
|
738
|
+
let currentNSType = null;
|
|
739
|
+
let parentNSType = null;
|
|
740
|
+
const existingNsStmt = (_a = nsContainer.namespaceStatements) === null || _a === void 0 ? void 0 : _a[0];
|
|
741
|
+
if (!nsContainer.isTopLevel) {
|
|
742
|
+
parentNSType = namespaceTypesKnown.get(nsContainer.parentNameLower);
|
|
743
|
+
if (!parentNSType) {
|
|
744
|
+
// we don't know about the parent namespace... uh, oh!
|
|
745
|
+
break;
|
|
775
746
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
747
|
+
currentNSType = parentNSType.getMemberType(nsContainer.fullNameLower, getTypeOptions);
|
|
748
|
+
}
|
|
749
|
+
else {
|
|
750
|
+
currentNSType = this.symbolTable.getSymbolType(nsContainer.fullNameLower, getTypeOptions);
|
|
751
|
+
}
|
|
752
|
+
if (!(0, reflection_1.isNamespaceType)(currentNSType)) {
|
|
753
|
+
if (!currentNSType || (0, reflection_1.isReferenceType)(currentNSType)) {
|
|
754
|
+
currentNSType = existingNsStmt
|
|
755
|
+
? existingNsStmt.getType(getTypeOptions)
|
|
756
|
+
: new NamespaceType_1.NamespaceType(nsName);
|
|
757
|
+
if (parentNSType) {
|
|
758
|
+
// adding as a member of existing NS
|
|
759
|
+
parentNSType.addMember(nsContainer.lastPartName, { definingNode: existingNsStmt }, currentNSType, getTypeOptions.flags);
|
|
760
|
+
this.symbolsAddedDuringLinking.push({ symbolTable: parentNSType.getMemberTable(), name: nsContainer.lastPartName, flags: getTypeOptions.flags });
|
|
785
761
|
}
|
|
786
762
|
else {
|
|
787
|
-
|
|
763
|
+
this.symbolTable.addSymbol(nsContainer.lastPartName, { definingNode: existingNsStmt }, currentNSType, getTypeOptions.flags);
|
|
764
|
+
this.symbolsAddedDuringLinking.push({ symbolTable: this.symbolTable, name: nsContainer.lastPartName, flags: getTypeOptions.flags });
|
|
788
765
|
}
|
|
789
766
|
}
|
|
767
|
+
else {
|
|
768
|
+
break;
|
|
769
|
+
}
|
|
790
770
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
const ifaceStmt = (_b = pair[1]) === null || _b === void 0 ? void 0 : _b.item;
|
|
802
|
-
ifaceStmt === null || ifaceStmt === void 0 ? void 0 : ifaceStmt.buildSymbolTable(this.getParentInterface(ifaceStmt));
|
|
803
|
-
}
|
|
804
|
-
//also link enums
|
|
805
|
-
const enumMap = this.getEnumMap();
|
|
806
|
-
for (const pair of enumMap) {
|
|
807
|
-
const enumStmt = (_c = pair[1]) === null || _c === void 0 ? void 0 : _c.item;
|
|
808
|
-
enumStmt === null || enumStmt === void 0 ? void 0 : enumStmt.buildSymbolTable();
|
|
771
|
+
else {
|
|
772
|
+
// Existing known namespace
|
|
773
|
+
}
|
|
774
|
+
if (!namespaceTypesKnown.has(nsName)) {
|
|
775
|
+
namespaceTypesKnown.set(nsName, currentNSType);
|
|
776
|
+
}
|
|
777
|
+
for (let nsStmt of nsContainer.namespaceStatements) {
|
|
778
|
+
this.linkSymbolTableDisposables.push(nsStmt === null || nsStmt === void 0 ? void 0 : nsStmt.getSymbolTable().addSibling(nsContainer.symbolTable));
|
|
779
|
+
}
|
|
780
|
+
this.linkSymbolTableDisposables.push(currentNSType.memberTable.addSibling(nsContainer.symbolTable));
|
|
809
781
|
}
|
|
810
782
|
}
|
|
811
783
|
unlinkSymbolTable() {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
}
|
|
819
|
-
}
|
|
784
|
+
for (const symbolToRemove of this.symbolsAddedDuringLinking) {
|
|
785
|
+
this.symbolTable.removeSymbol(symbolToRemove.name);
|
|
786
|
+
}
|
|
787
|
+
this.symbolsAddedDuringLinking = [];
|
|
788
|
+
for (const dispose of this.linkSymbolTableDisposables) {
|
|
789
|
+
dispose();
|
|
820
790
|
}
|
|
791
|
+
this.linkSymbolTableDisposables = [];
|
|
821
792
|
}
|
|
822
793
|
detectVariableNamespaceCollisions(file) {
|
|
794
|
+
var _a, _b;
|
|
823
795
|
//find all function parameters
|
|
824
|
-
for (let func of file.
|
|
796
|
+
for (let func of file['_cachedLookups'].functionExpressions) {
|
|
825
797
|
for (let param of func.parameters) {
|
|
826
|
-
let lowerParamName = param.name.text.toLowerCase();
|
|
827
|
-
let namespace = this.
|
|
798
|
+
let lowerParamName = param.tokens.name.text.toLowerCase();
|
|
799
|
+
let namespace = this.getNamespace(lowerParamName, (_a = param.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
|
|
828
800
|
//see if the param matches any starting namespace part
|
|
829
801
|
if (namespace) {
|
|
830
|
-
this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.parameterMayNotHaveSameNameAsNamespace(param.name.text)), { range: param.name.range, relatedInformation: [{
|
|
802
|
+
this.diagnostics.push(Object.assign(Object.assign({ origin: interfaces_1.DiagnosticOrigin.Scope, file: file }, DiagnosticMessages_1.DiagnosticMessages.parameterMayNotHaveSameNameAsNamespace(param.tokens.name.text)), { range: param.tokens.name.range, relatedInformation: [{
|
|
831
803
|
message: 'Namespace declared here',
|
|
832
804
|
location: util_1.util.createLocation(vscode_uri_1.URI.file(namespace.file.srcPath).toString(), namespace.nameRange)
|
|
833
805
|
}] }));
|
|
834
806
|
}
|
|
835
807
|
}
|
|
836
808
|
}
|
|
837
|
-
for (let assignment of file.
|
|
838
|
-
let lowerAssignmentName = assignment.name.text.toLowerCase();
|
|
839
|
-
let namespace = this.
|
|
809
|
+
for (let assignment of file['_cachedLookups'].assignmentStatements) {
|
|
810
|
+
let lowerAssignmentName = assignment.tokens.name.text.toLowerCase();
|
|
811
|
+
let namespace = this.getNamespace(lowerAssignmentName, (_b = assignment.findAncestor(reflection_1.isNamespaceStatement)) === null || _b === void 0 ? void 0 : _b.getName(Parser_1.ParseMode.BrighterScript).toLowerCase());
|
|
840
812
|
//see if the param matches any starting namespace part
|
|
841
813
|
if (namespace) {
|
|
842
|
-
this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.variableMayNotHaveSameNameAsNamespace(assignment.name.text)), { range: assignment.name.range, relatedInformation: [{
|
|
814
|
+
this.diagnostics.push(Object.assign(Object.assign({ origin: interfaces_1.DiagnosticOrigin.Scope, file: file }, DiagnosticMessages_1.DiagnosticMessages.variableMayNotHaveSameNameAsNamespace(assignment.tokens.name.text)), { range: assignment.tokens.name.range, relatedInformation: [{
|
|
843
815
|
message: 'Namespace declared here',
|
|
844
816
|
location: util_1.util.createLocation(vscode_uri_1.URI.file(namespace.file.srcPath).toString(), namespace.nameRange)
|
|
845
817
|
}] }));
|
|
@@ -856,50 +828,84 @@ class Scope {
|
|
|
856
828
|
if (lowerFuncName) {
|
|
857
829
|
//find function declarations with the same name as a stdlib function
|
|
858
830
|
if (globalCallables_1.globalCallableMap.has(lowerFuncName)) {
|
|
859
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scopeFunctionShadowedByBuiltInFunction()), { range: func.nameRange, file: file }));
|
|
831
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scopeFunctionShadowedByBuiltInFunction()), { range: func.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
860
832
|
}
|
|
861
833
|
//find any functions that have the same name as a class
|
|
862
|
-
|
|
863
|
-
|
|
834
|
+
const klassLink = this.getClassFileLink(lowerFuncName);
|
|
835
|
+
if (klassLink) {
|
|
836
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionCannotHaveSameNameAsClass(funcName)), { range: func.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope, relatedInformation: [{
|
|
837
|
+
location: util_1.util.createLocation(vscode_uri_1.URI.file(klassLink.file.srcPath).toString(), klassLink.item.tokens.name.range),
|
|
838
|
+
message: 'Original class declared here'
|
|
839
|
+
}] }));
|
|
864
840
|
}
|
|
865
841
|
}
|
|
866
842
|
}
|
|
867
843
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
844
|
+
detectNameCollisions(file) {
|
|
845
|
+
file.ast.walk((0, visitors_1.createVisitor)({
|
|
846
|
+
NamespaceStatement: (nsStmt) => {
|
|
847
|
+
var _a;
|
|
848
|
+
this.validateNameCollision(file, nsStmt, (_a = nsStmt.getNameParts()) === null || _a === void 0 ? void 0 : _a[0]);
|
|
849
|
+
},
|
|
850
|
+
ClassStatement: (classStmt) => {
|
|
851
|
+
this.validateNameCollision(file, classStmt, classStmt.tokens.name);
|
|
852
|
+
},
|
|
853
|
+
InterfaceStatement: (ifaceStmt) => {
|
|
854
|
+
this.validateNameCollision(file, ifaceStmt, ifaceStmt.tokens.name);
|
|
855
|
+
},
|
|
856
|
+
ConstStatement: (constStmt) => {
|
|
857
|
+
this.validateNameCollision(file, constStmt, constStmt.tokens.name);
|
|
858
|
+
},
|
|
859
|
+
EnumStatement: (enumStmt) => {
|
|
860
|
+
this.validateNameCollision(file, enumStmt, enumStmt.tokens.name);
|
|
882
861
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
862
|
+
}), {
|
|
863
|
+
walkMode: visitors_1.WalkMode.visitStatements
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
validateNameCollision(file, node, nameIdentifier) {
|
|
867
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
868
|
+
const name = nameIdentifier === null || nameIdentifier === void 0 ? void 0 : nameIdentifier.text;
|
|
869
|
+
if (!name || !node) {
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
const nameRange = nameIdentifier.range;
|
|
873
|
+
const containingNamespace = (_a = node.findAncestor(reflection_1.isNamespaceStatement)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript);
|
|
874
|
+
const links = this.getAllFileLinks(name, containingNamespace);
|
|
875
|
+
for (let link of links) {
|
|
876
|
+
if (!link || link.item === node) {
|
|
877
|
+
// refers to same node
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
if ((0, reflection_1.isNamespaceStatement)(link.item) && (0, reflection_1.isNamespaceStatement)(node)) {
|
|
881
|
+
// namespace can be declared multiple times
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
const thisNodeKindName = util_1.util.getAstNodeFriendlyName(node);
|
|
885
|
+
const thatNodeKindName = link.file.srcPath === 'global' ? 'Global Function' : (_b = util_1.util.getAstNodeFriendlyName(link.item)) !== null && _b !== void 0 ? _b : '';
|
|
886
|
+
let thatNameRange = (_f = (_e = (_d = (_c = link.item) === null || _c === void 0 ? void 0 : _c.tokens) === null || _d === void 0 ? void 0 : _d.name) === null || _e === void 0 ? void 0 : _e.range) !== null && _f !== void 0 ? _f : (_g = link.item) === null || _g === void 0 ? void 0 : _g.range;
|
|
887
|
+
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
|
|
888
|
+
switch ((_h = link.item) === null || _h === void 0 ? void 0 : _h.kind) {
|
|
889
|
+
case AstNode_1.AstNodeKind.ClassStatement: {
|
|
890
|
+
thatNameRange = (_j = link.item.tokens.name) === null || _j === void 0 ? void 0 : _j.range;
|
|
891
|
+
break;
|
|
888
892
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
if (!this.hasClass(paramTypeName, currentNamespaceName) && !this.hasInterface(paramTypeName) && !this.hasEnum(paramTypeName)) {
|
|
893
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(param.name.text, paramTypeName)), { range: param.type.range, file: file }));
|
|
894
|
-
}
|
|
893
|
+
case AstNode_1.AstNodeKind.NamespaceStatement: {
|
|
894
|
+
thatNameRange = (_l = (_k = link.item.getNameParts()) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l.range;
|
|
895
|
+
break;
|
|
895
896
|
}
|
|
896
897
|
}
|
|
898
|
+
const relatedInformation = thatNameRange ? [{
|
|
899
|
+
message: `${thatNodeKindName} declared here`,
|
|
900
|
+
location: util_1.util.createLocation(vscode_uri_1.URI.file((_m = link.file) === null || _m === void 0 ? void 0 : _m.srcPath).toString(), thatNameRange)
|
|
901
|
+
}] : undefined;
|
|
902
|
+
this.diagnostics.push(Object.assign(Object.assign({ file: file }, DiagnosticMessages_1.DiagnosticMessages.nameCollision(thisNodeKindName, thatNodeKindName, name)), { origin: interfaces_1.DiagnosticOrigin.Scope, range: nameRange, relatedInformation: relatedInformation }));
|
|
897
903
|
}
|
|
898
904
|
}
|
|
899
905
|
getNewExpressions() {
|
|
900
906
|
let result = [];
|
|
901
907
|
this.enumerateBrsFiles((file) => {
|
|
902
|
-
let expressions = file.
|
|
908
|
+
let expressions = file['_cachedLookups'].newExpressions;
|
|
903
909
|
for (let expression of expressions) {
|
|
904
910
|
expression.file = file;
|
|
905
911
|
result.push(expression);
|
|
@@ -907,57 +913,54 @@ class Scope {
|
|
|
907
913
|
});
|
|
908
914
|
return result;
|
|
909
915
|
}
|
|
910
|
-
validateClasses(
|
|
911
|
-
let validator = new ClassValidator_1.BsClassValidator();
|
|
912
|
-
validator.validate(
|
|
913
|
-
this.diagnostics.push(...validator.diagnostics
|
|
916
|
+
validateClasses() {
|
|
917
|
+
let validator = new ClassValidator_1.BsClassValidator(this);
|
|
918
|
+
validator.validate();
|
|
919
|
+
this.diagnostics.push(...validator.diagnostics.map(diag => {
|
|
920
|
+
return Object.assign(Object.assign({}, diag), { origin: interfaces_1.DiagnosticOrigin.Scope });
|
|
921
|
+
}));
|
|
914
922
|
}
|
|
915
923
|
/**
|
|
916
|
-
* Detect local variables (
|
|
917
|
-
* @param file
|
|
918
|
-
* @param callableContainerMap
|
|
924
|
+
* Detect local variables (function scope) that have the same name as scope calls
|
|
919
925
|
*/
|
|
920
926
|
diagnosticDetectShadowedLocalVars(file, callableContainerMap) {
|
|
927
|
+
var _a;
|
|
921
928
|
const classMap = this.getClassMap();
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
929
|
+
//loop through every function scope
|
|
930
|
+
for (let funcScope of file.functionScopes) {
|
|
931
|
+
//every var declaration in this function scope
|
|
932
|
+
for (let varDeclaration of funcScope.variableDeclarations) {
|
|
933
|
+
const varName = varDeclaration.name;
|
|
934
|
+
const lowerVarName = varName.toLowerCase();
|
|
935
|
+
const varIsFunction = () => {
|
|
936
|
+
return (0, reflection_1.isCallableType)(varDeclaration.getType());
|
|
937
|
+
};
|
|
938
|
+
if (
|
|
939
|
+
//has same name as stdlib
|
|
940
|
+
globalCallables_1.globalCallableMap.has(lowerVarName)) {
|
|
928
941
|
//local var function with same name as stdlib function
|
|
929
|
-
if (
|
|
930
|
-
|
|
931
|
-
globalCallables_1.globalCallableMap.has(symbolNameLower)) {
|
|
932
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('stdlib')), { range: symbol.range, file: file }));
|
|
933
|
-
//this check needs to come after the stdlib one, because the stdlib functions are included
|
|
934
|
-
//in the scope function list
|
|
935
|
-
}
|
|
936
|
-
else if (
|
|
937
|
-
//has same name as scope function
|
|
938
|
-
callableContainerMap.has(symbolNameLower)) {
|
|
939
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('scope')), { range: symbol.range, file: file }));
|
|
942
|
+
if (varIsFunction()) {
|
|
943
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('stdlib')), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
940
944
|
}
|
|
941
|
-
//var is not a function
|
|
942
945
|
}
|
|
943
|
-
else if (
|
|
944
|
-
//is NOT a callable from stdlib (because non-function local vars can have same name as stdlib names)
|
|
945
|
-
!globalCallables_1.globalCallableMap.has(symbolNameLower)) {
|
|
946
|
+
else if (callableContainerMap.has(lowerVarName)) {
|
|
946
947
|
//is same name as a callable
|
|
947
|
-
if (
|
|
948
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.
|
|
949
|
-
//has the same name as an in-scope class
|
|
948
|
+
if (varIsFunction()) {
|
|
949
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarFunctionShadowsParentFunction('scope')), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
950
950
|
}
|
|
951
|
-
else
|
|
952
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.
|
|
951
|
+
else {
|
|
952
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarShadowedByScopedFunction()), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
953
953
|
}
|
|
954
|
+
//has the same name as an in-scope class
|
|
955
|
+
}
|
|
956
|
+
else if (classMap.has(lowerVarName)) {
|
|
957
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.localVarSameNameAsClass((_a = classMap.get(lowerVarName)) === null || _a === void 0 ? void 0 : _a.item.getName(Parser_1.ParseMode.BrighterScript))), { range: varDeclaration.nameRange, file: file, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
954
958
|
}
|
|
955
959
|
}
|
|
956
960
|
}
|
|
957
961
|
}
|
|
958
962
|
/**
|
|
959
963
|
* Create diagnostics for any duplicate function declarations
|
|
960
|
-
* @param callablesByLowerName
|
|
961
964
|
*/
|
|
962
965
|
diagnosticFindDuplicateFunctionDeclarations(callableContainersByLowerName) {
|
|
963
966
|
//for each list of callables with the same name
|
|
@@ -990,9 +993,9 @@ class Scope {
|
|
|
990
993
|
//same file: skip redundant imports
|
|
991
994
|
continue;
|
|
992
995
|
}
|
|
993
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.overridesAncestorFunction(container.callable.name, container.scope.name, shadowedCallable.callable.file.
|
|
996
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.overridesAncestorFunction(container.callable.name, container.scope.name, shadowedCallable.callable.file.destPath,
|
|
994
997
|
//grab the last item in the list, which should be the closest ancestor's version
|
|
995
|
-
shadowedCallable.scope.name)), { range: container.callable.nameRange, file: container.callable.file }));
|
|
998
|
+
shadowedCallable.scope.name)), { range: container.callable.nameRange, file: container.callable.file, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
996
999
|
}
|
|
997
1000
|
}
|
|
998
1001
|
}
|
|
@@ -1000,7 +1003,7 @@ class Scope {
|
|
|
1000
1003
|
if (ownCallables.length > 1) {
|
|
1001
1004
|
for (let callableContainer of ownCallables) {
|
|
1002
1005
|
let callable = callableContainer.callable;
|
|
1003
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateFunctionImplementation(callable.name, callableContainer.scope.name)), { range: util_1.util.createRange(callable.nameRange.start.line, callable.nameRange.start.character, callable.nameRange.start.line, callable.nameRange.end.character), file: callable.file }));
|
|
1006
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.duplicateFunctionImplementation(callable.name, callableContainer.scope.name)), { range: util_1.util.createRange(callable.nameRange.start.line, callable.nameRange.start.character, callable.nameRange.start.line, callable.nameRange.end.character), file: callable.file, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
1004
1007
|
}
|
|
1005
1008
|
}
|
|
1006
1009
|
}
|
|
@@ -1027,11 +1030,11 @@ class Scope {
|
|
|
1027
1030
|
let scriptImports = this.getOwnScriptImports();
|
|
1028
1031
|
//verify every script import
|
|
1029
1032
|
for (let scriptImport of scriptImports) {
|
|
1030
|
-
let referencedFile = this.getFileByRelativePath(scriptImport.
|
|
1033
|
+
let referencedFile = this.getFileByRelativePath(scriptImport.destPath);
|
|
1031
1034
|
//if we can't find the file
|
|
1032
1035
|
if (!referencedFile) {
|
|
1033
1036
|
//skip the default bslib file, it will exist at transpile time but should not show up in the program during validation cycle
|
|
1034
|
-
if (scriptImport.
|
|
1037
|
+
if (scriptImport.destPath === this.program.bslibPkgPath) {
|
|
1035
1038
|
continue;
|
|
1036
1039
|
}
|
|
1037
1040
|
let dInfo;
|
|
@@ -1041,17 +1044,16 @@ class Scope {
|
|
|
1041
1044
|
else {
|
|
1042
1045
|
dInfo = DiagnosticMessages_1.DiagnosticMessages.referencedFileDoesNotExist();
|
|
1043
1046
|
}
|
|
1044
|
-
this.diagnostics.push(Object.assign(Object.assign({}, dInfo), { range: scriptImport.filePathRange, file: scriptImport.sourceFile }));
|
|
1047
|
+
this.diagnostics.push(Object.assign(Object.assign({}, dInfo), { range: scriptImport.filePathRange, file: scriptImport.sourceFile, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
1045
1048
|
//if the character casing of the script import path does not match that of the actual path
|
|
1046
1049
|
}
|
|
1047
|
-
else if (scriptImport.
|
|
1048
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scriptImportCaseMismatch(referencedFile.
|
|
1050
|
+
else if (scriptImport.destPath !== referencedFile.destPath) {
|
|
1051
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.scriptImportCaseMismatch(referencedFile.destPath)), { range: scriptImport.filePathRange, file: scriptImport.sourceFile, origin: interfaces_1.DiagnosticOrigin.Scope }));
|
|
1049
1052
|
}
|
|
1050
1053
|
}
|
|
1051
1054
|
}
|
|
1052
1055
|
/**
|
|
1053
1056
|
* Find the file with the specified relative path
|
|
1054
|
-
* @param relativePath
|
|
1055
1057
|
*/
|
|
1056
1058
|
getFileByRelativePath(relativePath) {
|
|
1057
1059
|
if (!relativePath) {
|
|
@@ -1059,91 +1061,23 @@ class Scope {
|
|
|
1059
1061
|
}
|
|
1060
1062
|
let files = this.getAllFiles();
|
|
1061
1063
|
for (let file of files) {
|
|
1062
|
-
if (file.
|
|
1064
|
+
if (file.destPath.toLowerCase() === relativePath.toLowerCase()) {
|
|
1063
1065
|
return file;
|
|
1064
1066
|
}
|
|
1065
1067
|
}
|
|
1066
1068
|
}
|
|
1067
1069
|
/**
|
|
1068
1070
|
* Determine if this file is included in this scope (excluding parent scopes)
|
|
1069
|
-
* @param file
|
|
1070
1071
|
*/
|
|
1071
1072
|
hasFile(file) {
|
|
1072
1073
|
let files = this.getOwnFiles();
|
|
1073
1074
|
let hasFile = files.includes(file);
|
|
1074
1075
|
return hasFile;
|
|
1075
1076
|
}
|
|
1076
|
-
/**
|
|
1077
|
-
* Get all callables as completionItems
|
|
1078
|
-
*/
|
|
1079
|
-
getCallablesAsCompletions(parseMode) {
|
|
1080
|
-
let completions = [];
|
|
1081
|
-
let callables = this.getAllCallables();
|
|
1082
|
-
if (parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
1083
|
-
//throw out the namespaced callables (they will be handled by another method)
|
|
1084
|
-
callables = callables.filter(x => x.callable.hasNamespace === false);
|
|
1085
|
-
}
|
|
1086
|
-
for (let callableContainer of callables) {
|
|
1087
|
-
completions.push(this.createCompletionFromCallable(callableContainer));
|
|
1088
|
-
}
|
|
1089
|
-
return completions;
|
|
1090
|
-
}
|
|
1091
|
-
createCompletionFromCallable(callableContainer) {
|
|
1092
|
-
return {
|
|
1093
|
-
label: callableContainer.callable.getName(Parser_1.ParseMode.BrighterScript),
|
|
1094
|
-
kind: vscode_languageserver_1.CompletionItemKind.Function,
|
|
1095
|
-
detail: callableContainer.callable.shortDescription,
|
|
1096
|
-
documentation: callableContainer.callable.documentation ? { kind: 'markdown', value: callableContainer.callable.documentation } : undefined
|
|
1097
|
-
};
|
|
1098
|
-
}
|
|
1099
|
-
createCompletionFromFunctionStatement(statement) {
|
|
1100
|
-
return {
|
|
1101
|
-
label: statement.getName(Parser_1.ParseMode.BrighterScript),
|
|
1102
|
-
kind: vscode_languageserver_1.CompletionItemKind.Function
|
|
1103
|
-
};
|
|
1104
|
-
}
|
|
1105
|
-
/**
|
|
1106
|
-
* Get the definition (where was this thing first defined) of the symbol under the position
|
|
1107
|
-
*/
|
|
1108
|
-
getDefinition(file, position) {
|
|
1109
|
-
// Overridden in XMLScope. Brs files use implementation in BrsFile
|
|
1110
|
-
return [];
|
|
1111
|
-
}
|
|
1112
|
-
/**
|
|
1113
|
-
* Scan all files for property names, and return them as completions
|
|
1114
|
-
*/
|
|
1115
|
-
getPropertyNameCompletions() {
|
|
1116
|
-
let results = [];
|
|
1117
|
-
this.enumerateBrsFiles((file) => {
|
|
1118
|
-
results.push(...file.propertyNameCompletions);
|
|
1119
|
-
});
|
|
1120
|
-
return results;
|
|
1121
|
-
}
|
|
1122
|
-
getAllClassMemberCompletions() {
|
|
1123
|
-
let results = new Map();
|
|
1124
|
-
let filesSearched = new Set();
|
|
1125
|
-
for (const file of this.getAllFiles()) {
|
|
1126
|
-
if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
|
|
1127
|
-
continue;
|
|
1128
|
-
}
|
|
1129
|
-
filesSearched.add(file);
|
|
1130
|
-
for (let cs of file.parser.references.classStatements) {
|
|
1131
|
-
for (let s of [...cs.methods, ...cs.fields]) {
|
|
1132
|
-
if (!results.has(s.name.text) && s.name.text.toLowerCase() !== 'new') {
|
|
1133
|
-
results.set(s.name.text, {
|
|
1134
|
-
label: s.name.text,
|
|
1135
|
-
kind: (0, reflection_1.isMethodStatement)(s) ? vscode_languageserver_1.CompletionItemKind.Method : vscode_languageserver_1.CompletionItemKind.Field
|
|
1136
|
-
});
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
return results;
|
|
1142
|
-
}
|
|
1143
1077
|
/**
|
|
1144
1078
|
* @param className - The name of the class (including namespace if possible)
|
|
1145
1079
|
* @param callsiteNamespace - the name of the namespace where the call site resides (this is NOT the known namespace of the class).
|
|
1146
|
-
* This is used to help resolve non-namespaced class names that reside in the same
|
|
1080
|
+
* This is used to help resolve non-namespaced class names that reside in the same namespac as the call site.
|
|
1147
1081
|
*/
|
|
1148
1082
|
getClassHierarchy(className, callsiteNamespace) {
|
|
1149
1083
|
var _a, _b;
|
|
@@ -1151,7 +1085,7 @@ class Scope {
|
|
|
1151
1085
|
let link = this.getClassFileLink(className, callsiteNamespace);
|
|
1152
1086
|
while (link) {
|
|
1153
1087
|
items.push(link);
|
|
1154
|
-
link = this.getClassFileLink((_b = (_a = link.item.parentClassName) === null || _a === void 0 ? void 0 : _a.getName(
|
|
1088
|
+
link = this.getClassFileLink((_b = (_a = link.item.parentClassName) === null || _a === void 0 ? void 0 : _a.getName()) === null || _b === void 0 ? void 0 : _b.toLowerCase(), callsiteNamespace);
|
|
1155
1089
|
}
|
|
1156
1090
|
return items;
|
|
1157
1091
|
}
|