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/files/BrsFile.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.BrsFile = void 0;
|
|
4
4
|
const source_map_1 = require("source-map");
|
|
5
5
|
const vscode_languageserver_1 = require("vscode-languageserver");
|
|
6
6
|
const vscode_languageserver_2 = require("vscode-languageserver");
|
|
7
7
|
const chalk_1 = require("chalk");
|
|
8
8
|
const path = require("path");
|
|
9
9
|
const DiagnosticMessages_1 = require("../DiagnosticMessages");
|
|
10
|
-
const
|
|
10
|
+
const FunctionScope_1 = require("../FunctionScope");
|
|
11
11
|
const Lexer_1 = require("../lexer/Lexer");
|
|
12
12
|
const TokenKind_1 = require("../lexer/TokenKind");
|
|
13
13
|
const Parser_1 = require("../parser/Parser");
|
|
@@ -18,29 +18,19 @@ const Preprocessor_1 = require("../preprocessor/Preprocessor");
|
|
|
18
18
|
const Logger_1 = require("../Logger");
|
|
19
19
|
const serialize_error_1 = require("serialize-error");
|
|
20
20
|
const reflection_1 = require("../astUtils/reflection");
|
|
21
|
-
const BscType_1 = require("../types/BscType");
|
|
22
21
|
const visitors_1 = require("../astUtils/visitors");
|
|
23
22
|
const CommentFlagProcessor_1 = require("../CommentFlagProcessor");
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
const
|
|
23
|
+
const AstValidationSegmenter_1 = require("../AstValidationSegmenter");
|
|
24
|
+
const SymbolTable_1 = require("../SymbolTable");
|
|
25
|
+
const CachedLookups_1 = require("../astUtils/CachedLookups");
|
|
26
|
+
const Editor_1 = require("../astUtils/Editor");
|
|
27
27
|
/**
|
|
28
28
|
* Holds all details about this file within the scope of the whole program
|
|
29
29
|
*/
|
|
30
30
|
class BrsFile {
|
|
31
|
-
constructor(
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*/
|
|
35
|
-
srcPath,
|
|
36
|
-
/**
|
|
37
|
-
* The full pkg path (i.e. `pkg:/path/to/file.brs`)
|
|
38
|
-
*/
|
|
39
|
-
pkgPath, program) {
|
|
40
|
-
var _a, _b;
|
|
41
|
-
this.srcPath = srcPath;
|
|
42
|
-
this.pkgPath = pkgPath;
|
|
43
|
-
this.program = program;
|
|
31
|
+
constructor(options) {
|
|
32
|
+
var _a, _b, _c;
|
|
33
|
+
this.type = 'BrsFile';
|
|
44
34
|
/**
|
|
45
35
|
* The parseMode used for the parser for this file
|
|
46
36
|
*/
|
|
@@ -50,43 +40,67 @@ class BrsFile {
|
|
|
50
40
|
* Files are only ever validated a single time
|
|
51
41
|
*/
|
|
52
42
|
this.isValidated = false;
|
|
53
|
-
this.diagnostics = [];
|
|
54
|
-
this.commentFlags = [];
|
|
55
|
-
this.callables = [];
|
|
56
|
-
this.functionCalls = [];
|
|
57
43
|
/**
|
|
58
|
-
*
|
|
44
|
+
* A collection of diagnostics related to this file
|
|
59
45
|
*/
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
this.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
46
|
+
this.diagnostics = [];
|
|
47
|
+
this.commentFlags = [];
|
|
48
|
+
this.scopesByFunc = new Map();
|
|
49
|
+
this.validationSegmenter = new AstValidationSegmenter_1.AstValidationSegmenter();
|
|
50
|
+
if (options) {
|
|
51
|
+
this.srcPath = (0, util_1.standardizePath) `${options.srcPath}`;
|
|
52
|
+
this.destPath = (0, util_1.standardizePath) `${options.destPath}`;
|
|
53
|
+
this.program = options.program;
|
|
54
|
+
this._cachedLookups = new CachedLookups_1.CachedLookups(this);
|
|
55
|
+
this.extension = util_1.util.getExtension(this.srcPath);
|
|
56
|
+
if (options.pkgPath) {
|
|
57
|
+
this.pkgPath = options.pkgPath;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
//don't rename .d.bs files to .d.brs
|
|
61
|
+
if (this.extension === '.d.bs') {
|
|
62
|
+
this.pkgPath = this.destPath;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
this.pkgPath = this.destPath.replace(/\.bs$/i, '.brs');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//all BrighterScript files need to be transpiled
|
|
69
|
+
if (((_a = this.extension) === null || _a === void 0 ? void 0 : _a.endsWith('.bs')) || ((_c = (_b = this.program) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c.allowBrighterScriptInBrightScript)) {
|
|
70
|
+
this.parseMode = Parser_1.ParseMode.BrighterScript;
|
|
71
|
+
}
|
|
72
|
+
this.isTypedef = this.extension === '.d.bs';
|
|
73
|
+
if (!this.isTypedef) {
|
|
74
|
+
this.typedefKey = util_1.util.getTypedefPath(this.srcPath);
|
|
75
|
+
}
|
|
76
|
+
//global file doesn't have a program, so only resolve typedef info if we have a program
|
|
77
|
+
if (this.program) {
|
|
78
|
+
this.resolveTypedef();
|
|
79
|
+
}
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
/**
|
|
79
|
-
*
|
|
80
|
-
* @deprecated use `srcPath` instead
|
|
83
|
+
* Will this file result in only comment or whitespace output? If so, it can be excluded from the output if that bsconfig setting is enabled.
|
|
81
84
|
*/
|
|
82
|
-
get
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
get canBePruned() {
|
|
86
|
+
let canPrune = true;
|
|
87
|
+
this.ast.walk((0, visitors_1.createVisitor)({
|
|
88
|
+
FunctionStatement: () => {
|
|
89
|
+
canPrune = false;
|
|
90
|
+
},
|
|
91
|
+
ClassStatement: () => {
|
|
92
|
+
canPrune = false;
|
|
93
|
+
}
|
|
94
|
+
}), {
|
|
95
|
+
walkMode: visitors_1.WalkMode.visitStatements
|
|
96
|
+
});
|
|
97
|
+
return canPrune;
|
|
87
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* @deprecated use `.diagnostics` instead
|
|
101
|
+
*/
|
|
88
102
|
getDiagnostics() {
|
|
89
|
-
return
|
|
103
|
+
return this.diagnostics;
|
|
90
104
|
}
|
|
91
105
|
addDiagnostic(diagnostic) {
|
|
92
106
|
if (!diagnostic.file) {
|
|
@@ -97,10 +111,15 @@ class BrsFile {
|
|
|
97
111
|
addDiagnostics(diagnostics) {
|
|
98
112
|
this.diagnostics.push(...diagnostics);
|
|
99
113
|
}
|
|
114
|
+
get functionScopes() {
|
|
115
|
+
if (!this._functionScopes) {
|
|
116
|
+
this.createFunctionScopes();
|
|
117
|
+
}
|
|
118
|
+
return this._functionScopes;
|
|
119
|
+
}
|
|
100
120
|
get cache() {
|
|
101
|
-
var _a;
|
|
102
121
|
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
103
|
-
return
|
|
122
|
+
return this._cachedLookups['cache'];
|
|
104
123
|
}
|
|
105
124
|
/**
|
|
106
125
|
* files referenced by import statements
|
|
@@ -108,16 +127,16 @@ class BrsFile {
|
|
|
108
127
|
get ownScriptImports() {
|
|
109
128
|
var _a, _b;
|
|
110
129
|
const result = (_b = (_a = this.cache) === null || _a === void 0 ? void 0 : _a.getOrAdd('BrsFile_ownScriptImports', () => {
|
|
111
|
-
var _a, _b
|
|
130
|
+
var _a, _b;
|
|
112
131
|
const result = [];
|
|
113
|
-
for (const statement of (
|
|
132
|
+
for (const statement of (_b = (_a = this._cachedLookups) === null || _a === void 0 ? void 0 : _a.importStatements) !== null && _b !== void 0 ? _b : []) {
|
|
114
133
|
//register import statements
|
|
115
|
-
if ((0, reflection_1.isImportStatement)(statement) && statement.
|
|
134
|
+
if ((0, reflection_1.isImportStatement)(statement) && statement.tokens.filePath) {
|
|
116
135
|
result.push({
|
|
117
|
-
filePathRange: statement.
|
|
118
|
-
|
|
136
|
+
filePathRange: statement.tokens.filePath.range,
|
|
137
|
+
destPath: util_1.util.getPkgPathFromTarget(this.destPath, statement.filePath),
|
|
119
138
|
sourceFile: this,
|
|
120
|
-
text:
|
|
139
|
+
text: statement.tokens.filePath.text
|
|
121
140
|
});
|
|
122
141
|
}
|
|
123
142
|
}
|
|
@@ -125,15 +144,29 @@ class BrsFile {
|
|
|
125
144
|
})) !== null && _b !== void 0 ? _b : [];
|
|
126
145
|
return result;
|
|
127
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Does this file need to be transpiled?
|
|
149
|
+
* @deprecated use the `.editor` property to push changes to the file, which will force transpilation
|
|
150
|
+
*/
|
|
151
|
+
get needsTranspiled() {
|
|
152
|
+
var _a, _b, _c, _d;
|
|
153
|
+
if (this._needsTranspiled !== undefined) {
|
|
154
|
+
return this._needsTranspiled;
|
|
155
|
+
}
|
|
156
|
+
return !!(((_a = this.extension) === null || _a === void 0 ? void 0 : _a.endsWith('.bs')) || ((_c = (_b = this.program) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c.allowBrighterScriptInBrightScript) || ((_d = this.editor) === null || _d === void 0 ? void 0 : _d.hasChanges));
|
|
157
|
+
}
|
|
158
|
+
set needsTranspiled(value) {
|
|
159
|
+
this._needsTranspiled = value;
|
|
160
|
+
}
|
|
128
161
|
/**
|
|
129
162
|
* The AST for this file
|
|
130
163
|
*/
|
|
131
164
|
get ast() {
|
|
132
|
-
|
|
165
|
+
var _a;
|
|
166
|
+
return (_a = this.parser) === null || _a === void 0 ? void 0 : _a.ast;
|
|
133
167
|
}
|
|
134
168
|
/**
|
|
135
169
|
* Get the token at the specified position
|
|
136
|
-
* @param position
|
|
137
170
|
*/
|
|
138
171
|
getTokenAt(position) {
|
|
139
172
|
for (let token of this.parser.tokens) {
|
|
@@ -181,38 +214,32 @@ class BrsFile {
|
|
|
181
214
|
* Find and set the typedef variables (if a matching typedef file exists)
|
|
182
215
|
*/
|
|
183
216
|
resolveTypedef() {
|
|
184
|
-
this.typedefFile = this.program.getFile(this.
|
|
217
|
+
this.typedefFile = this.program.getFile(this.typedefKey);
|
|
185
218
|
this.hasTypedef = !!this.typedefFile;
|
|
186
219
|
}
|
|
220
|
+
onDependenciesChanged() {
|
|
221
|
+
this.resolveTypedef();
|
|
222
|
+
}
|
|
187
223
|
/**
|
|
188
224
|
* Attach the file to the dependency graph so it can monitor changes.
|
|
189
225
|
* Also notify the dependency graph of our current dependencies so other dependents can be notified.
|
|
226
|
+
* @deprecated this does nothing. This functionality is now handled by the file api and will be deleted in v1
|
|
190
227
|
*/
|
|
191
|
-
attachDependencyGraph(dependencyGraph) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
});
|
|
198
|
-
const dependencies = this.ownScriptImports.filter(x => !!x.pkgPath).map(x => x.pkgPath.toLowerCase());
|
|
228
|
+
attachDependencyGraph(dependencyGraph) { }
|
|
229
|
+
/**
|
|
230
|
+
* The list of files that this file depends on
|
|
231
|
+
*/
|
|
232
|
+
get dependencies() {
|
|
233
|
+
const result = this.ownScriptImports.filter(x => !!x.destPath).map(x => x.destPath.toLowerCase());
|
|
199
234
|
//if this is a .brs file, watch for typedef changes
|
|
200
235
|
if (this.extension === '.brs') {
|
|
201
|
-
|
|
236
|
+
result.push(util_1.util.getTypedefPath(this.destPath));
|
|
202
237
|
}
|
|
203
|
-
|
|
204
|
-
}
|
|
205
|
-
get logger() {
|
|
206
|
-
var _a;
|
|
207
|
-
const logger = (_a = this.program) === null || _a === void 0 ? void 0 : _a.logger;
|
|
208
|
-
if (!logger && !this._logger) {
|
|
209
|
-
this._logger = new Logger_1.Logger();
|
|
210
|
-
}
|
|
211
|
-
return logger !== null && logger !== void 0 ? logger : this._logger;
|
|
238
|
+
return result;
|
|
212
239
|
}
|
|
213
240
|
/**
|
|
214
241
|
* Calculate the AST for this file
|
|
215
|
-
* @param fileContents
|
|
242
|
+
* @param fileContents the raw source code to parse
|
|
216
243
|
*/
|
|
217
244
|
parse(fileContents) {
|
|
218
245
|
try {
|
|
@@ -225,7 +252,7 @@ class BrsFile {
|
|
|
225
252
|
return;
|
|
226
253
|
}
|
|
227
254
|
//tokenize the input file
|
|
228
|
-
let lexer = this.logger.time(Logger_1.LogLevel.debug, ['lexer.lex', chalk_1.default.green(this.srcPath)], () => {
|
|
255
|
+
let lexer = this.program.logger.time(Logger_1.LogLevel.debug, ['lexer.lex', chalk_1.default.green(this.srcPath)], () => {
|
|
229
256
|
return Lexer_1.Lexer.scan(fileContents, {
|
|
230
257
|
includeWhitespace: false
|
|
231
258
|
});
|
|
@@ -236,7 +263,7 @@ class BrsFile {
|
|
|
236
263
|
//TODO preprocessor should go away in favor of the AST handling this internally (because it affects transpile)
|
|
237
264
|
//currently the preprocessor throws exceptions on syntax errors...so we need to catch it
|
|
238
265
|
try {
|
|
239
|
-
this.logger.time(Logger_1.LogLevel.debug, ['preprocessor.process', chalk_1.default.green(this.srcPath)], () => {
|
|
266
|
+
this.program.logger.time(Logger_1.LogLevel.debug, ['preprocessor.process', chalk_1.default.green(this.srcPath)], () => {
|
|
240
267
|
preprocessor.process(lexer.tokens, this.program.getManifest());
|
|
241
268
|
});
|
|
242
269
|
}
|
|
@@ -248,18 +275,14 @@ class BrsFile {
|
|
|
248
275
|
}
|
|
249
276
|
//if the preprocessor generated tokens, use them.
|
|
250
277
|
let tokens = preprocessor.processedTokens.length > 0 ? preprocessor.processedTokens : lexer.tokens;
|
|
251
|
-
this.logger.time(Logger_1.LogLevel.debug, ['parser.parse', chalk_1.default.green(this.srcPath)], () => {
|
|
278
|
+
this.program.logger.time(Logger_1.LogLevel.debug, ['parser.parse', chalk_1.default.green(this.srcPath)], () => {
|
|
252
279
|
this._parser = Parser_1.Parser.parse(tokens, {
|
|
253
280
|
mode: this.parseMode,
|
|
254
|
-
logger: this.logger
|
|
281
|
+
logger: this.program.logger
|
|
255
282
|
});
|
|
256
283
|
});
|
|
257
284
|
//absorb all lexing/preprocessing/parsing diagnostics
|
|
258
285
|
this.diagnostics.push(...lexer.diagnostics, ...preprocessor.diagnostics, ...this._parser.diagnostics);
|
|
259
|
-
//extract all callables from this file
|
|
260
|
-
this.findCallables();
|
|
261
|
-
//find all places where a sub/function is being called
|
|
262
|
-
this.findFunctionCalls();
|
|
263
286
|
//attach this file to every diagnostic
|
|
264
287
|
for (let diagnostic of this.diagnostics) {
|
|
265
288
|
diagnostic.file = this;
|
|
@@ -270,46 +293,6 @@ class BrsFile {
|
|
|
270
293
|
this.diagnostics.push(Object.assign({ file: this, range: util_1.util.createRange(0, 0, 0, Number.MAX_VALUE) }, DiagnosticMessages_1.DiagnosticMessages.genericParserMessage('Critical error parsing file: ' + JSON.stringify((0, serialize_error_1.serializeError)(e)))));
|
|
271
294
|
}
|
|
272
295
|
}
|
|
273
|
-
validate() {
|
|
274
|
-
util_1.util.validateTooDeepFile(this);
|
|
275
|
-
//only validate the file if it was actually parsed (skip files containing typedefs)
|
|
276
|
-
if (!this.hasTypedef) {
|
|
277
|
-
this.validateImportStatements();
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
validateImportStatements() {
|
|
281
|
-
let topOfFileIncludeStatements = [];
|
|
282
|
-
for (let stmt of this.ast.statements) {
|
|
283
|
-
//skip comments
|
|
284
|
-
if ((0, reflection_1.isCommentStatement)(stmt)) {
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
//if we found a non-library statement, this statement is not at the top of the file
|
|
288
|
-
if ((0, reflection_1.isLibraryStatement)(stmt) || (0, reflection_1.isImportStatement)(stmt)) {
|
|
289
|
-
topOfFileIncludeStatements.push(stmt);
|
|
290
|
-
}
|
|
291
|
-
else {
|
|
292
|
-
//break out of the loop, we found all of our library statements
|
|
293
|
-
break;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
let statements = [
|
|
297
|
-
...this._parser.references.libraryStatements,
|
|
298
|
-
...this._parser.references.importStatements
|
|
299
|
-
];
|
|
300
|
-
for (let result of statements) {
|
|
301
|
-
//if this statement is not one of the top-of-file statements,
|
|
302
|
-
//then add a diagnostic explaining that it is invalid
|
|
303
|
-
if (!topOfFileIncludeStatements.includes(result)) {
|
|
304
|
-
if ((0, reflection_1.isLibraryStatement)(result)) {
|
|
305
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.libraryStatementMustBeDeclaredAtTopOfFile()), { range: result.range, file: this }));
|
|
306
|
-
}
|
|
307
|
-
else if ((0, reflection_1.isImportStatement)(result)) {
|
|
308
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.importStatementMustBeDeclaredAtTopOfFile()), { range: result.range, file: this }));
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
296
|
/**
|
|
314
297
|
* Find a class. This scans all scopes for this file, and returns the first matching class that is found.
|
|
315
298
|
* Returns undefined if not found.
|
|
@@ -331,7 +314,7 @@ class BrsFile {
|
|
|
331
314
|
}
|
|
332
315
|
findPropertyNameCompletions() {
|
|
333
316
|
//Build completion items from all the "properties" found in the file
|
|
334
|
-
const { propertyHints } = this.
|
|
317
|
+
const { propertyHints } = this._cachedLookups;
|
|
335
318
|
const results = [];
|
|
336
319
|
for (const key of Object.keys(propertyHints)) {
|
|
337
320
|
results.push({
|
|
@@ -349,7 +332,7 @@ class BrsFile {
|
|
|
349
332
|
}
|
|
350
333
|
/**
|
|
351
334
|
* Find all comment flags in the source code. These enable or disable diagnostic messages.
|
|
352
|
-
* @param
|
|
335
|
+
* @param tokens - an array of tokens of which to find `TokenKind.Comment` from
|
|
353
336
|
*/
|
|
354
337
|
getCommentFlags(tokens) {
|
|
355
338
|
const processor = new CommentFlagProcessor_1.CommentFlagProcessor(this, ['rem', `'`], DiagnosticMessages_1.diagnosticCodes, [DiagnosticMessages_1.DiagnosticCodeMap.unknownDiagnosticCode]);
|
|
@@ -362,130 +345,246 @@ class BrsFile {
|
|
|
362
345
|
this.commentFlags.push(...processor.commentFlags);
|
|
363
346
|
this.diagnostics.push(...processor.diagnostics);
|
|
364
347
|
}
|
|
365
|
-
|
|
348
|
+
/**
|
|
349
|
+
* Create a scope for every function in this file
|
|
350
|
+
*/
|
|
351
|
+
createFunctionScopes() {
|
|
366
352
|
var _a;
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
353
|
+
//find every function
|
|
354
|
+
let functions = this._cachedLookups.functionExpressions;
|
|
355
|
+
//create a functionScope for every function
|
|
356
|
+
this._functionScopes = [];
|
|
357
|
+
for (let func of functions) {
|
|
358
|
+
let scope = new FunctionScope_1.FunctionScope(func);
|
|
359
|
+
//find parent function, and add this scope to it if found
|
|
360
|
+
{
|
|
361
|
+
let parentScope = this.scopesByFunc.get(func.findAncestor(reflection_1.isFunctionExpression));
|
|
362
|
+
//add this child scope to its parent
|
|
363
|
+
if (parentScope) {
|
|
364
|
+
parentScope.childrenScopes.push(scope);
|
|
365
|
+
}
|
|
366
|
+
//store the parent scope for this scope
|
|
367
|
+
scope.parentScope = parentScope;
|
|
368
|
+
}
|
|
369
|
+
//add every parameter
|
|
370
|
+
for (let param of func.parameters) {
|
|
371
|
+
scope.variableDeclarations.push({
|
|
372
|
+
nameRange: param.tokens.name.range,
|
|
373
|
+
lineIndex: param.tokens.name.range.start.line,
|
|
374
|
+
name: param.tokens.name.text,
|
|
375
|
+
getType: () => {
|
|
376
|
+
return param.getType({ flags: SymbolTable_1.SymbolTypeFlag.typetime });
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
//add all of ForEachStatement loop varibales
|
|
381
|
+
(_a = func.body) === null || _a === void 0 ? void 0 : _a.walk((0, visitors_1.createVisitor)({
|
|
382
|
+
ForEachStatement: (stmt) => {
|
|
383
|
+
scope.variableDeclarations.push({
|
|
384
|
+
nameRange: stmt.tokens.item.range,
|
|
385
|
+
lineIndex: stmt.tokens.item.range.start.line,
|
|
386
|
+
name: stmt.tokens.item.text,
|
|
387
|
+
getType: () => DynamicType_1.DynamicType.instance //TODO: Infer types from array
|
|
388
|
+
});
|
|
389
|
+
},
|
|
390
|
+
LabelStatement: (stmt) => {
|
|
391
|
+
const { name: identifier } = stmt.tokens;
|
|
392
|
+
scope.labelStatements.push({
|
|
393
|
+
nameRange: identifier.range,
|
|
394
|
+
lineIndex: identifier.range.start.line,
|
|
395
|
+
name: identifier.text
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
}), {
|
|
399
|
+
walkMode: visitors_1.WalkMode.visitStatements
|
|
381
400
|
});
|
|
401
|
+
this.scopesByFunc.set(func, scope);
|
|
402
|
+
//find every statement in the scope
|
|
403
|
+
this._functionScopes.push(scope);
|
|
404
|
+
}
|
|
405
|
+
//find every variable assignment in the whole file
|
|
406
|
+
let assignmentStatements = this._cachedLookups.assignmentStatements;
|
|
407
|
+
for (let statement of assignmentStatements) {
|
|
408
|
+
//find this statement's function scope
|
|
409
|
+
let scope = this.scopesByFunc.get(statement.findAncestor(reflection_1.isFunctionExpression));
|
|
410
|
+
//skip variable declarations that are outside of any scope
|
|
411
|
+
if (scope) {
|
|
412
|
+
const variableName = statement.tokens.name;
|
|
413
|
+
scope.variableDeclarations.push({
|
|
414
|
+
nameRange: variableName.range,
|
|
415
|
+
lineIndex: variableName.range.start.line,
|
|
416
|
+
name: variableName.text,
|
|
417
|
+
getType: () => {
|
|
418
|
+
return statement.getType({ flags: SymbolTable_1.SymbolTypeFlag.runtime });
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
382
422
|
}
|
|
383
423
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
424
|
+
get callables() {
|
|
425
|
+
if (this.staticCallables) {
|
|
426
|
+
// globalFile can statically set the callables
|
|
427
|
+
return this.staticCallables;
|
|
428
|
+
}
|
|
429
|
+
return this.cache.getOrAdd(`BrsFile_callables`, () => {
|
|
430
|
+
var _a, _b, _c, _d, _e;
|
|
431
|
+
const callables = [];
|
|
432
|
+
for (let statement of (_a = this._cachedLookups.functionStatements) !== null && _a !== void 0 ? _a : []) {
|
|
433
|
+
//extract the parameters
|
|
434
|
+
let params = [];
|
|
435
|
+
for (let param of statement.func.parameters) {
|
|
436
|
+
const paramType = param.getType({ flags: SymbolTable_1.SymbolTypeFlag.typetime });
|
|
437
|
+
let callableParam = {
|
|
438
|
+
name: (_b = param.tokens.name) === null || _b === void 0 ? void 0 : _b.text,
|
|
439
|
+
type: paramType,
|
|
440
|
+
isOptional: !!param.defaultValue,
|
|
441
|
+
isRestArgument: false
|
|
442
|
+
};
|
|
443
|
+
params.push(callableParam);
|
|
399
444
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
445
|
+
const funcType = statement.getType({ flags: SymbolTable_1.SymbolTypeFlag.typetime });
|
|
446
|
+
callables.push({
|
|
447
|
+
isSub: ((_c = statement.func.tokens.functionType) === null || _c === void 0 ? void 0 : _c.text.toLowerCase()) === 'sub',
|
|
448
|
+
name: (_d = statement.tokens.name) === null || _d === void 0 ? void 0 : _d.text,
|
|
449
|
+
nameRange: (_e = statement.tokens.name) === null || _e === void 0 ? void 0 : _e.range,
|
|
450
|
+
file: this,
|
|
451
|
+
params: params,
|
|
452
|
+
range: statement.func.range,
|
|
453
|
+
type: funcType,
|
|
454
|
+
getName: statement.getName.bind(statement),
|
|
455
|
+
hasNamespace: !!statement.findAncestor(reflection_1.isNamespaceStatement),
|
|
456
|
+
functionStatement: statement
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return callables;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
get functionCalls() {
|
|
463
|
+
return this.cache.getOrAdd(`BrsFile_functionCalls`, () => {
|
|
464
|
+
var _a, _b;
|
|
465
|
+
const functionCalls = [];
|
|
466
|
+
//for every function in the file
|
|
467
|
+
for (let func of this._cachedLookups.functionExpressions) {
|
|
468
|
+
//for all function calls in this function
|
|
469
|
+
for (let expression of func.callExpressions) {
|
|
470
|
+
if (
|
|
471
|
+
//filter out dotted function invocations (i.e. object.doSomething()) (not currently supported. TODO support it)
|
|
472
|
+
expression.callee.obj ||
|
|
473
|
+
//filter out method calls on method calls for now (i.e. getSomething().getSomethingElse())
|
|
474
|
+
expression.callee.callee ||
|
|
475
|
+
//filter out callees without a name (immediately-invoked function expressions)
|
|
476
|
+
!((_a = expression.callee.tokens) === null || _a === void 0 ? void 0 : _a.name)) {
|
|
477
|
+
continue;
|
|
416
478
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
479
|
+
//callee is the name of the function being called
|
|
480
|
+
let callee = expression.callee;
|
|
481
|
+
let functionName = callee.tokens.name.text;
|
|
482
|
+
let columnIndexBegin = callee.range.start.character;
|
|
483
|
+
let columnIndexEnd = callee.range.end.character;
|
|
484
|
+
let args = [];
|
|
485
|
+
//TODO convert if stmts to use instanceof instead
|
|
486
|
+
for (let arg of expression.args) {
|
|
487
|
+
//is a literal parameter value
|
|
488
|
+
if ((0, reflection_1.isLiteralExpression)(arg)) {
|
|
489
|
+
args.push({
|
|
490
|
+
range: arg.range,
|
|
491
|
+
type: arg.getType(),
|
|
492
|
+
text: arg.tokens.value.text,
|
|
493
|
+
expression: arg,
|
|
494
|
+
typeToken: undefined
|
|
495
|
+
});
|
|
496
|
+
//is variable being passed into argument
|
|
420
497
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
498
|
+
else if ((_b = arg.tokens) === null || _b === void 0 ? void 0 : _b.name) {
|
|
499
|
+
args.push({
|
|
500
|
+
range: arg.range,
|
|
501
|
+
//TODO - look up the data type of the actual variable
|
|
502
|
+
type: new DynamicType_1.DynamicType(),
|
|
503
|
+
text: arg.tokens.name.text,
|
|
504
|
+
expression: arg,
|
|
505
|
+
typeToken: undefined
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
else if (arg.value) {
|
|
509
|
+
let text = '';
|
|
510
|
+
/* istanbul ignore next: TODO figure out why value is undefined sometimes */
|
|
511
|
+
if (arg.value.value) {
|
|
512
|
+
text = arg.value.value.toString();
|
|
513
|
+
}
|
|
514
|
+
let callableArg = {
|
|
515
|
+
range: arg.range,
|
|
516
|
+
//TODO not sure what to do here
|
|
517
|
+
type: new DynamicType_1.DynamicType(),
|
|
518
|
+
text: text,
|
|
519
|
+
expression: arg,
|
|
520
|
+
typeToken: undefined
|
|
521
|
+
};
|
|
522
|
+
//wrap the value in quotes because that's how it appears in the code
|
|
523
|
+
if ((0, reflection_1.isStringType)(callableArg.type)) {
|
|
524
|
+
callableArg.text = '"' + callableArg.text + '"';
|
|
427
525
|
}
|
|
526
|
+
args.push(callableArg);
|
|
428
527
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
528
|
+
else {
|
|
529
|
+
args.push({
|
|
530
|
+
range: arg.range,
|
|
531
|
+
type: new DynamicType_1.DynamicType(),
|
|
532
|
+
//TODO get text from other types of args
|
|
533
|
+
text: '',
|
|
534
|
+
expression: arg,
|
|
535
|
+
typeToken: undefined
|
|
536
|
+
});
|
|
432
537
|
}
|
|
433
538
|
}
|
|
434
|
-
|
|
435
|
-
range:
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
539
|
+
let functionCall = {
|
|
540
|
+
range: expression.range,
|
|
541
|
+
functionScope: this.getFunctionScopeAtPosition(callee.range.start),
|
|
542
|
+
file: this,
|
|
543
|
+
name: functionName,
|
|
544
|
+
nameRange: util_1.util.createRange(callee.range.start.line, columnIndexBegin, callee.range.start.line, columnIndexEnd),
|
|
545
|
+
//TODO keep track of parameters
|
|
546
|
+
args: args,
|
|
547
|
+
expression: expression
|
|
548
|
+
};
|
|
549
|
+
functionCalls.push(functionCall);
|
|
441
550
|
}
|
|
442
|
-
let functionCall = {
|
|
443
|
-
range: util_1.util.createRangeFromPositions(expression.range.start, expression.closingParen.range.end),
|
|
444
|
-
functionExpression: this.getFunctionExpressionAtPosition(callee.range.start),
|
|
445
|
-
file: this,
|
|
446
|
-
name: functionName,
|
|
447
|
-
nameRange: util_1.util.createRange(callee.range.start.line, columnIndexBegin, callee.range.start.line, columnIndexEnd),
|
|
448
|
-
args: args,
|
|
449
|
-
isDottedInvocation: dottedInvocation
|
|
450
|
-
};
|
|
451
|
-
this.functionCalls.push(functionCall);
|
|
452
551
|
}
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
getFunctionExpressionAtPosition(position) {
|
|
456
|
-
return this.cache.getOrAdd(`functionExpressionAtPosition-${position.line}:${position.character}`, () => {
|
|
457
|
-
return this._getFunctionExpressionAtPosition(position, this.parser.references.functionExpressions);
|
|
552
|
+
return functionCalls;
|
|
458
553
|
});
|
|
459
554
|
}
|
|
460
555
|
/**
|
|
461
|
-
* Find the function
|
|
556
|
+
* Find the function scope at the given position.
|
|
557
|
+
* @param position the position used to find the deepest scope that contains it
|
|
462
558
|
*/
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
559
|
+
getFunctionScopeAtPosition(position) {
|
|
560
|
+
return this.cache.getOrAdd(`functionScope-${position.line}:${position.character}`, () => {
|
|
561
|
+
return this._getFunctionScopeAtPosition(position, this.functionScopes);
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
_getFunctionScopeAtPosition(position, functionScopes) {
|
|
565
|
+
if (!functionScopes) {
|
|
566
|
+
functionScopes = this.functionScopes;
|
|
466
567
|
}
|
|
467
|
-
for (let
|
|
468
|
-
if (util_1.util.rangeContains(
|
|
568
|
+
for (let scope of functionScopes) {
|
|
569
|
+
if (util_1.util.rangeContains(scope.range, position)) {
|
|
469
570
|
//see if any of that scope's children match the position also, and give them priority
|
|
470
|
-
let
|
|
471
|
-
if (
|
|
472
|
-
return
|
|
571
|
+
let childScope = this._getFunctionScopeAtPosition(position, scope.childrenScopes);
|
|
572
|
+
if (childScope) {
|
|
573
|
+
return childScope;
|
|
473
574
|
}
|
|
474
575
|
else {
|
|
475
|
-
return
|
|
576
|
+
return scope;
|
|
476
577
|
}
|
|
477
578
|
}
|
|
478
579
|
}
|
|
479
580
|
}
|
|
480
581
|
/**
|
|
481
582
|
* Find the NamespaceStatement enclosing the given position
|
|
482
|
-
* @param position
|
|
483
|
-
* @param functionScopes
|
|
484
583
|
*/
|
|
485
584
|
getNamespaceStatementForPosition(position) {
|
|
486
585
|
if (position) {
|
|
487
586
|
return this.cache.getOrAdd(`namespaceStatementForPosition-${position.line}:${position.character}`, () => {
|
|
488
|
-
for (const statement of this.
|
|
587
|
+
for (const statement of this._cachedLookups.namespaceStatements) {
|
|
489
588
|
if (util_1.util.rangeContains(statement.range, position)) {
|
|
490
589
|
return statement;
|
|
491
590
|
}
|
|
@@ -494,701 +593,93 @@ class BrsFile {
|
|
|
494
593
|
}
|
|
495
594
|
}
|
|
496
595
|
/**
|
|
497
|
-
*
|
|
596
|
+
* Given a current token, walk
|
|
498
597
|
*/
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
}
|
|
509
|
-
//if cursor is within a comment, disable completions
|
|
510
|
-
let currentToken = this.parser.getTokenAt(position);
|
|
511
|
-
const tokenKind = currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind;
|
|
512
|
-
if (tokenKind === TokenKind_1.TokenKind.Comment) {
|
|
513
|
-
return [];
|
|
514
|
-
}
|
|
515
|
-
else if (tokenKind === TokenKind_1.TokenKind.StringLiteral || tokenKind === TokenKind_1.TokenKind.TemplateStringQuasi) {
|
|
516
|
-
const match = /^("?)(pkg|libpkg):/.exec(currentToken.text);
|
|
517
|
-
if (match) {
|
|
518
|
-
const [, openingQuote, fileProtocol] = match;
|
|
519
|
-
//include every pkgPath from this scope
|
|
520
|
-
for (const file of scope.getAllFiles()) {
|
|
521
|
-
const pkgPath = `${fileProtocol}:/${file.pkgPath.replace('pkg:/', '')}`;
|
|
522
|
-
result.push({
|
|
523
|
-
label: pkgPath,
|
|
524
|
-
textEdit: vscode_languageserver_2.TextEdit.replace(util_1.util.createRange(currentToken.range.start.line,
|
|
525
|
-
//+1 to step past the opening quote
|
|
526
|
-
currentToken.range.start.character + (openingQuote ? 1 : 0), currentToken.range.end.line,
|
|
527
|
-
//-1 to exclude the closing quotemark (or the end character if there is no closing quotemark)
|
|
528
|
-
currentToken.range.end.character + (currentToken.text.endsWith('"') ? -1 : 0)), pkgPath),
|
|
529
|
-
kind: vscode_languageserver_2.CompletionItemKind.File
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
return result;
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
//do nothing. we don't want to show completions inside of strings...
|
|
536
|
-
return [];
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
const namespaceCompletions = this.getNamespaceCompletions(currentToken, this.parseMode, scope);
|
|
540
|
-
if (namespaceCompletions.length > 0) {
|
|
541
|
-
return [...namespaceCompletions];
|
|
542
|
-
}
|
|
543
|
-
const enumMemberCompletions = this.getEnumMemberStatementCompletions(currentToken, this.parseMode, scope);
|
|
544
|
-
if (enumMemberCompletions.length > 0) {
|
|
545
|
-
// no other completion is valid in this case
|
|
546
|
-
return enumMemberCompletions;
|
|
547
|
-
}
|
|
548
|
-
//determine if cursor is inside a function
|
|
549
|
-
let functionExpression = this.getFunctionExpressionAtPosition(position);
|
|
550
|
-
if (!functionExpression) {
|
|
551
|
-
//we aren't in any function scope, so return the keyword completions and namespaces
|
|
552
|
-
if (this.parser.getTokenBefore(currentToken, TokenKind_1.TokenKind.New)) {
|
|
553
|
-
// there's a new keyword, so only class types are viable here
|
|
554
|
-
return [...this.getGlobalClassStatementCompletions(currentToken, this.parseMode, scope)];
|
|
598
|
+
getPartialVariableName(currentToken, excludeTokens = null) {
|
|
599
|
+
let identifierAndDotKinds = [TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers, TokenKind_1.TokenKind.Dot];
|
|
600
|
+
//consume tokens backwards until we find something other than a dot or an identifier
|
|
601
|
+
let tokens = [];
|
|
602
|
+
const parser = this.parser;
|
|
603
|
+
for (let i = parser.tokens.indexOf(currentToken); i >= 0; i--) {
|
|
604
|
+
currentToken = parser.tokens[i];
|
|
605
|
+
if (identifierAndDotKinds.includes(currentToken.kind) && (!excludeTokens || !excludeTokens.includes(currentToken.kind))) {
|
|
606
|
+
tokens.unshift(currentToken.text);
|
|
555
607
|
}
|
|
556
608
|
else {
|
|
557
|
-
|
|
558
|
-
...exports.KeywordCompletions,
|
|
559
|
-
...this.getGlobalClassStatementCompletions(currentToken, this.parseMode, scope),
|
|
560
|
-
...namespaceCompletions,
|
|
561
|
-
...this.getNonNamespacedEnumStatementCompletions(currentToken, this.parseMode, scope),
|
|
562
|
-
...this.getGlobalInterfaceStatementCompletions(currentToken, this.parseMode, scope)
|
|
563
|
-
];
|
|
609
|
+
break;
|
|
564
610
|
}
|
|
565
611
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
if (newToken) {
|
|
570
|
-
//we are after a new keyword; so we can only be top-level namespaces or classes at this point
|
|
571
|
-
result.push(...classNameCompletions);
|
|
572
|
-
result.push(...namespaceCompletions);
|
|
573
|
-
return result;
|
|
574
|
-
}
|
|
575
|
-
if (this.parser.tokenFollows(currentToken, TokenKind_1.TokenKind.Goto)) {
|
|
576
|
-
return this.getLabelCompletion(functionExpression);
|
|
577
|
-
}
|
|
578
|
-
if (this.parser.isPositionNextToTokenKind(position, TokenKind_1.TokenKind.Dot)) {
|
|
579
|
-
const selfClassMemberCompletions = this.getClassMemberCompletions(position, currentToken, functionExpression, scope);
|
|
580
|
-
if (selfClassMemberCompletions.size > 0) {
|
|
581
|
-
return [...selfClassMemberCompletions.values()].filter((i) => i.label !== 'new');
|
|
582
|
-
}
|
|
583
|
-
const tokenLookup = this.getSymbolTypeFromToken(currentToken, functionExpression, scope);
|
|
584
|
-
if ((_a = tokenLookup.symbolContainer) === null || _a === void 0 ? void 0 : _a.memberTable) {
|
|
585
|
-
return this.getCompletionsFromSymbolTable(tokenLookup.symbolContainer.memberTable);
|
|
586
|
-
}
|
|
587
|
-
const foundClassLink = this.getClassFromTokenLookup(tokenLookup, scope);
|
|
588
|
-
if (!foundClassLink) {
|
|
589
|
-
//and anything from any class in scope to a non m class
|
|
590
|
-
let classMemberCompletions = scope.getAllClassMemberCompletions();
|
|
591
|
-
result.push(...classMemberCompletions.values());
|
|
592
|
-
result.push(...scope.getPropertyNameCompletions().filter((i) => !classMemberCompletions.has(i.label)));
|
|
593
|
-
}
|
|
594
|
-
else {
|
|
595
|
-
result.push(...scope.getPropertyNameCompletions());
|
|
596
|
-
}
|
|
612
|
+
//if we found name and dot tokens, join them together to make the namespace name
|
|
613
|
+
if (tokens.length > 0) {
|
|
614
|
+
return tokens.join('');
|
|
597
615
|
}
|
|
598
616
|
else {
|
|
599
|
-
|
|
600
|
-
//include namespaces
|
|
601
|
-
...namespaceCompletions,
|
|
602
|
-
//include class names
|
|
603
|
-
...classNameCompletions,
|
|
604
|
-
//include interfaces
|
|
605
|
-
...interfaceNameCompletions,
|
|
606
|
-
//include enums
|
|
607
|
-
...this.getNonNamespacedEnumStatementCompletions(currentToken, this.parseMode, scope),
|
|
608
|
-
//include constants
|
|
609
|
-
...this.getNonNamespacedConstStatementCompletions(currentToken, this.parseMode, scope),
|
|
610
|
-
//include the global callables
|
|
611
|
-
...scope.getCallablesAsCompletions(this.parseMode));
|
|
612
|
-
//add `m` because that's always valid within a function
|
|
613
|
-
result.push({
|
|
614
|
-
label: 'm',
|
|
615
|
-
kind: vscode_languageserver_2.CompletionItemKind.Variable
|
|
616
|
-
});
|
|
617
|
-
names.m = true;
|
|
618
|
-
result.push(...exports.KeywordCompletions);
|
|
619
|
-
//include local variables
|
|
620
|
-
for (let symbol of functionExpression.symbolTable.getOwnSymbols()) {
|
|
621
|
-
const symbolNameLower = symbol.name.toLowerCase();
|
|
622
|
-
//skip duplicate variable names
|
|
623
|
-
if (names[symbolNameLower]) {
|
|
624
|
-
continue;
|
|
625
|
-
}
|
|
626
|
-
names[symbolNameLower] = true;
|
|
627
|
-
// TODO TYPES (This may be a performance hit?)
|
|
628
|
-
// const foundType = getTypeFromContext(symbol.type, { scope: scope, file: this });
|
|
629
|
-
result.push({
|
|
630
|
-
//TODO does this work?
|
|
631
|
-
label: symbol.name,
|
|
632
|
-
//TODO TYPES find type for local vars - SEE above
|
|
633
|
-
kind: vscode_languageserver_2.CompletionItemKind.Variable
|
|
634
|
-
// kind: isFunctionType(foundType) ? CompletionItemKind.Function : CompletionItemKind.Variable
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
if (this.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
638
|
-
//include the first part of namespaces
|
|
639
|
-
let namespaces = scope.getAllNamespaceStatements();
|
|
640
|
-
for (let stmt of namespaces) {
|
|
641
|
-
let firstPart = stmt.nameExpression.getNameParts().shift();
|
|
642
|
-
//skip duplicate namespace names
|
|
643
|
-
if (names[firstPart.toLowerCase()]) {
|
|
644
|
-
continue;
|
|
645
|
-
}
|
|
646
|
-
names[firstPart.toLowerCase()] = true;
|
|
647
|
-
result.push({
|
|
648
|
-
label: firstPart,
|
|
649
|
-
kind: vscode_languageserver_2.CompletionItemKind.Module
|
|
650
|
-
});
|
|
651
|
-
}
|
|
652
|
-
}
|
|
617
|
+
return undefined;
|
|
653
618
|
}
|
|
654
|
-
return result;
|
|
655
|
-
}
|
|
656
|
-
getCompletionsFromSymbolTable(symbolTable) {
|
|
657
|
-
return symbolTable.getAllSymbols().map(bscType => {
|
|
658
|
-
return {
|
|
659
|
-
label: bscType.name,
|
|
660
|
-
kind: (0, reflection_1.isTypedFunctionType)(bscType.type) ? vscode_languageserver_2.CompletionItemKind.Method : vscode_languageserver_2.CompletionItemKind.Field
|
|
661
|
-
};
|
|
662
|
-
});
|
|
663
619
|
}
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
kind: vscode_languageserver_2.CompletionItemKind.Reference
|
|
668
|
-
}));
|
|
620
|
+
isPositionNextToTokenKind(position, tokenKind) {
|
|
621
|
+
const closestToken = this.getClosestToken(position);
|
|
622
|
+
return this.isTokenNextToTokenKind(closestToken, tokenKind);
|
|
669
623
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
if (
|
|
675
|
-
|
|
676
|
-
for (let cs of classes) {
|
|
677
|
-
for (let member of [...(_b = (_a = cs === null || cs === void 0 ? void 0 : cs.item) === null || _a === void 0 ? void 0 : _a.fields) !== null && _b !== void 0 ? _b : [], ...(_d = (_c = cs === null || cs === void 0 ? void 0 : cs.item) === null || _c === void 0 ? void 0 : _c.methods) !== null && _d !== void 0 ? _d : []]) {
|
|
678
|
-
if (!results.has(member.name.text.toLowerCase())) {
|
|
679
|
-
results.set(member.name.text.toLowerCase(), {
|
|
680
|
-
label: member.name.text,
|
|
681
|
-
kind: (0, reflection_1.isFieldStatement)(member) ? vscode_languageserver_2.CompletionItemKind.Field : vscode_languageserver_2.CompletionItemKind.Method
|
|
682
|
-
});
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
}
|
|
624
|
+
isTokenNextToTokenKind(closestToken, tokenKind) {
|
|
625
|
+
const previousToken = this.getPreviousToken(closestToken);
|
|
626
|
+
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
627
|
+
//next to matched token
|
|
628
|
+
if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
|
|
629
|
+
return false;
|
|
686
630
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
/**
|
|
690
|
-
* Gets the class (if any) of a given token based on the scope
|
|
691
|
-
* @param currentToken token in question
|
|
692
|
-
* @param functionExpression current functionExpression
|
|
693
|
-
* @param scope the current scope
|
|
694
|
-
* @returns A fileLink of the ClassStatement, if it is a class, otherwise undefined
|
|
695
|
-
*/
|
|
696
|
-
getClassFromToken(currentToken, functionExpression, scope) {
|
|
697
|
-
const tokenLookup = this.getSymbolTypeFromToken(currentToken, functionExpression, scope);
|
|
698
|
-
return this.getClassFromTokenLookup(tokenLookup, scope);
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* Gets the class (if any) of a given token based on the scope
|
|
702
|
-
* @param currentToken token in question
|
|
703
|
-
* @param functionExpression current functionExpression
|
|
704
|
-
* @param scope the current scope
|
|
705
|
-
* @returns A fileLink of the ClassStatement, if it is a class, otherwise undefined
|
|
706
|
-
*/
|
|
707
|
-
getClassFromTokenLookup(tokenLookup, scope) {
|
|
708
|
-
const currentClass = tokenLookup === null || tokenLookup === void 0 ? void 0 : tokenLookup.symbolContainer;
|
|
709
|
-
if ((0, reflection_1.isClassStatement)(currentClass)) {
|
|
710
|
-
return { item: currentClass, file: this };
|
|
711
|
-
}
|
|
712
|
-
else if ((0, reflection_1.isCustomType)(currentClass)) {
|
|
713
|
-
const foundClass = scope.getClass(currentClass.name);
|
|
714
|
-
if (foundClass) {
|
|
715
|
-
return { item: foundClass, file: this };
|
|
716
|
-
}
|
|
631
|
+
else if (closestToken.kind === tokenKind) {
|
|
632
|
+
return true;
|
|
717
633
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
let namespaceTokens = [];
|
|
722
|
-
let startsWithNamespace = '';
|
|
723
|
-
let namespaceContainer;
|
|
724
|
-
let tokenChain = [...originalTokenChain];
|
|
725
|
-
while (tokenChain[0] && tokenChain[0].usage === Parser_1.TokenUsage.Direct) {
|
|
726
|
-
const namespaceNameToCheck = `${startsWithNamespace}${startsWithNamespace.length > 0 ? '.' : ''}${tokenChain[0].token.text}`.toLowerCase();
|
|
727
|
-
const foundNamespace = scope.namespaceLookup.get(namespaceNameToCheck);
|
|
728
|
-
if (foundNamespace) {
|
|
729
|
-
namespaceContainer = foundNamespace;
|
|
730
|
-
namespaceTokens.push(tokenChain[0].token);
|
|
731
|
-
startsWithNamespace = namespaceTokens.map(token => token.text).join('.');
|
|
732
|
-
tokenChain.shift();
|
|
733
|
-
}
|
|
734
|
-
else {
|
|
735
|
-
break;
|
|
736
|
-
}
|
|
634
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
|
|
635
|
+
return false;
|
|
636
|
+
//next to an identifier, which is next to token kind
|
|
737
637
|
}
|
|
738
|
-
if (
|
|
739
|
-
|
|
638
|
+
else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
639
|
+
return true;
|
|
740
640
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
checkForSpecialClassSymbol(currentToken, scope, func) {
|
|
744
|
-
var _a;
|
|
745
|
-
const containingClass = this.parser.getContainingClass(currentToken);
|
|
746
|
-
let symbolType;
|
|
747
|
-
let currentClassRef;
|
|
748
|
-
const currentTokenLower = currentToken.text.toLowerCase();
|
|
749
|
-
const typeContext = { file: this, scope: scope, position: currentToken.range.start };
|
|
750
|
-
if (containingClass) {
|
|
751
|
-
// Special cases for a single token inside a class
|
|
752
|
-
let expandedText = '';
|
|
753
|
-
let useExpandedTextOnly = false;
|
|
754
|
-
if (containingClass.name === currentToken) {
|
|
755
|
-
symbolType = containingClass.getThisBscType();
|
|
756
|
-
expandedText = `class ${containingClass.getName(Parser_1.ParseMode.BrighterScript)}`;
|
|
757
|
-
useExpandedTextOnly = true;
|
|
758
|
-
currentClassRef = containingClass;
|
|
759
|
-
}
|
|
760
|
-
else if (currentTokenLower === 'm') {
|
|
761
|
-
symbolType = containingClass.getThisBscType();
|
|
762
|
-
expandedText = currentToken.text;
|
|
763
|
-
currentClassRef = containingClass;
|
|
764
|
-
}
|
|
765
|
-
else if (currentTokenLower === 'super') {
|
|
766
|
-
symbolType = (0, BscType_1.getTypeFromContext)(containingClass.symbolTable.getSymbolType(currentTokenLower, true, typeContext), typeContext);
|
|
767
|
-
if ((0, reflection_1.isTypedFunctionType)(symbolType)) {
|
|
768
|
-
currentClassRef = scope.getParentClass(containingClass);
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
else if (((_a = func === null || func === void 0 ? void 0 : func.functionStatement) === null || _a === void 0 ? void 0 : _a.name) === currentToken) {
|
|
772
|
-
// check if this is a method declaration
|
|
773
|
-
currentClassRef = containingClass;
|
|
774
|
-
symbolType = containingClass === null || containingClass === void 0 ? void 0 : containingClass.memberTable.getSymbolType(currentTokenLower, true, { file: this, scope: scope });
|
|
775
|
-
expandedText = [containingClass.getName(Parser_1.ParseMode.BrighterScript), currentToken.text].join('.');
|
|
776
|
-
}
|
|
777
|
-
else if (!func) {
|
|
778
|
-
// check if this is a field declaration
|
|
779
|
-
currentClassRef = containingClass;
|
|
780
|
-
symbolType = containingClass === null || containingClass === void 0 ? void 0 : containingClass.memberTable.getSymbolType(currentTokenLower, true, { file: this, scope: scope });
|
|
781
|
-
expandedText = [containingClass.getName(Parser_1.ParseMode.BrighterScript), currentToken.text].join('.');
|
|
782
|
-
}
|
|
783
|
-
if (symbolType) {
|
|
784
|
-
return { type: symbolType, expandedTokenText: expandedText, symbolContainer: currentClassRef, useExpandedTextOnly: useExpandedTextOnly };
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
checkForSpecialCaseToken(nameSpacedTokenChain, functionExpression, scope) {
|
|
789
|
-
var _a;
|
|
790
|
-
const tokenChain = (_a = nameSpacedTokenChain.tokenChain) !== null && _a !== void 0 ? _a : [];
|
|
791
|
-
if (nameSpacedTokenChain.namespaceContainer && tokenChain.length === 0) {
|
|
792
|
-
//currentToken was part of a namespace
|
|
793
|
-
return {
|
|
794
|
-
type: null,
|
|
795
|
-
expandedTokenText: `namespace ${nameSpacedTokenChain.namespaceContainer.fullName}`,
|
|
796
|
-
useExpandedTextOnly: true
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
|
-
const specialCase = tokenChain.length === 1 ? this.checkForSpecialClassSymbol(tokenChain[0].token, scope, functionExpression) : null;
|
|
800
|
-
if (specialCase) {
|
|
801
|
-
return specialCase;
|
|
641
|
+
else {
|
|
642
|
+
return false;
|
|
802
643
|
}
|
|
803
644
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
var _a, _b, _c, _d;
|
|
813
|
-
if (!scope || !currentToken) {
|
|
814
|
-
return undefined;
|
|
815
|
-
}
|
|
816
|
-
const cachedSymbolData = scope.symbolCache.get(currentToken);
|
|
817
|
-
if (cachedSymbolData) {
|
|
818
|
-
return cachedSymbolData;
|
|
819
|
-
}
|
|
820
|
-
const tokenChainResponse = this.parser.getTokenChain(currentToken);
|
|
821
|
-
if (tokenChainResponse.includesUnknowableTokenType) {
|
|
822
|
-
const symbolData = { type: new DynamicType_1.DynamicType(), expandedTokenText: currentToken.text };
|
|
823
|
-
scope.symbolCache.set(currentToken, symbolData);
|
|
824
|
-
return symbolData;
|
|
825
|
-
}
|
|
826
|
-
const nameSpacedTokenChain = this.findNamespaceFromTokenChain(tokenChainResponse.chain, scope);
|
|
827
|
-
const specialCase = this.checkForSpecialCaseToken(nameSpacedTokenChain, functionExpression, scope);
|
|
828
|
-
if (specialCase) {
|
|
829
|
-
scope.symbolCache.set(currentToken, specialCase);
|
|
830
|
-
return specialCase;
|
|
831
|
-
}
|
|
832
|
-
const tokenChain = nameSpacedTokenChain.tokenChain;
|
|
833
|
-
let symbolContainer = this.parser.getContainingAA(currentToken) || this.parser.getContainingClass(currentToken);
|
|
834
|
-
let currentSymbolTable = (_b = (_a = nameSpacedTokenChain.namespaceContainer) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : functionExpression === null || functionExpression === void 0 ? void 0 : functionExpression.symbolTable;
|
|
835
|
-
let tokenFoundCount = 0;
|
|
836
|
-
let symbolTypeBeforeReference;
|
|
837
|
-
let symbolType;
|
|
838
|
-
let tokenText = [];
|
|
839
|
-
let justReturnDynamic = false;
|
|
840
|
-
let fullNamespaceName = nameSpacedTokenChain.namespaceContainer ? nameSpacedTokenChain.namespaceContainer.fullName + '.' : '';
|
|
841
|
-
const typeContext = { file: this, scope: scope, position: (_c = tokenChain[0]) === null || _c === void 0 ? void 0 : _c.token.range.start };
|
|
842
|
-
for (const tokenChainMember of tokenChain) {
|
|
843
|
-
const token = tokenChainMember === null || tokenChainMember === void 0 ? void 0 : tokenChainMember.token;
|
|
844
|
-
const tokenUsage = tokenChainMember === null || tokenChainMember === void 0 ? void 0 : tokenChainMember.usage;
|
|
845
|
-
const tokenLowerText = token.text.toLowerCase();
|
|
846
|
-
if (tokenLowerText === 'super' && (0, reflection_1.isClassStatement)(symbolContainer) && tokenFoundCount === 0) {
|
|
847
|
-
/// Special cases for first item in chain inside a class
|
|
848
|
-
symbolContainer = scope === null || scope === void 0 ? void 0 : scope.getParentClass(symbolContainer);
|
|
849
|
-
currentSymbolTable = symbolContainer === null || symbolContainer === void 0 ? void 0 : symbolContainer.memberTable;
|
|
850
|
-
if (symbolContainer && currentSymbolTable) {
|
|
851
|
-
tokenText.push(symbolContainer.getName(Parser_1.ParseMode.BrighterScript));
|
|
852
|
-
tokenFoundCount++;
|
|
853
|
-
continue;
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
if (!currentSymbolTable) {
|
|
857
|
-
// uh oh... no symbol table to continue to check
|
|
645
|
+
getTokenBefore(currentToken, tokenKind) {
|
|
646
|
+
const index = this.parser.tokens.indexOf(currentToken);
|
|
647
|
+
if (!tokenKind) {
|
|
648
|
+
return this.parser.tokens[index - 1];
|
|
649
|
+
}
|
|
650
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
651
|
+
currentToken = this.parser.tokens[i];
|
|
652
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
|
|
858
653
|
break;
|
|
859
654
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
//check for global callable
|
|
863
|
-
symbolType = (_d = scope.getGlobalCallableByName(tokenLowerText)) === null || _d === void 0 ? void 0 : _d.type;
|
|
864
|
-
}
|
|
865
|
-
if (symbolType) {
|
|
866
|
-
// found this symbol, and it's valid. increase found counter
|
|
867
|
-
tokenFoundCount++;
|
|
868
|
-
}
|
|
869
|
-
symbolTypeBeforeReference = symbolType;
|
|
870
|
-
if ((0, reflection_1.isTypedFunctionType)(symbolType)) {
|
|
871
|
-
// this is a function, and it is in the start or middle of the chain
|
|
872
|
-
// the next symbol to check will be the return value of this function
|
|
873
|
-
symbolType = (0, BscType_1.getTypeFromContext)(symbolType.returnType, typeContext);
|
|
874
|
-
if (tokenFoundCount < tokenChain.length) {
|
|
875
|
-
// We still have more tokens, but remember the last known reference
|
|
876
|
-
symbolTypeBeforeReference = symbolType;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
if ((0, reflection_1.isArrayType)(symbolType) && tokenUsage === Parser_1.TokenUsage.ArrayReference) {
|
|
880
|
-
symbolType = (0, BscType_1.getTypeFromContext)(symbolType.getDefaultType(typeContext), typeContext);
|
|
881
|
-
}
|
|
882
|
-
if (symbolType === null || symbolType === void 0 ? void 0 : symbolType.memberTable) {
|
|
883
|
-
if ((0, reflection_1.isCustomType)(symbolType) || (0, reflection_1.isInterfaceType)(symbolType) || (0, reflection_1.isEnumType)(symbolType)) {
|
|
884
|
-
// we're currently looking at a type that has its own symbol table
|
|
885
|
-
// use the name of the custom type
|
|
886
|
-
// TODO TYPES: get proper parent name for methods/fields defined in super classes
|
|
887
|
-
tokenText.push(tokenChain.length === 1 ? token.text : symbolType.name);
|
|
888
|
-
}
|
|
889
|
-
else {
|
|
890
|
-
justReturnDynamic = true;
|
|
891
|
-
tokenText.push(token.text);
|
|
892
|
-
}
|
|
893
|
-
symbolContainer = symbolType;
|
|
894
|
-
currentSymbolTable = symbolContainer === null || symbolContainer === void 0 ? void 0 : symbolContainer.memberTable;
|
|
895
|
-
}
|
|
896
|
-
else if ((0, reflection_1.isObjectType)(symbolType) || (0, reflection_1.isArrayType)(symbolType) || (0, reflection_1.isDynamicType)(symbolType)) {
|
|
897
|
-
// this is an object that has no member table
|
|
898
|
-
// this could happen if a parameter is marked as object
|
|
899
|
-
// assume all fields are dynamic
|
|
900
|
-
symbolContainer = undefined;
|
|
901
|
-
tokenText.push(token.text);
|
|
902
|
-
justReturnDynamic = true;
|
|
903
|
-
break;
|
|
904
|
-
}
|
|
905
|
-
else {
|
|
906
|
-
// No further symbol tables were found
|
|
907
|
-
symbolContainer = undefined;
|
|
908
|
-
tokenText.push(token.text);
|
|
909
|
-
break;
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
if (tokenText.length > 2) {
|
|
913
|
-
// TokenText is used for hovers. We only need the last two tokens for a hover
|
|
914
|
-
// So in a long chain (e.g. klass.getData()[0].anotherKlass.property), the hover
|
|
915
|
-
// for the last token should just be "AnotherKlass.property", not the whole chain
|
|
916
|
-
tokenText = tokenText.slice(-2);
|
|
917
|
-
}
|
|
918
|
-
let expandedTokenText = tokenText.join('.');
|
|
919
|
-
let backUpReturnType;
|
|
920
|
-
if (tokenFoundCount === tokenChain.length) {
|
|
921
|
-
// did we complete the chain? if so, we have a valid token at the end
|
|
922
|
-
const symbolData = { type: symbolTypeBeforeReference, expandedTokenText: tokenText.join('.'), symbolContainer: symbolContainer };
|
|
923
|
-
scope.symbolCache.set(currentToken, symbolData);
|
|
924
|
-
return symbolData;
|
|
925
|
-
}
|
|
926
|
-
if ((0, reflection_1.isDynamicType)(symbolTypeBeforeReference) || (0, reflection_1.isArrayType)(symbolTypeBeforeReference) || justReturnDynamic) {
|
|
927
|
-
// last type in chain is dynamic... so currentToken could be anything.
|
|
928
|
-
backUpReturnType = new DynamicType_1.DynamicType();
|
|
929
|
-
expandedTokenText = currentToken.text;
|
|
930
|
-
}
|
|
931
|
-
else if ((0, reflection_1.isPrimitiveType)(symbolTypeBeforeReference)) {
|
|
932
|
-
// last type in chain is dynamic... so currentToken could be anything.
|
|
933
|
-
backUpReturnType = new DynamicType_1.DynamicType();
|
|
934
|
-
expandedTokenText = currentToken.text;
|
|
935
|
-
}
|
|
936
|
-
else if (tokenChain.length === 1) {
|
|
937
|
-
// variable that has not been assigned
|
|
938
|
-
expandedTokenText = currentToken.text;
|
|
939
|
-
backUpReturnType = new UninitializedType_1.UninitializedType();
|
|
940
|
-
}
|
|
941
|
-
else if (tokenFoundCount === tokenChain.length - 1) {
|
|
942
|
-
// member field that is not known
|
|
943
|
-
if (symbolContainer) {
|
|
944
|
-
backUpReturnType = new InvalidType_1.InvalidType();
|
|
945
|
-
}
|
|
946
|
-
else {
|
|
947
|
-
// TODO TYPES: once we have stricter object/node member type checking, we could say this is invalid, but until then, call it dynamic
|
|
948
|
-
backUpReturnType = new DynamicType_1.DynamicType();
|
|
949
|
-
expandedTokenText = currentToken.text;
|
|
655
|
+
else if (currentToken.kind === tokenKind) {
|
|
656
|
+
return currentToken;
|
|
950
657
|
}
|
|
951
658
|
}
|
|
952
|
-
|
|
953
|
-
scope.symbolCache.set(currentToken, symbolData);
|
|
954
|
-
return symbolData;
|
|
955
|
-
}
|
|
956
|
-
getGlobalClassStatementCompletions(currentToken, parseMode, scope) {
|
|
957
|
-
var _a;
|
|
958
|
-
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
959
|
-
return [];
|
|
960
|
-
}
|
|
961
|
-
let results = new Map();
|
|
962
|
-
let completionName = (_a = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New])) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
963
|
-
if (completionName === null || completionName === void 0 ? void 0 : completionName.includes('.')) {
|
|
964
|
-
return [];
|
|
965
|
-
}
|
|
966
|
-
let classMap = scope.getClassMap();
|
|
967
|
-
// let viableKeys = [...classMap.keys()].filter((k) => k.startsWith(completionName));
|
|
968
|
-
for (const key of [...classMap.keys()]) {
|
|
969
|
-
let cs = classMap.get(key).item;
|
|
970
|
-
if (!results.has(cs.name.text)) {
|
|
971
|
-
results.set(cs.name.text, {
|
|
972
|
-
label: cs.name.text,
|
|
973
|
-
kind: vscode_languageserver_2.CompletionItemKind.Class
|
|
974
|
-
});
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
return [...results.values()];
|
|
978
|
-
}
|
|
979
|
-
getNonNamespacedEnumStatementCompletions(currentToken, parseMode, scope) {
|
|
980
|
-
var _a, _b;
|
|
981
|
-
if (parseMode !== Parser_1.ParseMode.BrighterScript) {
|
|
982
|
-
return [];
|
|
983
|
-
}
|
|
984
|
-
const containingNamespaceName = ((_b = this.getNamespaceStatementForPosition((_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.range) === null || _a === void 0 ? void 0 : _a.start)) === null || _b === void 0 ? void 0 : _b.name) + '.';
|
|
985
|
-
const results = new Map();
|
|
986
|
-
const enumMap = scope.getEnumMap();
|
|
987
|
-
for (const key of [...enumMap.keys()]) {
|
|
988
|
-
const enumStatement = enumMap.get(key).item;
|
|
989
|
-
const fullName = enumStatement.fullName;
|
|
990
|
-
//if the enum is contained within our own namespace, or if it's a non-namespaced enum
|
|
991
|
-
if (fullName.startsWith(containingNamespaceName) || !fullName.includes('.')) {
|
|
992
|
-
results.set(fullName, {
|
|
993
|
-
label: enumStatement.name,
|
|
994
|
-
kind: vscode_languageserver_2.CompletionItemKind.Enum
|
|
995
|
-
});
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
return [...results.values()];
|
|
999
|
-
}
|
|
1000
|
-
getNonNamespacedConstStatementCompletions(currentToken, parseMode, scope) {
|
|
1001
|
-
var _a, _b;
|
|
1002
|
-
if (parseMode !== Parser_1.ParseMode.BrighterScript) {
|
|
1003
|
-
return [];
|
|
1004
|
-
}
|
|
1005
|
-
const containingNamespaceName = ((_b = this.getNamespaceStatementForPosition((_a = currentToken === null || currentToken === void 0 ? void 0 : currentToken.range) === null || _a === void 0 ? void 0 : _a.start)) === null || _b === void 0 ? void 0 : _b.name) + '.';
|
|
1006
|
-
const results = new Map();
|
|
1007
|
-
const map = scope.getConstMap();
|
|
1008
|
-
for (const key of [...map.keys()]) {
|
|
1009
|
-
const statement = map.get(key).item;
|
|
1010
|
-
const fullName = statement.fullName;
|
|
1011
|
-
//if the item is contained within our own namespace, or if it's non-namespaced
|
|
1012
|
-
if (fullName.startsWith(containingNamespaceName) || !fullName.includes('.')) {
|
|
1013
|
-
results.set(fullName, {
|
|
1014
|
-
label: statement.name,
|
|
1015
|
-
kind: vscode_languageserver_2.CompletionItemKind.Constant
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
return [...results.values()];
|
|
1020
|
-
}
|
|
1021
|
-
getEnumMemberStatementCompletions(currentToken, parseMode, scope) {
|
|
1022
|
-
var _a, _b, _c, _d, _e;
|
|
1023
|
-
if (parseMode === Parser_1.ParseMode.BrightScript || !currentToken) {
|
|
1024
|
-
return [];
|
|
1025
|
-
}
|
|
1026
|
-
const results = new Map();
|
|
1027
|
-
const completionName = (_a = this.getPartialVariableName(currentToken)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
1028
|
-
//if we don't have a completion name, or if there's no period in the name, then this is not to the right of an enum name
|
|
1029
|
-
if (!completionName || !completionName.includes('.')) {
|
|
1030
|
-
return [];
|
|
1031
|
-
}
|
|
1032
|
-
const enumNameLower = (_b = completionName === null || completionName === void 0 ? void 0 : completionName.split(/\.(\w+)?$/)[0]) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
1033
|
-
const namespaceNameLower = (_c = this.getNamespaceStatementForPosition(currentToken.range.end)) === null || _c === void 0 ? void 0 : _c.name.toLowerCase();
|
|
1034
|
-
const enumMap = scope.getEnumMap();
|
|
1035
|
-
//get the enum statement with this name (check without namespace prefix first, then with inferred namespace prefix next)
|
|
1036
|
-
const enumStatement = (_e = ((_d = enumMap.get(enumNameLower)) !== null && _d !== void 0 ? _d : enumMap.get(namespaceNameLower + '.' + enumNameLower))) === null || _e === void 0 ? void 0 : _e.item;
|
|
1037
|
-
//if we found an enum with this name
|
|
1038
|
-
if (enumStatement) {
|
|
1039
|
-
for (const member of enumStatement.getMembers()) {
|
|
1040
|
-
const name = enumStatement.fullName + '.' + member.name;
|
|
1041
|
-
const nameLower = name.toLowerCase();
|
|
1042
|
-
results.set(nameLower, {
|
|
1043
|
-
label: member.name,
|
|
1044
|
-
kind: vscode_languageserver_2.CompletionItemKind.EnumMember
|
|
1045
|
-
});
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
return [...results.values()];
|
|
1049
|
-
}
|
|
1050
|
-
getGlobalInterfaceStatementCompletions(currentToken, parseMode, scope) {
|
|
1051
|
-
var _a;
|
|
1052
|
-
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
1053
|
-
return [];
|
|
1054
|
-
}
|
|
1055
|
-
let results = new Map();
|
|
1056
|
-
let completionName = (_a = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New])) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
1057
|
-
if (completionName === null || completionName === void 0 ? void 0 : completionName.includes('.')) {
|
|
1058
|
-
return [];
|
|
1059
|
-
}
|
|
1060
|
-
let ifaceMap = scope.getInterfaceMap();
|
|
1061
|
-
for (const key of [...ifaceMap.keys()]) {
|
|
1062
|
-
let cs = ifaceMap.get(key).item;
|
|
1063
|
-
if (!results.has(cs.name.text)) {
|
|
1064
|
-
results.set(cs.name.text, {
|
|
1065
|
-
label: cs.name.text,
|
|
1066
|
-
kind: vscode_languageserver_2.CompletionItemKind.Interface
|
|
1067
|
-
});
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
return [...results.values()];
|
|
1071
|
-
}
|
|
1072
|
-
getNamespaceCompletions(currentToken, parseMode, scope) {
|
|
1073
|
-
//BrightScript does not support namespaces, so return an empty list in that case
|
|
1074
|
-
if (parseMode === Parser_1.ParseMode.BrightScript) {
|
|
1075
|
-
return [];
|
|
1076
|
-
}
|
|
1077
|
-
const completionName = this.getPartialVariableName(currentToken, [TokenKind_1.TokenKind.New]);
|
|
1078
|
-
//if we don't have a completion name, or if there's no period in the name, then this is not a namespaced variable
|
|
1079
|
-
if (!completionName || !completionName.includes('.')) {
|
|
1080
|
-
return [];
|
|
1081
|
-
}
|
|
1082
|
-
//remove any trailing identifer and then any trailing dot, to give us the
|
|
1083
|
-
//name of its immediate parent namespace
|
|
1084
|
-
let closestParentNamespaceName = completionName.replace(/\.([a-z0-9_]*)?$/gi, '').toLowerCase();
|
|
1085
|
-
let newToken = this.parser.getTokenBefore(currentToken, TokenKind_1.TokenKind.New);
|
|
1086
|
-
let result = new Map();
|
|
1087
|
-
for (let [, namespace] of scope.namespaceLookup) {
|
|
1088
|
-
//completionName = "NameA."
|
|
1089
|
-
//completionName = "NameA.Na
|
|
1090
|
-
//NameA
|
|
1091
|
-
//NameA.NameB
|
|
1092
|
-
//NameA.NameB.NameC
|
|
1093
|
-
if (namespace.fullName.toLowerCase() === closestParentNamespaceName) {
|
|
1094
|
-
//add all of this namespace's immediate child namespaces, bearing in mind if we are after a new keyword
|
|
1095
|
-
for (let [, ns] of namespace.namespaces) {
|
|
1096
|
-
if (!newToken || ns.statements.find((s) => (0, reflection_1.isClassStatement)(s))) {
|
|
1097
|
-
if (!result.has(ns.lastPartName)) {
|
|
1098
|
-
result.set(ns.lastPartName, {
|
|
1099
|
-
label: ns.lastPartName,
|
|
1100
|
-
kind: vscode_languageserver_2.CompletionItemKind.Module
|
|
1101
|
-
});
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
//add function and class statement completions
|
|
1106
|
-
for (let stmt of namespace.statements) {
|
|
1107
|
-
if ((0, reflection_1.isClassStatement)(stmt)) {
|
|
1108
|
-
result.set(stmt.name.text, {
|
|
1109
|
-
label: stmt.name.text,
|
|
1110
|
-
kind: vscode_languageserver_2.CompletionItemKind.Class
|
|
1111
|
-
});
|
|
1112
|
-
}
|
|
1113
|
-
else if ((0, reflection_1.isFunctionStatement)(stmt) && !newToken) {
|
|
1114
|
-
result.set(stmt.name.text, {
|
|
1115
|
-
label: stmt.name.text,
|
|
1116
|
-
kind: vscode_languageserver_2.CompletionItemKind.Function
|
|
1117
|
-
});
|
|
1118
|
-
}
|
|
1119
|
-
else if ((0, reflection_1.isEnumStatement)(stmt) && !newToken) {
|
|
1120
|
-
result.set(stmt.name, {
|
|
1121
|
-
label: stmt.name,
|
|
1122
|
-
kind: vscode_languageserver_2.CompletionItemKind.Enum
|
|
1123
|
-
});
|
|
1124
|
-
}
|
|
1125
|
-
else if ((0, reflection_1.isConstStatement)(stmt) && !newToken) {
|
|
1126
|
-
result.set(stmt.name, {
|
|
1127
|
-
label: stmt.name,
|
|
1128
|
-
kind: vscode_languageserver_2.CompletionItemKind.Constant
|
|
1129
|
-
});
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
return [...result.values()];
|
|
659
|
+
return undefined;
|
|
1135
660
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
if (
|
|
1139
|
-
return
|
|
661
|
+
tokenFollows(currentToken, tokenKind) {
|
|
662
|
+
const index = this.parser.tokens.indexOf(currentToken);
|
|
663
|
+
if (index > 0) {
|
|
664
|
+
return this.parser.tokens[index - 1].kind === tokenKind;
|
|
1140
665
|
}
|
|
1141
|
-
|
|
1142
|
-
const nameParts = this.getPartialVariableName(token, [TokenKind_1.TokenKind.New]).split('.');
|
|
1143
|
-
const endName = nameParts[nameParts.length - 1].toLowerCase();
|
|
1144
|
-
const namespaceName = nameParts.slice(0, -1).join('.').toLowerCase();
|
|
1145
|
-
const statementHandler = (statement) => {
|
|
1146
|
-
if (!location && statement.getName(Parser_1.ParseMode.BrighterScript).toLowerCase() === namespaceName) {
|
|
1147
|
-
const namespaceItemStatementHandler = (statement) => {
|
|
1148
|
-
if (!location && statement.name.text.toLowerCase() === endName) {
|
|
1149
|
-
const uri = util_1.util.pathToUri(file.srcPath);
|
|
1150
|
-
location = util_1.util.createLocation(uri, statement.range);
|
|
1151
|
-
}
|
|
1152
|
-
};
|
|
1153
|
-
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
1154
|
-
ClassStatement: namespaceItemStatementHandler,
|
|
1155
|
-
FunctionStatement: namespaceItemStatementHandler
|
|
1156
|
-
}), {
|
|
1157
|
-
walkMode: visitors_1.WalkMode.visitStatements
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
};
|
|
1161
|
-
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
1162
|
-
NamespaceStatement: statementHandler
|
|
1163
|
-
}), {
|
|
1164
|
-
walkMode: visitors_1.WalkMode.visitStatements
|
|
1165
|
-
});
|
|
1166
|
-
return location;
|
|
666
|
+
return false;
|
|
1167
667
|
}
|
|
1168
|
-
|
|
1169
|
-
* Given a current token, walk
|
|
1170
|
-
*/
|
|
1171
|
-
getPartialVariableName(currentToken, excludeTokens = null) {
|
|
1172
|
-
let identifierAndDotKinds = [TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers, TokenKind_1.TokenKind.Dot];
|
|
1173
|
-
//consume tokens backwards until we find something other than a dot or an identifier
|
|
668
|
+
getTokensUntil(currentToken, tokenKind, direction = -1) {
|
|
1174
669
|
let tokens = [];
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
currentToken
|
|
1178
|
-
if (identifierAndDotKinds.includes(currentToken.kind) && (!excludeTokens || !excludeTokens.includes(currentToken.kind))) {
|
|
1179
|
-
tokens.unshift(currentToken.text);
|
|
1180
|
-
}
|
|
1181
|
-
else {
|
|
670
|
+
for (let i = this.parser.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.parser.tokens.length; i += direction) {
|
|
671
|
+
currentToken = this.parser.tokens[i];
|
|
672
|
+
if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
1182
673
|
break;
|
|
1183
674
|
}
|
|
675
|
+
tokens.push(currentToken);
|
|
1184
676
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
}
|
|
677
|
+
return tokens;
|
|
678
|
+
}
|
|
679
|
+
getPreviousToken(token) {
|
|
680
|
+
const parser = this.parser;
|
|
681
|
+
let idx = parser.tokens.indexOf(token);
|
|
682
|
+
return parser.tokens[idx - 1];
|
|
1192
683
|
}
|
|
1193
684
|
/**
|
|
1194
685
|
* Find the first scope that has a namespace with this name.
|
|
@@ -1200,7 +691,7 @@ class BrsFile {
|
|
|
1200
691
|
left = left.obj;
|
|
1201
692
|
}
|
|
1202
693
|
if ((0, reflection_1.isVariableExpression)(left)) {
|
|
1203
|
-
let lowerName = left.name.text.toLowerCase();
|
|
694
|
+
let lowerName = left.tokens.name.text.toLowerCase();
|
|
1204
695
|
//find the first scope that contains this namespace
|
|
1205
696
|
let scopes = this.program.getScopesForFile(this);
|
|
1206
697
|
for (let scope of scopes) {
|
|
@@ -1218,12 +709,15 @@ class BrsFile {
|
|
|
1218
709
|
var _a, _b;
|
|
1219
710
|
//if we have a variable and a namespace
|
|
1220
711
|
if ((0, reflection_1.isVariableExpression)(callee) && namespaceName) {
|
|
1221
|
-
let lowerCalleeName = (_b = (_a = callee === null || callee === void 0 ? void 0 : callee.name) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
712
|
+
let lowerCalleeName = (_b = (_a = callee === null || callee === void 0 ? void 0 : callee.tokens.name) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
1222
713
|
if (lowerCalleeName) {
|
|
1223
714
|
let scopes = this.program.getScopesForFile(this);
|
|
1224
715
|
for (let scope of scopes) {
|
|
1225
716
|
let namespace = scope.namespaceLookup.get(namespaceName.toLowerCase());
|
|
1226
|
-
if (namespace.functionStatements
|
|
717
|
+
if (namespace.functionStatements.has(lowerCalleeName)) {
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
if (namespace.classStatements.has(lowerCalleeName)) {
|
|
1227
721
|
return true;
|
|
1228
722
|
}
|
|
1229
723
|
}
|
|
@@ -1231,6 +725,49 @@ class BrsFile {
|
|
|
1231
725
|
}
|
|
1232
726
|
return false;
|
|
1233
727
|
}
|
|
728
|
+
/**
|
|
729
|
+
* Determine if the callee (i.e. function name) is a known function
|
|
730
|
+
*/
|
|
731
|
+
calleeIsKnownFunction(callee, namespaceName) {
|
|
732
|
+
var _a, _b;
|
|
733
|
+
//if we have a variable and a namespace
|
|
734
|
+
if ((0, reflection_1.isVariableExpression)(callee)) {
|
|
735
|
+
if (namespaceName) {
|
|
736
|
+
return this.calleeIsKnownNamespaceFunction(callee, namespaceName);
|
|
737
|
+
}
|
|
738
|
+
let scopes = this.program.getScopesForFile(this);
|
|
739
|
+
let lowerCalleeName = (_b = (_a = callee === null || callee === void 0 ? void 0 : callee.tokens.name) === null || _a === void 0 ? void 0 : _a.text) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
740
|
+
for (let scope of scopes) {
|
|
741
|
+
if (scope.getCallableByName(lowerCalleeName)) {
|
|
742
|
+
return true;
|
|
743
|
+
}
|
|
744
|
+
if (scope.getClass(lowerCalleeName)) {
|
|
745
|
+
return true;
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return false;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Get the token closest to the position. if no token is found, the previous token is returned
|
|
753
|
+
*/
|
|
754
|
+
getClosestToken(position) {
|
|
755
|
+
let tokens = this.parser.tokens;
|
|
756
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
757
|
+
let token = tokens[i];
|
|
758
|
+
if (util_1.util.rangeContains(token.range, position)) {
|
|
759
|
+
return token;
|
|
760
|
+
}
|
|
761
|
+
//if the position less than this token range, then this position touches no token,
|
|
762
|
+
if (util_1.util.positionIsGreaterThanRange(position, token.range) === false) {
|
|
763
|
+
let t = tokens[i - 1];
|
|
764
|
+
//return the token or the first token
|
|
765
|
+
return t ? t : tokens[0];
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
//return the last token
|
|
769
|
+
return tokens[tokens.length - 1];
|
|
770
|
+
}
|
|
1234
771
|
/**
|
|
1235
772
|
* Builds a list of document symbols for this file. Used by LanguageServer's onDocumentSymbol functionality
|
|
1236
773
|
*/
|
|
@@ -1300,7 +837,7 @@ class BrsFile {
|
|
|
1300
837
|
else {
|
|
1301
838
|
return;
|
|
1302
839
|
}
|
|
1303
|
-
const name = (0, reflection_1.isFieldStatement)(statement) ? statement.name.text : statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
840
|
+
const name = (0, reflection_1.isFieldStatement)(statement) ? statement.tokens.name.text : statement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1304
841
|
return vscode_languageserver_2.DocumentSymbol.create(name, '', symbolKind, statement.range, statement.range, children);
|
|
1305
842
|
}
|
|
1306
843
|
/**
|
|
@@ -1340,225 +877,33 @@ class BrsFile {
|
|
|
1340
877
|
symbols.push(symbol);
|
|
1341
878
|
return symbols;
|
|
1342
879
|
}
|
|
1343
|
-
/**
|
|
1344
|
-
* Given a position in a file, if the position is sitting on some type of identifier,
|
|
1345
|
-
* go to the definition of that identifier (where this thing was first defined)
|
|
1346
|
-
*/
|
|
1347
|
-
getDefinition(position) {
|
|
1348
|
-
var _a, _b;
|
|
1349
|
-
let results = [];
|
|
1350
|
-
//get the token at the position
|
|
1351
|
-
const token = this.parser.getTokenAt(position);
|
|
1352
|
-
// While certain other tokens are allowed as local variables (AllowedLocalIdentifiers: https://github.com/rokucommunity/brighterscript/blob/master/src/lexer/TokenKind.ts#L418), these are converted by the parser to TokenKind.Identifier by the time we retrieve the token using getTokenAt
|
|
1353
|
-
let definitionTokenTypes = [
|
|
1354
|
-
TokenKind_1.TokenKind.Identifier,
|
|
1355
|
-
TokenKind_1.TokenKind.StringLiteral
|
|
1356
|
-
];
|
|
1357
|
-
//throw out invalid tokens and the wrong kind of tokens
|
|
1358
|
-
if (!token || !definitionTokenTypes.includes(token.kind)) {
|
|
1359
|
-
return results;
|
|
1360
|
-
}
|
|
1361
|
-
const scopesForFile = this.program.getScopesForFile(this);
|
|
1362
|
-
const [scope] = scopesForFile;
|
|
1363
|
-
scope.linkSymbolTable();
|
|
1364
|
-
const expression = this.getClosestExpression(position);
|
|
1365
|
-
if (expression) {
|
|
1366
|
-
let containingNamespace = (_a = this.getNamespaceStatementForPosition(expression.range.start)) === null || _a === void 0 ? void 0 : _a.getName(Parser_1.ParseMode.BrighterScript);
|
|
1367
|
-
const fullName = (_b = util_1.util.getAllDottedGetParts(expression)) === null || _b === void 0 ? void 0 : _b.map(x => x.text).join('.');
|
|
1368
|
-
//find a constant with this name
|
|
1369
|
-
const constant = scope.getConstFileLink(fullName, containingNamespace);
|
|
1370
|
-
if (constant) {
|
|
1371
|
-
results.push(util_1.util.createLocation(vscode_uri_1.URI.file(constant.file.srcPath).toString(), constant.item.tokens.name.range));
|
|
1372
|
-
return results;
|
|
1373
|
-
}
|
|
1374
|
-
}
|
|
1375
|
-
let textToSearchFor = token.text.toLowerCase();
|
|
1376
|
-
const previousToken = this.parser.getTokenAt({ line: token.range.start.line, character: token.range.start.character });
|
|
1377
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Callfunc) {
|
|
1378
|
-
for (const scope of scopesForFile) {
|
|
1379
|
-
//to only get functions defined in interface methods
|
|
1380
|
-
const callable = scope.getAllCallables().find((c) => c.callable.name.toLowerCase() === textToSearchFor); // eslint-disable-line @typescript-eslint/no-loop-func
|
|
1381
|
-
if (callable) {
|
|
1382
|
-
results.push(util_1.util.createLocation(util_1.util.pathToUri(callable.callable.file.srcPath), callable.callable.functionStatement.range));
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
return results;
|
|
1386
|
-
}
|
|
1387
|
-
let classToken = this.parser.getTokenBefore(token, TokenKind_1.TokenKind.Class);
|
|
1388
|
-
if (classToken) {
|
|
1389
|
-
let cs = this.parser.references.classStatements.find((cs) => cs.classKeyword.range === classToken.range);
|
|
1390
|
-
if (cs === null || cs === void 0 ? void 0 : cs.parentClassName) {
|
|
1391
|
-
const nameParts = cs.parentClassName.getNameParts();
|
|
1392
|
-
let extendedClass = this.getClassFileLink(nameParts[nameParts.length - 1], nameParts.slice(0, -1).join('.'));
|
|
1393
|
-
if (extendedClass) {
|
|
1394
|
-
results.push(util_1.util.createLocation(util_1.util.pathToUri(extendedClass.file.srcPath), extendedClass.item.range));
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
return results;
|
|
1398
|
-
}
|
|
1399
|
-
if (token.kind === TokenKind_1.TokenKind.StringLiteral) {
|
|
1400
|
-
// We need to strip off the quotes but only if present
|
|
1401
|
-
const startIndex = textToSearchFor.startsWith('"') ? 1 : 0;
|
|
1402
|
-
let endIndex = textToSearchFor.length;
|
|
1403
|
-
if (textToSearchFor.endsWith('"')) {
|
|
1404
|
-
endIndex--;
|
|
1405
|
-
}
|
|
1406
|
-
textToSearchFor = textToSearchFor.substring(startIndex, endIndex);
|
|
1407
|
-
}
|
|
1408
|
-
const func = this.getFunctionExpressionAtPosition(position);
|
|
1409
|
-
if (func) {
|
|
1410
|
-
//look through local variables first
|
|
1411
|
-
//find any variable with this name
|
|
1412
|
-
for (const symbol of func.symbolTable.getOwnSymbols()) {
|
|
1413
|
-
//we found a variable declaration with this token text
|
|
1414
|
-
if (symbol.name.toLowerCase() === textToSearchFor) {
|
|
1415
|
-
const uri = util_1.util.pathToUri(this.srcPath);
|
|
1416
|
-
results.push(util_1.util.createLocation(uri, symbol.range));
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
|
-
if (this.parser.tokenFollows(token, TokenKind_1.TokenKind.Goto)) {
|
|
1420
|
-
for (const label of func.labelStatements) {
|
|
1421
|
-
if (label.tokens.identifier.text.toLocaleLowerCase() === textToSearchFor) {
|
|
1422
|
-
const uri = util_1.util.pathToUri(this.srcPath);
|
|
1423
|
-
results.push(util_1.util.createLocation(uri, label.tokens.identifier.range));
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
const filesSearched = new Set();
|
|
1429
|
-
//look through all files in scope for matches
|
|
1430
|
-
for (const scope of scopesForFile) {
|
|
1431
|
-
for (const file of scope.getAllFiles()) {
|
|
1432
|
-
if ((0, reflection_1.isXmlFile)(file) || filesSearched.has(file)) {
|
|
1433
|
-
continue;
|
|
1434
|
-
}
|
|
1435
|
-
filesSearched.add(file);
|
|
1436
|
-
if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind) === TokenKind_1.TokenKind.Dot && file.parseMode === Parser_1.ParseMode.BrighterScript) {
|
|
1437
|
-
results.push(...this.getClassMemberDefinitions(textToSearchFor, file));
|
|
1438
|
-
const namespaceDefinition = this.getNamespaceDefinitions(token, file);
|
|
1439
|
-
if (namespaceDefinition) {
|
|
1440
|
-
results.push(namespaceDefinition);
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
const statementHandler = (statement) => {
|
|
1444
|
-
if (statement.getName(this.parseMode).toLowerCase() === textToSearchFor) {
|
|
1445
|
-
const uri = util_1.util.pathToUri(file.srcPath);
|
|
1446
|
-
results.push(util_1.util.createLocation(uri, statement.range));
|
|
1447
|
-
}
|
|
1448
|
-
};
|
|
1449
|
-
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
1450
|
-
FunctionStatement: statementHandler
|
|
1451
|
-
}), {
|
|
1452
|
-
walkMode: visitors_1.WalkMode.visitStatements
|
|
1453
|
-
});
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
return results;
|
|
1457
|
-
}
|
|
1458
880
|
getClassMemberDefinitions(textToSearchFor, file) {
|
|
1459
881
|
let results = [];
|
|
1460
882
|
//get class fields and members
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
results.push(util_1.util.createLocation(util_1.util.pathToUri(file.srcPath), statement.range));
|
|
1470
|
-
}
|
|
883
|
+
const statementHandler = (statement) => {
|
|
884
|
+
if (statement.getName(file.parseMode).toLowerCase() === textToSearchFor) {
|
|
885
|
+
results.push(util_1.util.createLocation(util_1.util.pathToUri(file.srcPath), statement.range));
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
const fieldStatementHandler = (statement) => {
|
|
889
|
+
if (statement.tokens.name.text.toLowerCase() === textToSearchFor) {
|
|
890
|
+
results.push(util_1.util.createLocation(util_1.util.pathToUri(file.srcPath), statement.range));
|
|
1471
891
|
}
|
|
892
|
+
};
|
|
893
|
+
file.parser.ast.walk((0, visitors_1.createVisitor)({
|
|
894
|
+
MethodStatement: statementHandler,
|
|
895
|
+
FieldStatement: fieldStatementHandler
|
|
1472
896
|
}), {
|
|
1473
897
|
walkMode: visitors_1.WalkMode.visitStatements
|
|
1474
898
|
});
|
|
1475
899
|
return results;
|
|
1476
900
|
}
|
|
1477
|
-
getSignatureHelpForNamespaceMethods(callableName, dottedGetText, scope) {
|
|
1478
|
-
var _a;
|
|
1479
|
-
if (!dottedGetText) {
|
|
1480
|
-
return [];
|
|
1481
|
-
}
|
|
1482
|
-
let resultsMap = new Map();
|
|
1483
|
-
for (let [, namespace] of scope.namespaceLookup) {
|
|
1484
|
-
//completionName = "NameA."
|
|
1485
|
-
//completionName = "NameA.Na
|
|
1486
|
-
//NameA
|
|
1487
|
-
//NameA.NameB
|
|
1488
|
-
//NameA.NameB.NameC
|
|
1489
|
-
if (namespace.fullName.toLowerCase() === dottedGetText.toLowerCase()) {
|
|
1490
|
-
//add function and class statement completions
|
|
1491
|
-
for (let stmt of namespace.statements) {
|
|
1492
|
-
if ((0, reflection_1.isFunctionStatement)(stmt) && stmt.name.text.toLowerCase() === callableName.toLowerCase()) {
|
|
1493
|
-
const result = (_a = namespace.file) === null || _a === void 0 ? void 0 : _a.getSignatureHelpForStatement(stmt);
|
|
1494
|
-
if (!resultsMap.has(result.key)) {
|
|
1495
|
-
resultsMap.set(result.key, result);
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
}
|
|
1500
|
-
}
|
|
1501
|
-
return [...resultsMap.values()];
|
|
1502
|
-
}
|
|
1503
|
-
getSignatureHelpForStatement(statement) {
|
|
1504
|
-
if (!(0, reflection_1.isFunctionStatement)(statement) && !(0, reflection_1.isMethodStatement)(statement)) {
|
|
1505
|
-
return undefined;
|
|
1506
|
-
}
|
|
1507
|
-
const func = statement.func;
|
|
1508
|
-
const funcStartPosition = func.range.start;
|
|
1509
|
-
// Get function comments in reverse order
|
|
1510
|
-
let currentToken = this.parser.getTokenAt(funcStartPosition);
|
|
1511
|
-
let functionComments = [];
|
|
1512
|
-
while (currentToken) {
|
|
1513
|
-
currentToken = this.parser.getPreviousToken(currentToken);
|
|
1514
|
-
if (!currentToken) {
|
|
1515
|
-
break;
|
|
1516
|
-
}
|
|
1517
|
-
if (currentToken.range.start.line + 1 < funcStartPosition.line) {
|
|
1518
|
-
if (functionComments.length === 0) {
|
|
1519
|
-
break;
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
const kind = currentToken.kind;
|
|
1523
|
-
if (kind === TokenKind_1.TokenKind.Comment) {
|
|
1524
|
-
// Strip off common leading characters to make it easier to read
|
|
1525
|
-
const commentText = currentToken.text.replace(/^[' *\/]+/, '');
|
|
1526
|
-
functionComments.unshift(commentText);
|
|
1527
|
-
}
|
|
1528
|
-
else if (kind === TokenKind_1.TokenKind.Newline) {
|
|
1529
|
-
if (functionComments.length === 0) {
|
|
1530
|
-
continue;
|
|
1531
|
-
}
|
|
1532
|
-
// if we already had a new line as the last token then exit out
|
|
1533
|
-
if (functionComments[0] === currentToken.text) {
|
|
1534
|
-
break;
|
|
1535
|
-
}
|
|
1536
|
-
functionComments.unshift(currentToken.text);
|
|
1537
|
-
}
|
|
1538
|
-
else {
|
|
1539
|
-
break;
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
const documentation = functionComments.join('').trim();
|
|
1543
|
-
const lines = util_1.util.splitIntoLines(this.fileContents);
|
|
1544
|
-
let key = statement.name.text + documentation;
|
|
1545
|
-
const params = [];
|
|
1546
|
-
for (const param of func.parameters) {
|
|
1547
|
-
params.push(vscode_languageserver_2.ParameterInformation.create(param.name.text));
|
|
1548
|
-
key += param.name.text;
|
|
1549
|
-
}
|
|
1550
|
-
const label = util_1.util.getTextForRange(lines, func.functionDeclarationRange).trim();
|
|
1551
|
-
const signature = vscode_languageserver_2.SignatureInformation.create(label, documentation, ...params);
|
|
1552
|
-
const index = 1;
|
|
1553
|
-
return { key: key, signature: signature, index: index };
|
|
1554
|
-
}
|
|
1555
901
|
getClassMethod(classStatement, name, walkParents = true) {
|
|
1556
902
|
var _a;
|
|
1557
|
-
//TODO - would like to write this with
|
|
1558
|
-
//TODO types - this could be solved with symbolTable?
|
|
903
|
+
//TODO - would like to write this with getClassHieararchy; but got stuck on working out the scopes to use... :(
|
|
1559
904
|
let statement;
|
|
1560
905
|
const statementHandler = (e) => {
|
|
1561
|
-
if (!statement && e.name.text.toLowerCase() === name.toLowerCase()) {
|
|
906
|
+
if (!statement && e.tokens.name.text.toLowerCase() === name.toLowerCase()) {
|
|
1562
907
|
statement = e;
|
|
1563
908
|
}
|
|
1564
909
|
};
|
|
@@ -1581,45 +926,55 @@ class BrsFile {
|
|
|
1581
926
|
}
|
|
1582
927
|
return statement;
|
|
1583
928
|
}
|
|
1584
|
-
getClassSignatureHelp(classStatement) {
|
|
1585
|
-
const classConstructor = this.getClassMethod(classStatement, 'new');
|
|
1586
|
-
let sigHelp = classConstructor ? this.getSignatureHelpForStatement(classConstructor) : undefined;
|
|
1587
|
-
if (sigHelp) {
|
|
1588
|
-
sigHelp.key = classStatement.getName(Parser_1.ParseMode.BrighterScript);
|
|
1589
|
-
sigHelp.signature.label = sigHelp.signature.label.replace(/(function|sub) new/, sigHelp.key);
|
|
1590
|
-
}
|
|
1591
|
-
return sigHelp;
|
|
1592
|
-
}
|
|
1593
929
|
getReferences(position) {
|
|
1594
|
-
const callSiteToken = this.
|
|
930
|
+
const callSiteToken = this.getTokenAt(position);
|
|
1595
931
|
let locations = [];
|
|
1596
932
|
const searchFor = callSiteToken.text.toLowerCase();
|
|
1597
933
|
const scopes = this.program.getScopesForFile(this);
|
|
1598
934
|
for (const scope of scopes) {
|
|
1599
935
|
const processedFiles = new Set();
|
|
1600
936
|
for (const file of scope.getAllFiles()) {
|
|
1601
|
-
if ((0, reflection_1.
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
locations.push(util_1.util.createLocation(util_1.util.pathToUri(file.srcPath), e.range));
|
|
937
|
+
if ((0, reflection_1.isBrsFile)(file) && !processedFiles.has(file)) {
|
|
938
|
+
processedFiles.add(file);
|
|
939
|
+
file.ast.walk((0, visitors_1.createVisitor)({
|
|
940
|
+
VariableExpression: (e) => {
|
|
941
|
+
if (e.tokens.name.text.toLowerCase() === searchFor) {
|
|
942
|
+
locations.push(util_1.util.createLocation(util_1.util.pathToUri(file.srcPath), e.range));
|
|
943
|
+
}
|
|
1609
944
|
}
|
|
1610
|
-
}
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
}
|
|
945
|
+
}), {
|
|
946
|
+
walkMode: visitors_1.WalkMode.visitExpressionsRecursive
|
|
947
|
+
});
|
|
948
|
+
}
|
|
1614
949
|
}
|
|
1615
950
|
}
|
|
1616
951
|
return locations;
|
|
1617
952
|
}
|
|
953
|
+
/**
|
|
954
|
+
* Generate the code, map, and typedef for this file
|
|
955
|
+
*/
|
|
956
|
+
serialize() {
|
|
957
|
+
const result = {};
|
|
958
|
+
const transpiled = this.transpile();
|
|
959
|
+
if (typeof transpiled.code === 'string') {
|
|
960
|
+
result.code = transpiled.code;
|
|
961
|
+
}
|
|
962
|
+
if (transpiled.map) {
|
|
963
|
+
result.map = transpiled.map.toString();
|
|
964
|
+
}
|
|
965
|
+
//generate the typedef (if this is not a typedef itself, and if enabled)
|
|
966
|
+
if (!this.isTypedef && this.program.options.emitDefinitions) {
|
|
967
|
+
result.typedef = this.getTypedef();
|
|
968
|
+
}
|
|
969
|
+
return result;
|
|
970
|
+
}
|
|
1618
971
|
/**
|
|
1619
972
|
* Convert the brightscript/brighterscript source code into valid brightscript
|
|
1620
973
|
*/
|
|
1621
974
|
transpile() {
|
|
975
|
+
var _a;
|
|
1622
976
|
const state = new BrsTranspileState_1.BrsTranspileState(this);
|
|
977
|
+
state.editor = (_a = this.editor) !== null && _a !== void 0 ? _a : new Editor_1.Editor();
|
|
1623
978
|
let transpileResult;
|
|
1624
979
|
if (this.needsTranspiled) {
|
|
1625
980
|
transpileResult = new source_map_1.SourceNode(null, null, state.srcPath, this.ast.transpile(state));
|
|
@@ -1632,8 +987,11 @@ class BrsFile {
|
|
|
1632
987
|
//simple SourceNode wrapping the entire file to simplify the logic below
|
|
1633
988
|
transpileResult = new source_map_1.SourceNode(null, null, state.srcPath, this.fileContents);
|
|
1634
989
|
}
|
|
1635
|
-
//
|
|
1636
|
-
|
|
990
|
+
//if we created an editor for this flow, undo the edits now
|
|
991
|
+
if (!this.editor) {
|
|
992
|
+
//undo any AST edits that the transpile cycle has made
|
|
993
|
+
state.editor.undoAll();
|
|
994
|
+
}
|
|
1637
995
|
if (this.program.options.sourceMap) {
|
|
1638
996
|
return new source_map_1.SourceNode(null, null, null, [
|
|
1639
997
|
transpileResult,
|
|
@@ -1648,6 +1006,206 @@ class BrsFile {
|
|
|
1648
1006
|
};
|
|
1649
1007
|
}
|
|
1650
1008
|
}
|
|
1009
|
+
processSymbolInformation() {
|
|
1010
|
+
this.validationSegmenter.processTree(this.ast);
|
|
1011
|
+
this.program.addFileSymbolInfo(this);
|
|
1012
|
+
}
|
|
1013
|
+
getValidationSegments(changedSymbols) {
|
|
1014
|
+
const segments = this.validationSegmenter.getSegments(changedSymbols);
|
|
1015
|
+
return segments;
|
|
1016
|
+
}
|
|
1017
|
+
get requiredSymbols() {
|
|
1018
|
+
return this.cache.getOrAdd(`requiredSymbols`, () => {
|
|
1019
|
+
var _a, _b, _c;
|
|
1020
|
+
const allNeededSymbolSets = this.validationSegmenter.unresolvedSegmentsSymbols.values();
|
|
1021
|
+
const requiredSymbols = [];
|
|
1022
|
+
const addedSymbols = new Map();
|
|
1023
|
+
addedSymbols.set(SymbolTable_1.SymbolTypeFlag.runtime, new Set());
|
|
1024
|
+
addedSymbols.set(SymbolTable_1.SymbolTypeFlag.typetime, new Set());
|
|
1025
|
+
for (const setOfSymbols of allNeededSymbolSets) {
|
|
1026
|
+
for (const symbol of setOfSymbols) {
|
|
1027
|
+
const fullSymbolKey = symbol.typeChain.map(tce => tce.name).join('.').toLowerCase();
|
|
1028
|
+
for (const flag of [SymbolTable_1.SymbolTypeFlag.runtime, SymbolTable_1.SymbolTypeFlag.typetime]) {
|
|
1029
|
+
// eslint-disable-next-line no-bitwise
|
|
1030
|
+
if (symbol.flags & flag) {
|
|
1031
|
+
if ((_a = this.providedSymbols.symbolMap.get(flag)) === null || _a === void 0 ? void 0 : _a.has(fullSymbolKey)) {
|
|
1032
|
+
// this catches namespaced things
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
if (!((_b = addedSymbols.get(flag)) === null || _b === void 0 ? void 0 : _b.has(fullSymbolKey))) {
|
|
1036
|
+
requiredSymbols.push(symbol);
|
|
1037
|
+
(_c = addedSymbols.get(flag)) === null || _c === void 0 ? void 0 : _c.add(fullSymbolKey);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return requiredSymbols;
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
get providedSymbols() {
|
|
1047
|
+
var _a;
|
|
1048
|
+
return (_a = this.cache) === null || _a === void 0 ? void 0 : _a.getOrAdd(`providedSymbols`, () => {
|
|
1049
|
+
return this.getProvidedSymbols();
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
getProvidedSymbols() {
|
|
1053
|
+
var _a, _b;
|
|
1054
|
+
const symbolMap = new Map();
|
|
1055
|
+
const runTimeSymbolMap = new Map();
|
|
1056
|
+
const typeTimeSymbolMap = new Map();
|
|
1057
|
+
const tablesToGetSymbolsFrom = [{
|
|
1058
|
+
table: this.parser.symbolTable
|
|
1059
|
+
}];
|
|
1060
|
+
for (const namespaceStatement of this._cachedLookups.namespaceStatements) {
|
|
1061
|
+
tablesToGetSymbolsFrom.push({
|
|
1062
|
+
table: namespaceStatement.body.getSymbolTable(),
|
|
1063
|
+
namePrefixLower: namespaceStatement.getName(Parser_1.ParseMode.BrighterScript).toLowerCase()
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
for (const symbolTable of tablesToGetSymbolsFrom) {
|
|
1067
|
+
const runTimeSymbols = symbolTable.table.getOwnSymbols(SymbolTable_1.SymbolTypeFlag.runtime);
|
|
1068
|
+
const typeTimeSymbols = symbolTable.table.getOwnSymbols(SymbolTable_1.SymbolTypeFlag.typetime);
|
|
1069
|
+
for (const symbol of runTimeSymbols) {
|
|
1070
|
+
if (!(0, reflection_1.isAnyReferenceType)(symbol.type)) {
|
|
1071
|
+
const symbolNameLower = symbolTable.namePrefixLower
|
|
1072
|
+
? `${symbolTable.namePrefixLower}.${symbol.name.toLowerCase()}`
|
|
1073
|
+
: symbol.name.toLowerCase();
|
|
1074
|
+
runTimeSymbolMap.set(symbolNameLower, symbol);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
for (const symbol of typeTimeSymbols) {
|
|
1078
|
+
if (!(0, reflection_1.isAnyReferenceType)(symbol.type)) {
|
|
1079
|
+
const symbolNameLower = symbolTable.namePrefixLower
|
|
1080
|
+
? `${symbolTable.namePrefixLower}.${symbol.name.toLowerCase()}`
|
|
1081
|
+
: symbol.name.toLowerCase();
|
|
1082
|
+
typeTimeSymbolMap.set(symbolNameLower, symbol);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
symbolMap.set(SymbolTable_1.SymbolTypeFlag.runtime, runTimeSymbolMap);
|
|
1087
|
+
symbolMap.set(SymbolTable_1.SymbolTypeFlag.typetime, typeTimeSymbolMap);
|
|
1088
|
+
const changes = new Map();
|
|
1089
|
+
changes.set(SymbolTable_1.SymbolTypeFlag.runtime, new Set());
|
|
1090
|
+
changes.set(SymbolTable_1.SymbolTypeFlag.typetime, new Set());
|
|
1091
|
+
const previouslyProvidedSymbols = (_a = this.program.getFileSymbolInfo(this)) === null || _a === void 0 ? void 0 : _a.provides.symbolMap;
|
|
1092
|
+
const previousSymbolsChecked = new Map();
|
|
1093
|
+
previousSymbolsChecked.set(SymbolTable_1.SymbolTypeFlag.runtime, new Set());
|
|
1094
|
+
previousSymbolsChecked.set(SymbolTable_1.SymbolTypeFlag.typetime, new Set());
|
|
1095
|
+
for (const flag of [SymbolTable_1.SymbolTypeFlag.runtime, SymbolTable_1.SymbolTypeFlag.typetime]) {
|
|
1096
|
+
const newSymbolMapForFlag = symbolMap.get(flag);
|
|
1097
|
+
const oldSymbolMapForFlag = previouslyProvidedSymbols === null || previouslyProvidedSymbols === void 0 ? void 0 : previouslyProvidedSymbols.get(flag);
|
|
1098
|
+
const previousSymbolsCheckedForFlag = previousSymbolsChecked.get(flag);
|
|
1099
|
+
const changesForFlag = changes.get(flag);
|
|
1100
|
+
if (!oldSymbolMapForFlag) {
|
|
1101
|
+
for (const key of newSymbolMapForFlag.keys()) {
|
|
1102
|
+
changesForFlag.add(key);
|
|
1103
|
+
}
|
|
1104
|
+
continue;
|
|
1105
|
+
}
|
|
1106
|
+
for (const [symbolKey, symbol] of newSymbolMapForFlag) {
|
|
1107
|
+
const symbolType = symbol.type;
|
|
1108
|
+
const previousType = (_b = oldSymbolMapForFlag === null || oldSymbolMapForFlag === void 0 ? void 0 : oldSymbolMapForFlag.get(symbolKey)) === null || _b === void 0 ? void 0 : _b.type;
|
|
1109
|
+
previousSymbolsCheckedForFlag.add(symbolKey);
|
|
1110
|
+
if (!previousType) {
|
|
1111
|
+
changesForFlag.add(symbolKey);
|
|
1112
|
+
continue;
|
|
1113
|
+
}
|
|
1114
|
+
const data = {};
|
|
1115
|
+
if (!symbolType.isEqual(previousType, data)) {
|
|
1116
|
+
changesForFlag.add(symbolKey);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
for (const [symbolKey] of previouslyProvidedSymbols.get(flag)) {
|
|
1120
|
+
if (!previousSymbolsCheckedForFlag.has(symbolKey)) {
|
|
1121
|
+
changesForFlag.add(symbolKey);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
return {
|
|
1126
|
+
symbolMap: symbolMap,
|
|
1127
|
+
changes: changes
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
markSegmentAsValidated(node) {
|
|
1131
|
+
this.validationSegmenter.markSegmentAsValidated(node);
|
|
1132
|
+
}
|
|
1133
|
+
getNamespaceLookupObject() {
|
|
1134
|
+
if (!this.isValidated) {
|
|
1135
|
+
return this.buildNamespaceLookup();
|
|
1136
|
+
}
|
|
1137
|
+
return this.cache.getOrAdd(`namespaceLookup`, () => {
|
|
1138
|
+
const nsLookup = this.buildNamespaceLookup();
|
|
1139
|
+
return nsLookup;
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
buildNamespaceLookup() {
|
|
1143
|
+
const namespaceLookup = new Map();
|
|
1144
|
+
for (let namespaceStatement of this._cachedLookups.namespaceStatements) {
|
|
1145
|
+
let nameParts = namespaceStatement.getNameParts();
|
|
1146
|
+
let loopName = null;
|
|
1147
|
+
let lowerLoopName = null;
|
|
1148
|
+
let parentNameLower = null;
|
|
1149
|
+
//ensure each namespace section is represented in the results
|
|
1150
|
+
//(so if the namespace name is A.B.C, this will make an entry for "A", an entry for "A.B", and an entry for "A.B.C"
|
|
1151
|
+
for (let i = 0; i < nameParts.length; i++) {
|
|
1152
|
+
let part = nameParts[i];
|
|
1153
|
+
let lowerPartName = part.text.toLowerCase();
|
|
1154
|
+
if (i === 0) {
|
|
1155
|
+
loopName = part.text;
|
|
1156
|
+
lowerLoopName = lowerPartName;
|
|
1157
|
+
}
|
|
1158
|
+
else {
|
|
1159
|
+
parentNameLower = lowerLoopName;
|
|
1160
|
+
loopName += '.' + part.text;
|
|
1161
|
+
lowerLoopName += '.' + lowerPartName;
|
|
1162
|
+
}
|
|
1163
|
+
if (!namespaceLookup.has(lowerLoopName)) {
|
|
1164
|
+
namespaceLookup.set(lowerLoopName, {
|
|
1165
|
+
isTopLevel: i === 0,
|
|
1166
|
+
file: this,
|
|
1167
|
+
fullName: loopName,
|
|
1168
|
+
fullNameLower: lowerLoopName,
|
|
1169
|
+
parentNameLower: parentNameLower,
|
|
1170
|
+
nameParts: nameParts.slice(0, i),
|
|
1171
|
+
nameRange: namespaceStatement.nameExpression.range,
|
|
1172
|
+
lastPartName: part.text,
|
|
1173
|
+
lastPartNameLower: lowerPartName,
|
|
1174
|
+
functionStatements: new Map(),
|
|
1175
|
+
namespaceStatements: [],
|
|
1176
|
+
namespaces: new Map(),
|
|
1177
|
+
classStatements: new Map(),
|
|
1178
|
+
enumStatements: new Map(),
|
|
1179
|
+
constStatements: new Map(),
|
|
1180
|
+
statements: [],
|
|
1181
|
+
// the aggregate symbol table should have no parent. It should include just the symbols of the namespace.
|
|
1182
|
+
symbolTable: new SymbolTable_1.SymbolTable(`Namespace Aggregate: '${loopName}'`)
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
let ns = namespaceLookup.get(lowerLoopName);
|
|
1187
|
+
ns.namespaceStatements.push(namespaceStatement);
|
|
1188
|
+
ns.statements.push(...namespaceStatement.body.statements);
|
|
1189
|
+
for (let statement of namespaceStatement.body.statements) {
|
|
1190
|
+
if ((0, reflection_1.isClassStatement)(statement) && statement.tokens.name) {
|
|
1191
|
+
ns.classStatements.set(statement.tokens.name.text.toLowerCase(), statement);
|
|
1192
|
+
}
|
|
1193
|
+
else if ((0, reflection_1.isFunctionStatement)(statement) && statement.tokens.name) {
|
|
1194
|
+
ns.functionStatements.set(statement.tokens.name.text.toLowerCase(), statement);
|
|
1195
|
+
}
|
|
1196
|
+
else if ((0, reflection_1.isEnumStatement)(statement) && statement.fullName) {
|
|
1197
|
+
ns.enumStatements.set(statement.fullName.toLowerCase(), statement);
|
|
1198
|
+
}
|
|
1199
|
+
else if ((0, reflection_1.isConstStatement)(statement) && statement.fullName) {
|
|
1200
|
+
ns.constStatements.set(statement.fullName.toLowerCase(), statement);
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
// Merges all the symbol tables of the namespace statements into the new symbol table created above.
|
|
1204
|
+
// Set those symbol tables to have this new merged table as a parent
|
|
1205
|
+
ns.symbolTable.mergeSymbolTable(namespaceStatement.body.getSymbolTable());
|
|
1206
|
+
}
|
|
1207
|
+
return namespaceLookup;
|
|
1208
|
+
}
|
|
1651
1209
|
getTypedef() {
|
|
1652
1210
|
const state = new BrsTranspileState_1.BrsTranspileState(this);
|
|
1653
1211
|
const typedef = this.ast.getTypedef(state);
|
|
@@ -1655,30 +1213,14 @@ class BrsFile {
|
|
|
1655
1213
|
return programNode.toString();
|
|
1656
1214
|
}
|
|
1657
1215
|
dispose() {
|
|
1658
|
-
var _a
|
|
1216
|
+
var _a;
|
|
1659
1217
|
(_a = this._parser) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
1660
|
-
//unsubscribe from any DependencyGraph subscriptions
|
|
1661
|
-
(_b = this.unsubscribeFromDependencyGraph) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
1662
1218
|
//deleting these properties result in lower memory usage (garbage collection is magic!)
|
|
1663
1219
|
delete this.fileContents;
|
|
1664
1220
|
delete this._parser;
|
|
1665
|
-
delete this.
|
|
1666
|
-
delete this.
|
|
1221
|
+
delete this._functionScopes;
|
|
1222
|
+
delete this.scopesByFunc;
|
|
1667
1223
|
}
|
|
1668
1224
|
}
|
|
1669
1225
|
exports.BrsFile = BrsFile;
|
|
1670
|
-
/**
|
|
1671
|
-
* List of completions for all valid keywords/reserved words.
|
|
1672
|
-
* Build this list once because it won't change for the lifetime of this process
|
|
1673
|
-
*/
|
|
1674
|
-
exports.KeywordCompletions = Object.keys(TokenKind_1.Keywords)
|
|
1675
|
-
//remove any keywords with whitespace
|
|
1676
|
-
.filter(x => !x.includes(' '))
|
|
1677
|
-
//create completions
|
|
1678
|
-
.map(x => {
|
|
1679
|
-
return {
|
|
1680
|
-
label: x,
|
|
1681
|
-
kind: vscode_languageserver_2.CompletionItemKind.Keyword
|
|
1682
|
-
};
|
|
1683
|
-
});
|
|
1684
1226
|
//# sourceMappingURL=BrsFile.js.map
|