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/parser/Parser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ParseMode = exports.Parser = void 0;
|
|
4
4
|
const Token_1 = require("../lexer/Token");
|
|
5
5
|
const Lexer_1 = require("../lexer/Lexer");
|
|
6
6
|
const TokenKind_1 = require("../lexer/TokenKind");
|
|
@@ -10,14 +10,8 @@ const util_1 = require("../util");
|
|
|
10
10
|
const Expression_1 = require("./Expression");
|
|
11
11
|
const Logger_1 = require("../Logger");
|
|
12
12
|
const reflection_1 = require("../astUtils/reflection");
|
|
13
|
-
const visitors_1 = require("../astUtils/visitors");
|
|
14
13
|
const creators_1 = require("../astUtils/creators");
|
|
15
|
-
const Cache_1 = require("../Cache");
|
|
16
14
|
const SymbolTable_1 = require("../SymbolTable");
|
|
17
|
-
const DynamicType_1 = require("../types/DynamicType");
|
|
18
|
-
const ArrayType_1 = require("../types/ArrayType");
|
|
19
|
-
const helpers_1 = require("../types/helpers");
|
|
20
|
-
const ObjectType_1 = require("../types/ObjectType");
|
|
21
15
|
class Parser {
|
|
22
16
|
constructor() {
|
|
23
17
|
/**
|
|
@@ -27,12 +21,7 @@ class Parser {
|
|
|
27
21
|
/**
|
|
28
22
|
* The list of statements for the parsed file
|
|
29
23
|
*/
|
|
30
|
-
this.ast = new Statement_1.Body([]);
|
|
31
|
-
/**
|
|
32
|
-
* The top-level symbol table for this file. Things like top-level namespaces, non-namespaced classes, enums, interfaces, and functions beling here.
|
|
33
|
-
*/
|
|
34
|
-
this.symbolTable = new SymbolTable_1.SymbolTable(undefined, `File Parser`);
|
|
35
|
-
this._references = new References();
|
|
24
|
+
this.ast = new Statement_1.Body({ statements: [] });
|
|
36
25
|
this.globalTerminators = [];
|
|
37
26
|
/**
|
|
38
27
|
* An array of CallExpression for the current function body
|
|
@@ -42,48 +31,11 @@ class Parser {
|
|
|
42
31
|
get statements() {
|
|
43
32
|
return this.ast.statements;
|
|
44
33
|
}
|
|
45
|
-
get currentSymbolTable() {
|
|
46
|
-
var _a, _b, _c, _d;
|
|
47
|
-
return (_d = (_b = (_a = this.currentFunctionExpression) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : (_c = this.currentNamespace) === null || _c === void 0 ? void 0 : _c.symbolTable) !== null && _d !== void 0 ? _d : this.symbolTable;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* References for significant statements/expressions in the parser.
|
|
51
|
-
* These are initially extracted during parse-time to improve performance, but will also be dynamically regenerated if need be.
|
|
52
|
-
*
|
|
53
|
-
* If a plugin modifies the AST, then the plugin should call Parser#invalidateReferences() to force this object to refresh
|
|
54
|
-
*/
|
|
55
|
-
get references() {
|
|
56
|
-
//build the references object if it's missing.
|
|
57
|
-
if (!this._references) {
|
|
58
|
-
this.findReferences();
|
|
59
|
-
}
|
|
60
|
-
return this._references;
|
|
61
|
-
}
|
|
62
34
|
/**
|
|
63
|
-
*
|
|
35
|
+
* The top-level symbol table for the body of this file.
|
|
64
36
|
*/
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
}
|
|
68
|
-
addPropertyHints(item) {
|
|
69
|
-
if ((0, Token_1.isToken)(item)) {
|
|
70
|
-
const name = item.text;
|
|
71
|
-
this._references.propertyHints[name.toLowerCase()] = name;
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
for (const member of item.elements) {
|
|
75
|
-
if (!(0, reflection_1.isCommentStatement)(member)) {
|
|
76
|
-
const name = member.keyToken.text;
|
|
77
|
-
if (!name.startsWith('"')) {
|
|
78
|
-
this._references.propertyHints[name.toLowerCase()] = name;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
get currentNamespaceName() {
|
|
85
|
-
var _a;
|
|
86
|
-
return (_a = this.currentNamespace) === null || _a === void 0 ? void 0 : _a.nameExpression;
|
|
37
|
+
get symbolTable() {
|
|
38
|
+
return this.ast.symbolTable;
|
|
87
39
|
}
|
|
88
40
|
/**
|
|
89
41
|
* Get the currently active global terminators
|
|
@@ -125,11 +77,13 @@ class Parser {
|
|
|
125
77
|
this.namespaceAndFunctionDepth = 0;
|
|
126
78
|
this.pendingAnnotations = [];
|
|
127
79
|
this.ast = this.body();
|
|
80
|
+
//now that we've built the AST, link every node to its parent
|
|
81
|
+
this.ast.link();
|
|
128
82
|
return this;
|
|
129
83
|
}
|
|
130
84
|
body() {
|
|
131
85
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
132
|
-
let body = new Statement_1.Body([]
|
|
86
|
+
let body = new Statement_1.Body({ statements: [] });
|
|
133
87
|
if (this.tokens.length > 0) {
|
|
134
88
|
this.consumeStatementSeparators(true);
|
|
135
89
|
try {
|
|
@@ -190,7 +144,7 @@ class Parser {
|
|
|
190
144
|
declaration() {
|
|
191
145
|
try {
|
|
192
146
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
193
|
-
return this.
|
|
147
|
+
return this.functionDeclaration(false);
|
|
194
148
|
}
|
|
195
149
|
if (this.checkLibrary()) {
|
|
196
150
|
return this.libraryStatement();
|
|
@@ -236,75 +190,125 @@ class Parser {
|
|
|
236
190
|
return identifier;
|
|
237
191
|
}
|
|
238
192
|
enumMemberStatement() {
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
193
|
+
const statement = new Statement_1.EnumMemberStatement({});
|
|
194
|
+
statement.tokens.name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
242
195
|
//look for `= SOME_EXPRESSION`
|
|
243
196
|
if (this.check(TokenKind_1.TokenKind.Equal)) {
|
|
244
|
-
tokens.
|
|
245
|
-
value = this.expression();
|
|
197
|
+
statement.tokens.equals = this.advance();
|
|
198
|
+
statement.value = this.expression();
|
|
246
199
|
}
|
|
247
|
-
return
|
|
200
|
+
return statement;
|
|
248
201
|
}
|
|
249
202
|
/**
|
|
250
|
-
* Create a new
|
|
203
|
+
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
|
|
251
204
|
*/
|
|
252
|
-
interfaceFieldStatement() {
|
|
205
|
+
interfaceFieldStatement(optionalKeyword) {
|
|
253
206
|
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
254
207
|
let asToken;
|
|
255
|
-
let
|
|
256
|
-
//look for `as SOME_TYPE`
|
|
208
|
+
let typeExpression;
|
|
257
209
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
258
|
-
asToken = this.
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
210
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
211
|
+
}
|
|
212
|
+
return new Statement_1.InterfaceFieldStatement({ name: name, as: asToken, typeExpression: typeExpression, optional: optionalKeyword });
|
|
213
|
+
}
|
|
214
|
+
consumeAsTokenAndTypeExpression(ignoreDiagnostics = false) {
|
|
215
|
+
let asToken = this.consumeToken(TokenKind_1.TokenKind.As);
|
|
216
|
+
let typeExpression;
|
|
217
|
+
if (asToken) {
|
|
218
|
+
//if there's nothing after the `as`, add a diagnostic and continue
|
|
219
|
+
if (this.checkEndOfStatement()) {
|
|
220
|
+
if (!ignoreDiagnostics) {
|
|
221
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
|
|
222
|
+
}
|
|
223
|
+
//consume the statement separator
|
|
224
|
+
this.consumeStatementSeparators();
|
|
225
|
+
}
|
|
226
|
+
else if (this.peek().kind !== TokenKind_1.TokenKind.Identifier && !this.checkAny(...TokenKind_1.DeclarableTypes, ...TokenKind_1.AllowedTypeIdentifiers)) {
|
|
227
|
+
if (!ignoreDiagnostics) {
|
|
228
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
typeExpression = this.typeExpression();
|
|
263
233
|
}
|
|
264
234
|
}
|
|
265
|
-
return
|
|
235
|
+
return [asToken, typeExpression];
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration()`
|
|
239
|
+
*/
|
|
240
|
+
interfaceMethodStatement(optionalKeyword) {
|
|
241
|
+
const functionType = this.advance();
|
|
242
|
+
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
243
|
+
const leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.LeftParen), TokenKind_1.TokenKind.LeftParen);
|
|
244
|
+
let params = [];
|
|
245
|
+
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
246
|
+
do {
|
|
247
|
+
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
248
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
249
|
+
}
|
|
250
|
+
params.push(this.functionParameter());
|
|
251
|
+
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
252
|
+
}
|
|
253
|
+
const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
|
|
254
|
+
// let asToken = null as Token;
|
|
255
|
+
// let returnTypeExpression: TypeExpression;
|
|
256
|
+
let asToken;
|
|
257
|
+
let returnTypeExpression;
|
|
258
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
259
|
+
[asToken, returnTypeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
260
|
+
}
|
|
261
|
+
return new Statement_1.InterfaceMethodStatement({
|
|
262
|
+
functionType: functionType,
|
|
263
|
+
name: name,
|
|
264
|
+
leftParen: leftParen,
|
|
265
|
+
params: params,
|
|
266
|
+
rightParen: rightParen,
|
|
267
|
+
as: asToken,
|
|
268
|
+
returnTypeExpression: returnTypeExpression,
|
|
269
|
+
optional: optionalKeyword
|
|
270
|
+
});
|
|
266
271
|
}
|
|
267
272
|
interfaceDeclaration() {
|
|
268
273
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
269
274
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
270
275
|
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
|
|
271
|
-
|
|
272
|
-
let nameToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('interface'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
276
|
+
const nameToken = this.identifier(...this.allowedLocalIdentifiers);
|
|
273
277
|
let extendsToken;
|
|
274
278
|
let parentInterfaceName;
|
|
275
279
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
276
280
|
extendsToken = this.advance();
|
|
277
|
-
|
|
281
|
+
if (this.checkEndOfStatement()) {
|
|
282
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(extendsToken.text)), { range: extendsToken.range }));
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
parentInterfaceName = this.typeExpression();
|
|
286
|
+
}
|
|
278
287
|
}
|
|
279
288
|
this.consumeStatementSeparators();
|
|
280
289
|
//gather up all interface members (Fields, Methods)
|
|
281
290
|
let body = [];
|
|
282
291
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
283
292
|
try {
|
|
284
|
-
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
285
|
-
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
286
|
-
break;
|
|
287
|
-
}
|
|
288
293
|
let decl;
|
|
289
294
|
//collect leading annotations
|
|
290
295
|
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
291
296
|
this.annotationExpression();
|
|
292
297
|
}
|
|
298
|
+
const optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
|
|
293
299
|
//fields
|
|
294
|
-
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.
|
|
300
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkAnyNext(TokenKind_1.TokenKind.As, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
301
|
+
decl = this.interfaceFieldStatement(optionalKeyword);
|
|
302
|
+
//field with name = 'optional'
|
|
303
|
+
}
|
|
304
|
+
else if (optionalKeyword && this.checkAny(TokenKind_1.TokenKind.As, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
305
|
+
//rewind one place, so that 'optional' is the field name
|
|
306
|
+
this.current--;
|
|
295
307
|
decl = this.interfaceFieldStatement();
|
|
296
308
|
//methods (function/sub keyword followed by opening paren)
|
|
297
309
|
}
|
|
298
|
-
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.
|
|
299
|
-
|
|
300
|
-
hasName: true,
|
|
301
|
-
hasBody: false,
|
|
302
|
-
hasEnd: false,
|
|
303
|
-
onlyCallableAsMember: true
|
|
304
|
-
});
|
|
305
|
-
decl = new Statement_1.InterfaceMethodStatement(functionStatement.name, functionStatement.func);
|
|
306
|
-
//refer to this statement as parent of the expression
|
|
307
|
-
functionStatement.func.functionStatement = decl;
|
|
310
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
311
|
+
decl = this.interfaceMethodStatement(optionalKeyword);
|
|
308
312
|
//comments
|
|
309
313
|
}
|
|
310
314
|
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
@@ -314,6 +318,10 @@ class Parser {
|
|
|
314
318
|
this.consumePendingAnnotations(decl);
|
|
315
319
|
body.push(decl);
|
|
316
320
|
}
|
|
321
|
+
else {
|
|
322
|
+
//we didn't find a declaration...flag tokens until next line
|
|
323
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
324
|
+
}
|
|
317
325
|
}
|
|
318
326
|
catch (e) {
|
|
319
327
|
//throw out any failed members and move on to the next line
|
|
@@ -321,24 +329,30 @@ class Parser {
|
|
|
321
329
|
}
|
|
322
330
|
//ensure statement separator
|
|
323
331
|
this.consumeStatementSeparators();
|
|
332
|
+
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
333
|
+
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
324
336
|
}
|
|
325
337
|
//consume the final `end interface` token
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
338
|
+
const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
|
|
339
|
+
const statement = new Statement_1.InterfaceStatement({
|
|
340
|
+
interface: interfaceToken,
|
|
341
|
+
name: nameToken,
|
|
342
|
+
extends: extendsToken,
|
|
343
|
+
parentInterfaceName: parentInterfaceName,
|
|
344
|
+
body: body,
|
|
345
|
+
endInterface: endInterfaceToken
|
|
346
|
+
});
|
|
332
347
|
this.exitAnnotationBlock(parentAnnotations);
|
|
333
348
|
return statement;
|
|
334
349
|
}
|
|
335
350
|
enumDeclaration() {
|
|
351
|
+
const result = new Statement_1.EnumStatement({ name: {}, body: [] });
|
|
336
352
|
this.warnIfNotBrighterScriptMode('enum declarations');
|
|
337
353
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
|
|
341
|
-
tokens.name = this.tryIdentifier();
|
|
354
|
+
result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
|
|
355
|
+
result.tokens.name = this.tryIdentifier(...this.allowedLocalIdentifiers);
|
|
342
356
|
this.consumeStatementSeparators();
|
|
343
357
|
//gather up all members
|
|
344
358
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
@@ -358,7 +372,7 @@ class Parser {
|
|
|
358
372
|
}
|
|
359
373
|
if (decl) {
|
|
360
374
|
this.consumePendingAnnotations(decl);
|
|
361
|
-
body.push(decl);
|
|
375
|
+
result.body.push(decl);
|
|
362
376
|
}
|
|
363
377
|
else {
|
|
364
378
|
//we didn't find a declaration...flag tokens until next line
|
|
@@ -377,12 +391,7 @@ class Parser {
|
|
|
377
391
|
}
|
|
378
392
|
}
|
|
379
393
|
//consume the final `end interface` token
|
|
380
|
-
tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
|
|
381
|
-
const result = new Statement_1.EnumStatement(tokens, body, this.currentNamespaceName);
|
|
382
|
-
if (tokens.name) {
|
|
383
|
-
this.currentSymbolTable.addSymbol(tokens.name.text, tokens.name.range, result.getThisBscType());
|
|
384
|
-
}
|
|
385
|
-
this._references.enumStatements.push(result);
|
|
394
|
+
result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
|
|
386
395
|
this.exitAnnotationBlock(parentAnnotations);
|
|
387
396
|
return result;
|
|
388
397
|
}
|
|
@@ -400,7 +409,12 @@ class Parser {
|
|
|
400
409
|
//see if the class inherits from parent
|
|
401
410
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
402
411
|
extendsKeyword = this.advance();
|
|
403
|
-
|
|
412
|
+
if (this.checkEndOfStatement()) {
|
|
413
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(extendsKeyword.text)), { range: extendsKeyword.range }));
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
parentClassName = this.typeExpression();
|
|
417
|
+
}
|
|
404
418
|
}
|
|
405
419
|
//ensure statement separator
|
|
406
420
|
this.consumeStatementSeparators();
|
|
@@ -423,16 +437,19 @@ class Parser {
|
|
|
423
437
|
}
|
|
424
438
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
425
439
|
if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) || (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkNext(TokenKind_1.TokenKind.LeftParen))) {
|
|
426
|
-
const
|
|
440
|
+
const funcDeclaration = this.functionDeclaration(false, false);
|
|
427
441
|
//if we have an overrides keyword AND this method is called 'new', that's not allowed
|
|
428
|
-
if (overrideKeyword &&
|
|
442
|
+
if (overrideKeyword && funcDeclaration.tokens.name.text.toLowerCase() === 'new') {
|
|
429
443
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
|
|
430
444
|
}
|
|
431
|
-
decl = new Statement_1.MethodStatement(
|
|
445
|
+
decl = new Statement_1.MethodStatement({
|
|
446
|
+
modifiers: accessModifier,
|
|
447
|
+
name: funcDeclaration.tokens.name,
|
|
448
|
+
func: funcDeclaration.func,
|
|
449
|
+
override: overrideKeyword
|
|
450
|
+
});
|
|
432
451
|
//refer to this statement as parent of the expression
|
|
433
|
-
|
|
434
|
-
//cache the range property so that plugins can't affect it
|
|
435
|
-
decl.cacheRange();
|
|
452
|
+
funcDeclaration.func.functionStatement = decl;
|
|
436
453
|
//fields
|
|
437
454
|
}
|
|
438
455
|
else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
@@ -462,26 +479,50 @@ class Parser {
|
|
|
462
479
|
if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
|
|
463
480
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
|
|
464
481
|
}
|
|
465
|
-
const result = new Statement_1.ClassStatement(
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
482
|
+
const result = new Statement_1.ClassStatement({
|
|
483
|
+
class: classKeyword,
|
|
484
|
+
name: className,
|
|
485
|
+
body: body,
|
|
486
|
+
endClass: endingKeyword,
|
|
487
|
+
extends: extendsKeyword,
|
|
488
|
+
parentClassName: parentClassName
|
|
489
|
+
});
|
|
470
490
|
this.exitAnnotationBlock(parentAnnotations);
|
|
471
491
|
return result;
|
|
472
492
|
}
|
|
473
493
|
fieldDeclaration(accessModifier) {
|
|
494
|
+
let optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
|
|
495
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
496
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
497
|
+
if (this.checkAnyNext(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Newline)) {
|
|
498
|
+
// as <EOL>
|
|
499
|
+
// `as` is the field name
|
|
500
|
+
}
|
|
501
|
+
else if (this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
502
|
+
// as as ____
|
|
503
|
+
// first `as` is the field name
|
|
504
|
+
}
|
|
505
|
+
else if (optionalKeyword) {
|
|
506
|
+
// optional as ____
|
|
507
|
+
// optional is the field name, `as` starts type
|
|
508
|
+
// rewind current token
|
|
509
|
+
optionalKeyword = null;
|
|
510
|
+
this.current--;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
// no name after `optional` ... optional is the name
|
|
516
|
+
// rewind current token
|
|
517
|
+
optionalKeyword = null;
|
|
518
|
+
this.current--;
|
|
519
|
+
}
|
|
474
520
|
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
475
521
|
let asToken;
|
|
476
|
-
let
|
|
522
|
+
let fieldTypeExpression;
|
|
477
523
|
//look for `as SOME_TYPE`
|
|
478
524
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
479
|
-
asToken = this.
|
|
480
|
-
fieldTypeExpr = this.typeExpression();
|
|
481
|
-
//no field type specified
|
|
482
|
-
if (!fieldTypeExpr.isValidType(this.options.mode)) {
|
|
483
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedValidTypeToFollowAsKeyword()), { range: this.peek().range }));
|
|
484
|
-
}
|
|
525
|
+
[asToken, fieldTypeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
485
526
|
}
|
|
486
527
|
let initialValue;
|
|
487
528
|
let equal;
|
|
@@ -490,43 +531,30 @@ class Parser {
|
|
|
490
531
|
equal = this.advance();
|
|
491
532
|
initialValue = this.expression();
|
|
492
533
|
}
|
|
493
|
-
return new Statement_1.FieldStatement(
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
this._references.functionStatements.push(result);
|
|
503
|
-
}
|
|
504
|
-
// Add the transpiled name for namespace functions
|
|
505
|
-
// to consider an edge case when defining namespaces in .bs files
|
|
506
|
-
// and using them in .brs files.
|
|
507
|
-
if (result.func.namespaceName) {
|
|
508
|
-
const transpiledNamespaceFunctionName = result.getName(ParseMode.BrightScript);
|
|
509
|
-
const funcType = result.func.getFunctionType();
|
|
510
|
-
funcType.setName(transpiledNamespaceFunctionName);
|
|
511
|
-
this.symbolTable.addSymbol(transpiledNamespaceFunctionName, result.name.range, funcType);
|
|
512
|
-
}
|
|
513
|
-
return result;
|
|
514
|
-
}
|
|
534
|
+
return new Statement_1.FieldStatement({
|
|
535
|
+
accessModifier: accessModifier,
|
|
536
|
+
name: name,
|
|
537
|
+
as: asToken,
|
|
538
|
+
typeExpression: fieldTypeExpression,
|
|
539
|
+
equals: equal,
|
|
540
|
+
initialValue: initialValue,
|
|
541
|
+
optional: optionalKeyword
|
|
542
|
+
});
|
|
515
543
|
}
|
|
516
|
-
functionDeclaration(
|
|
517
|
-
var _a
|
|
544
|
+
functionDeclaration(isAnonymous, checkIdentifier = true, onlyCallableAsMember = false) {
|
|
545
|
+
var _a;
|
|
518
546
|
let previousCallExpressions = this.callExpressions;
|
|
519
547
|
this.callExpressions = [];
|
|
520
548
|
try {
|
|
521
549
|
//track depth to help certain statements need to know if they are contained within a function body
|
|
522
550
|
this.namespaceAndFunctionDepth++;
|
|
523
|
-
let
|
|
551
|
+
let functionType;
|
|
524
552
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
525
|
-
|
|
553
|
+
functionType = this.advance();
|
|
526
554
|
}
|
|
527
555
|
else {
|
|
528
556
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
|
|
529
|
-
|
|
557
|
+
functionType = {
|
|
530
558
|
isReserved: true,
|
|
531
559
|
kind: TokenKind_1.TokenKind.Function,
|
|
532
560
|
text: 'function',
|
|
@@ -535,33 +563,34 @@ class Parser {
|
|
|
535
563
|
start: this.peek().range.start,
|
|
536
564
|
end: this.peek().range.start
|
|
537
565
|
},
|
|
538
|
-
leadingWhitespace: ''
|
|
566
|
+
leadingWhitespace: '',
|
|
567
|
+
leadingTrivia: []
|
|
539
568
|
};
|
|
540
569
|
}
|
|
541
|
-
let isSub = (
|
|
542
|
-
let
|
|
570
|
+
let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
|
|
571
|
+
let functionTypeText = isSub ? 'sub' : 'function';
|
|
543
572
|
let name;
|
|
544
573
|
let leftParen;
|
|
545
|
-
if (
|
|
546
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(
|
|
574
|
+
if (isAnonymous) {
|
|
575
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
547
576
|
}
|
|
548
577
|
else {
|
|
549
|
-
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(
|
|
550
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(
|
|
578
|
+
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
579
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
551
580
|
//prevent functions from ending with type designators
|
|
552
581
|
let lastChar = name.text[name.text.length - 1];
|
|
553
582
|
if (['$', '%', '!', '#', '&'].includes(lastChar)) {
|
|
554
583
|
//don't throw this error; let the parser continue
|
|
555
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(
|
|
584
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
|
|
556
585
|
}
|
|
557
|
-
//flag functions with keywords for names (only for standard functions
|
|
558
|
-
if (
|
|
586
|
+
//flag functions with keywords for names (only for standard functions)
|
|
587
|
+
if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
|
|
559
588
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
560
589
|
}
|
|
561
590
|
}
|
|
562
591
|
let params = [];
|
|
563
592
|
let asToken;
|
|
564
|
-
let
|
|
593
|
+
let typeExpression;
|
|
565
594
|
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
566
595
|
do {
|
|
567
596
|
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
@@ -572,69 +601,57 @@ class Parser {
|
|
|
572
601
|
}
|
|
573
602
|
let rightParen = this.advance();
|
|
574
603
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
575
|
-
asToken = this.
|
|
576
|
-
typeExpr = this.typeExpression();
|
|
577
|
-
if (!typeExpr.isValidType(this.options.mode)) {
|
|
578
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeExpr.getText()) !== null && _a !== void 0 ? _a : '')), { range: typeExpr.range }));
|
|
579
|
-
}
|
|
604
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
580
605
|
}
|
|
581
606
|
params.reduce((haveFoundOptional, param) => {
|
|
582
607
|
if (haveFoundOptional && !param.defaultValue) {
|
|
583
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.requiredParameterMayNotFollowOptionalParameter(param.name.text)), { range: param.range }));
|
|
608
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.requiredParameterMayNotFollowOptionalParameter(param.tokens.name.text)), { range: param.range }));
|
|
584
609
|
}
|
|
585
610
|
return haveFoundOptional || !!param.defaultValue;
|
|
586
611
|
}, false);
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
612
|
+
this.consumeStatementSeparators(true);
|
|
613
|
+
let func = new Expression_1.FunctionExpression({
|
|
614
|
+
parameters: params,
|
|
615
|
+
body: undefined,
|
|
616
|
+
functionType: functionType,
|
|
617
|
+
endFunctionType: undefined,
|
|
618
|
+
leftParen: leftParen,
|
|
619
|
+
rightParen: rightParen,
|
|
620
|
+
as: asToken,
|
|
621
|
+
returnTypeExpression: typeExpression
|
|
622
|
+
});
|
|
623
|
+
//support ending the function with `end sub` OR `end function`
|
|
624
|
+
func.body = this.block();
|
|
625
|
+
//if the parser was unable to produce a block, make an empty one so the AST makes some sense...
|
|
626
|
+
if (!func.body) {
|
|
627
|
+
func.body = new Statement_1.Block({
|
|
628
|
+
statements: [],
|
|
629
|
+
startingRange: util_1.util.createRangeFromPositions(func.range.start, func.range.start)
|
|
630
|
+
});
|
|
590
631
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
leftParen, rightParen, asToken, typeExpr, //return type
|
|
596
|
-
this.currentFunctionExpression, this.currentNamespaceName, funcExprParentSymbolTable);
|
|
597
|
-
//if there is a parent function, register this function with the parent
|
|
598
|
-
if (this.currentFunctionExpression) {
|
|
599
|
-
this.currentFunctionExpression.childFunctionExpressions.push(func);
|
|
600
|
-
}
|
|
601
|
-
// add the function to the relevant symbol tables
|
|
602
|
-
if (!options.onlyCallableAsMember && name) {
|
|
603
|
-
const funcType = func.getFunctionType();
|
|
604
|
-
funcType.setName(name.text);
|
|
605
|
-
// add the function as declared to the current symbol table
|
|
606
|
-
this.currentSymbolTable.addSymbol(name.text, name.range, funcType);
|
|
607
|
-
}
|
|
608
|
-
this._references.functionExpressions.push(func);
|
|
609
|
-
if (options.hasBody) {
|
|
610
|
-
let previousFunctionExpression = this.currentFunctionExpression;
|
|
611
|
-
this.currentFunctionExpression = func;
|
|
612
|
-
//make sure to restore the currentFunctionExpression even if the body block fails to parse
|
|
613
|
-
try {
|
|
614
|
-
//support ending the function with `end sub` OR `end function`
|
|
615
|
-
func.body = this.block();
|
|
616
|
-
}
|
|
617
|
-
finally {
|
|
618
|
-
this.currentFunctionExpression = previousFunctionExpression;
|
|
619
|
-
}
|
|
620
|
-
if (!func.body) {
|
|
621
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionKeywordText)), { range: this.peek().range }));
|
|
622
|
-
throw this.lastDiagnosticAsError();
|
|
623
|
-
}
|
|
632
|
+
func.body.symbolTable = new SymbolTable_1.SymbolTable(`Block: Function '${(_a = name === null || name === void 0 ? void 0 : name.text) !== null && _a !== void 0 ? _a : ''}'`, () => func.getSymbolTable());
|
|
633
|
+
if (!func.body) {
|
|
634
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionTypeText)), { range: this.peek().range }));
|
|
635
|
+
throw this.lastDiagnosticAsError();
|
|
624
636
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionKeywordText, func.end.text)), { range: this.peek().range }));
|
|
633
|
-
}
|
|
637
|
+
// consume 'end sub' or 'end function'
|
|
638
|
+
func.tokens.endFunctionType = this.advance();
|
|
639
|
+
let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
|
|
640
|
+
//if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
|
|
641
|
+
//add an error but don't hard-fail so the AST can continue more gracefully
|
|
642
|
+
if (func.tokens.endFunctionType.kind !== expectedEndKind) {
|
|
643
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionTypeText, func.tokens.endFunctionType.text)), { range: func.tokens.endFunctionType.range }));
|
|
634
644
|
}
|
|
635
645
|
func.callExpressions = this.callExpressions;
|
|
636
|
-
|
|
637
|
-
|
|
646
|
+
if (isAnonymous) {
|
|
647
|
+
return func;
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
let result = new Statement_1.FunctionStatement({ name: name, func: func });
|
|
651
|
+
func.symbolTable.name += `: '${name === null || name === void 0 ? void 0 : name.text}'`;
|
|
652
|
+
func.functionStatement = result;
|
|
653
|
+
return result;
|
|
654
|
+
}
|
|
638
655
|
}
|
|
639
656
|
finally {
|
|
640
657
|
this.namespaceAndFunctionDepth--;
|
|
@@ -647,65 +664,62 @@ class Parser {
|
|
|
647
664
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
|
|
648
665
|
throw this.lastDiagnosticAsError();
|
|
649
666
|
}
|
|
650
|
-
|
|
651
|
-
|
|
667
|
+
let name = this.advance();
|
|
668
|
+
// force the name into an identifier so the AST makes some sense
|
|
669
|
+
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
670
|
+
let typeExpression;
|
|
652
671
|
let defaultValue;
|
|
653
|
-
let
|
|
672
|
+
let equalToken;
|
|
654
673
|
// parse argument default value
|
|
655
|
-
if (this.
|
|
656
|
-
equalsToken = this.previous();
|
|
674
|
+
if ((equalToken = this.consumeTokenIf(TokenKind_1.TokenKind.Equal))) {
|
|
657
675
|
// it seems any expression is allowed here -- including ones that operate on other arguments!
|
|
658
|
-
defaultValue = this.expression();
|
|
676
|
+
defaultValue = this.expression(false);
|
|
659
677
|
}
|
|
660
678
|
let asToken = null;
|
|
661
679
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
662
|
-
asToken = this.
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
typeInContext = typeExpr.type;
|
|
672
|
-
}
|
|
673
|
-
else if (defaultValue) {
|
|
674
|
-
typeInContext = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
|
|
675
|
-
if ((0, reflection_1.isInvalidType)(typeInContext)) {
|
|
676
|
-
typeInContext = new DynamicType_1.DynamicType();
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
else {
|
|
680
|
-
typeInContext = new DynamicType_1.DynamicType();
|
|
681
|
-
}
|
|
682
|
-
return new Expression_1.FunctionParameterExpression(name, typeInContext, equalsToken, defaultValue, asToken, typeExpr, this.currentNamespaceName);
|
|
680
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
681
|
+
}
|
|
682
|
+
return new Expression_1.FunctionParameterExpression({
|
|
683
|
+
name: name,
|
|
684
|
+
equals: equalToken,
|
|
685
|
+
defaultValue: defaultValue,
|
|
686
|
+
as: asToken,
|
|
687
|
+
typeExpression: typeExpression
|
|
688
|
+
});
|
|
683
689
|
}
|
|
684
690
|
assignment() {
|
|
685
|
-
let name = this.
|
|
691
|
+
let name = this.advance();
|
|
686
692
|
//add diagnostic if name is a reserved word that cannot be used as an identifier
|
|
687
693
|
if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
|
|
688
694
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
689
695
|
}
|
|
696
|
+
let asToken;
|
|
697
|
+
let typeExpression;
|
|
698
|
+
//look for `as SOME_TYPE`
|
|
699
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
700
|
+
this.warnIfNotBrighterScriptMode('typed assignment');
|
|
701
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
702
|
+
}
|
|
690
703
|
let operator = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOperatorAfterIdentifier(TokenKind_1.AssignmentOperators, name.text), ...TokenKind_1.AssignmentOperators);
|
|
691
704
|
let value = this.expression();
|
|
692
705
|
let result;
|
|
693
706
|
if (operator.kind === TokenKind_1.TokenKind.Equal) {
|
|
694
|
-
result = new Statement_1.AssignmentStatement(
|
|
707
|
+
result = new Statement_1.AssignmentStatement({ equals: operator, name: name, value: value, as: asToken, typeExpression: typeExpression });
|
|
695
708
|
}
|
|
696
709
|
else {
|
|
697
|
-
const nameExpression = new Expression_1.VariableExpression(name
|
|
698
|
-
result = new Statement_1.AssignmentStatement(
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
710
|
+
const nameExpression = new Expression_1.VariableExpression({ name: name });
|
|
711
|
+
result = new Statement_1.AssignmentStatement({
|
|
712
|
+
equals: operator,
|
|
713
|
+
name: name,
|
|
714
|
+
value: new Expression_1.BinaryExpression({
|
|
715
|
+
left: nameExpression,
|
|
716
|
+
operator: operator,
|
|
717
|
+
right: value
|
|
718
|
+
}),
|
|
719
|
+
as: asToken,
|
|
720
|
+
typeExpression: typeExpression
|
|
721
|
+
});
|
|
722
|
+
}
|
|
709
723
|
return result;
|
|
710
724
|
}
|
|
711
725
|
checkLibrary() {
|
|
@@ -774,6 +788,10 @@ class Parser {
|
|
|
774
788
|
if (this.check(TokenKind_1.TokenKind.Goto)) {
|
|
775
789
|
return this.gotoStatement();
|
|
776
790
|
}
|
|
791
|
+
//the continue keyword (followed by `for`, `while`, or a statement separator)
|
|
792
|
+
if (this.check(TokenKind_1.TokenKind.Continue) && this.checkAnyNext(TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
793
|
+
return this.continueStatement();
|
|
794
|
+
}
|
|
777
795
|
//does this line look like a label? (i.e. `someIdentifier:` )
|
|
778
796
|
if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
|
|
779
797
|
try {
|
|
@@ -789,9 +807,31 @@ class Parser {
|
|
|
789
807
|
// BrightScript is like python, in that variables can be declared without a `var`,
|
|
790
808
|
// `let`, (...) keyword. As such, we must check the token *after* an identifier to figure
|
|
791
809
|
// out what to do with it.
|
|
792
|
-
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)
|
|
793
|
-
this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
|
|
794
|
-
|
|
810
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
|
|
811
|
+
if (this.checkAnyNext(...TokenKind_1.AssignmentOperators)) {
|
|
812
|
+
return this.assignment();
|
|
813
|
+
}
|
|
814
|
+
else if (this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
815
|
+
// may be a typed assignment
|
|
816
|
+
const backtrack = this.current;
|
|
817
|
+
let validTypeExpression = false;
|
|
818
|
+
try {
|
|
819
|
+
// skip the identifier, and check for valid type expression
|
|
820
|
+
this.advance();
|
|
821
|
+
const parts = this.consumeAsTokenAndTypeExpression(true);
|
|
822
|
+
validTypeExpression = !!((parts === null || parts === void 0 ? void 0 : parts[0]) && (parts === null || parts === void 0 ? void 0 : parts[1]));
|
|
823
|
+
}
|
|
824
|
+
catch (e) {
|
|
825
|
+
// ignore any errors
|
|
826
|
+
}
|
|
827
|
+
finally {
|
|
828
|
+
this.current = backtrack;
|
|
829
|
+
}
|
|
830
|
+
if (validTypeExpression) {
|
|
831
|
+
// there is a valid 'as' and type expression
|
|
832
|
+
return this.assignment();
|
|
833
|
+
}
|
|
834
|
+
}
|
|
795
835
|
}
|
|
796
836
|
//some BrighterScript keywords are allowed as a local identifiers, so we need to check for them AFTER the assignment check
|
|
797
837
|
if (this.check(TokenKind_1.TokenKind.Interface)) {
|
|
@@ -824,7 +864,12 @@ class Parser {
|
|
|
824
864
|
else {
|
|
825
865
|
endWhile = this.advance();
|
|
826
866
|
}
|
|
827
|
-
return new Statement_1.WhileStatement({
|
|
867
|
+
return new Statement_1.WhileStatement({
|
|
868
|
+
while: whileKeyword,
|
|
869
|
+
endWhile: endWhile,
|
|
870
|
+
condition: condition,
|
|
871
|
+
body: whileBlock
|
|
872
|
+
});
|
|
828
873
|
}
|
|
829
874
|
exitWhile() {
|
|
830
875
|
let keyword = this.advance();
|
|
@@ -859,11 +904,20 @@ class Parser {
|
|
|
859
904
|
}
|
|
860
905
|
// WARNING: BrightScript doesn't delete the loop initial value after a for/to loop! It just
|
|
861
906
|
// stays around in scope with whatever value it was when the loop exited.
|
|
862
|
-
return new Statement_1.ForStatement(
|
|
907
|
+
return new Statement_1.ForStatement({
|
|
908
|
+
for: forToken,
|
|
909
|
+
counterDeclaration: initializer,
|
|
910
|
+
to: toToken,
|
|
911
|
+
finalValue: finalValue,
|
|
912
|
+
body: body,
|
|
913
|
+
endFor: endForToken,
|
|
914
|
+
step: stepToken,
|
|
915
|
+
increment: incrementExpression
|
|
916
|
+
});
|
|
863
917
|
}
|
|
864
918
|
forEachStatement() {
|
|
865
919
|
let forEach = this.advance();
|
|
866
|
-
let name = this.
|
|
920
|
+
let name = this.advance();
|
|
867
921
|
let maybeIn = this.peek();
|
|
868
922
|
if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
|
|
869
923
|
this.advance();
|
|
@@ -877,12 +931,6 @@ class Parser {
|
|
|
877
931
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
|
|
878
932
|
throw this.lastDiagnosticAsError();
|
|
879
933
|
}
|
|
880
|
-
let itemType = new DynamicType_1.DynamicType();
|
|
881
|
-
const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
|
|
882
|
-
if ((0, reflection_1.isArrayType)(targetType)) {
|
|
883
|
-
itemType = targetType.getDefaultType();
|
|
884
|
-
}
|
|
885
|
-
this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
|
|
886
934
|
this.consumeStatementSeparators();
|
|
887
935
|
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
888
936
|
if (!body) {
|
|
@@ -890,7 +938,14 @@ class Parser {
|
|
|
890
938
|
throw this.lastDiagnosticAsError();
|
|
891
939
|
}
|
|
892
940
|
let endFor = this.advance();
|
|
893
|
-
return new Statement_1.ForEachStatement(
|
|
941
|
+
return new Statement_1.ForEachStatement({
|
|
942
|
+
forEach: forEach,
|
|
943
|
+
in: maybeIn,
|
|
944
|
+
endFor: endFor,
|
|
945
|
+
item: name,
|
|
946
|
+
target: target,
|
|
947
|
+
body: body
|
|
948
|
+
});
|
|
894
949
|
}
|
|
895
950
|
exitFor() {
|
|
896
951
|
let keyword = this.advance();
|
|
@@ -901,7 +956,7 @@ class Parser {
|
|
|
901
956
|
//then this comment should be treated as a single-line comment
|
|
902
957
|
let prev = this.previous();
|
|
903
958
|
if ((prev === null || prev === void 0 ? void 0 : prev.range.end.line) === this.peek().range.start.line) {
|
|
904
|
-
return new Statement_1.CommentStatement([this.advance()]);
|
|
959
|
+
return new Statement_1.CommentStatement({ comments: [this.advance()] });
|
|
905
960
|
}
|
|
906
961
|
else {
|
|
907
962
|
let comments = [this.advance()];
|
|
@@ -909,25 +964,19 @@ class Parser {
|
|
|
909
964
|
this.advance();
|
|
910
965
|
comments.push(this.advance());
|
|
911
966
|
}
|
|
912
|
-
return new Statement_1.CommentStatement(comments);
|
|
967
|
+
return new Statement_1.CommentStatement({ comments: comments });
|
|
913
968
|
}
|
|
914
969
|
}
|
|
915
970
|
namespaceStatement() {
|
|
916
971
|
this.warnIfNotBrighterScriptMode('namespace');
|
|
917
972
|
let keyword = this.advance();
|
|
918
|
-
if (!this.isAtRootLevel()) {
|
|
919
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.keywordMustBeDeclaredAtRootLevel('namespace')), { range: keyword.range }));
|
|
920
|
-
}
|
|
921
973
|
this.namespaceAndFunctionDepth++;
|
|
922
|
-
let name = this.
|
|
974
|
+
let name = this.identifyingExpression();
|
|
923
975
|
//set the current namespace name
|
|
924
|
-
let result = new Statement_1.NamespaceStatement(keyword, name,
|
|
925
|
-
this.currentNamespace = result;
|
|
976
|
+
let result = new Statement_1.NamespaceStatement({ namespace: keyword, nameExpression: name, body: null });
|
|
926
977
|
this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
|
|
927
978
|
let body = this.body();
|
|
928
979
|
this.globalTerminators.pop();
|
|
929
|
-
//unset the current namespace name
|
|
930
|
-
this.currentNamespace = undefined;
|
|
931
980
|
let endKeyword;
|
|
932
981
|
if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
|
|
933
982
|
endKeyword = this.advance();
|
|
@@ -938,25 +987,23 @@ class Parser {
|
|
|
938
987
|
}
|
|
939
988
|
this.namespaceAndFunctionDepth--;
|
|
940
989
|
result.body = body;
|
|
941
|
-
result.
|
|
942
|
-
this._references.namespaceStatements.push(result);
|
|
990
|
+
result.tokens.endNamespace = endKeyword;
|
|
943
991
|
//cache the range property so that plugins can't affect it
|
|
944
992
|
result.cacheRange();
|
|
945
|
-
|
|
946
|
-
this.symbolTable.addSymbol(result.name.split('.')[0], result.nameExpression.range, DynamicType_1.DynamicType.instance);
|
|
947
|
-
}
|
|
993
|
+
result.body.symbolTable.name += `: namespace '${result.name}'`;
|
|
948
994
|
return result;
|
|
949
995
|
}
|
|
950
996
|
/**
|
|
951
997
|
* Get an expression with identifiers separated by periods. Useful for namespaces and class extends
|
|
952
998
|
*/
|
|
953
|
-
|
|
954
|
-
|
|
999
|
+
identifyingExpression(allowedTokenKinds) {
|
|
1000
|
+
allowedTokenKinds = allowedTokenKinds !== null && allowedTokenKinds !== void 0 ? allowedTokenKinds : this.allowedLocalIdentifiers;
|
|
1001
|
+
let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...allowedTokenKinds);
|
|
955
1002
|
let expr;
|
|
956
1003
|
if (firstIdentifier) {
|
|
957
1004
|
// force it into an identifier so the AST makes some sense
|
|
958
1005
|
firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
959
|
-
const varExpr = new Expression_1.VariableExpression(firstIdentifier
|
|
1006
|
+
const varExpr = new Expression_1.VariableExpression({ name: firstIdentifier });
|
|
960
1007
|
expr = varExpr;
|
|
961
1008
|
//consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
|
|
962
1009
|
while (this.check(TokenKind_1.TokenKind.Dot)) {
|
|
@@ -964,16 +1011,16 @@ class Parser {
|
|
|
964
1011
|
if (!dot) {
|
|
965
1012
|
break;
|
|
966
1013
|
}
|
|
967
|
-
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...
|
|
1014
|
+
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...allowedTokenKinds, ...TokenKind_1.AllowedProperties);
|
|
968
1015
|
if (!identifier) {
|
|
969
1016
|
break;
|
|
970
1017
|
}
|
|
971
1018
|
// force it into an identifier so the AST makes some sense
|
|
972
1019
|
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
973
|
-
expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
|
|
1020
|
+
expr = new Expression_1.DottedGetExpression({ obj: expr, name: identifier, dot: dot });
|
|
974
1021
|
}
|
|
975
1022
|
}
|
|
976
|
-
return
|
|
1023
|
+
return expr;
|
|
977
1024
|
}
|
|
978
1025
|
/**
|
|
979
1026
|
* Add an 'unexpected token' diagnostic for any token found between current and the first stopToken found.
|
|
@@ -986,8 +1033,8 @@ class Parser {
|
|
|
986
1033
|
}
|
|
987
1034
|
/**
|
|
988
1035
|
* Consume tokens until one of the `stopTokenKinds` is encountered
|
|
989
|
-
* @param tokenKinds
|
|
990
|
-
* @
|
|
1036
|
+
* @param stopTokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
|
|
1037
|
+
* @returns - the list of tokens consumed, EXCLUDING the `stopTokenKind` (you can use `this.peek()` to see which one it was)
|
|
991
1038
|
*/
|
|
992
1039
|
consumeUntil(...stopTokenKinds) {
|
|
993
1040
|
let result = [];
|
|
@@ -1006,12 +1053,9 @@ class Parser {
|
|
|
1006
1053
|
const statement = new Statement_1.ConstStatement({
|
|
1007
1054
|
const: constToken,
|
|
1008
1055
|
name: nameToken,
|
|
1009
|
-
equals: equalToken
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
this.currentSymbolTable.addSymbol(nameToken.text, nameToken.range, getBscTypeFromExpression(expression));
|
|
1013
|
-
}
|
|
1014
|
-
this._references.constStatements.push(statement);
|
|
1056
|
+
equals: equalToken,
|
|
1057
|
+
value: expression
|
|
1058
|
+
});
|
|
1015
1059
|
return statement;
|
|
1016
1060
|
}
|
|
1017
1061
|
libraryStatement() {
|
|
@@ -1020,15 +1064,15 @@ class Parser {
|
|
|
1020
1064
|
//grab the next token only if it's a string
|
|
1021
1065
|
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
|
|
1022
1066
|
});
|
|
1023
|
-
this._references.libraryStatements.push(libStatement);
|
|
1024
1067
|
return libStatement;
|
|
1025
1068
|
}
|
|
1026
1069
|
importStatement() {
|
|
1027
1070
|
this.warnIfNotBrighterScriptMode('import statements');
|
|
1028
|
-
let importStatement = new Statement_1.ImportStatement(
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1071
|
+
let importStatement = new Statement_1.ImportStatement({
|
|
1072
|
+
import: this.advance(),
|
|
1073
|
+
//grab the next token only if it's a string
|
|
1074
|
+
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral)
|
|
1075
|
+
});
|
|
1032
1076
|
return importStatement;
|
|
1033
1077
|
}
|
|
1034
1078
|
annotationExpression() {
|
|
@@ -1037,15 +1081,13 @@ class Parser {
|
|
|
1037
1081
|
if (identifier) {
|
|
1038
1082
|
identifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
1039
1083
|
}
|
|
1040
|
-
let annotation = new Expression_1.AnnotationExpression(atToken, identifier);
|
|
1084
|
+
let annotation = new Expression_1.AnnotationExpression({ at: atToken, name: identifier });
|
|
1041
1085
|
this.pendingAnnotations.push(annotation);
|
|
1042
1086
|
//optional arguments
|
|
1043
1087
|
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1044
1088
|
let leftParen = this.advance();
|
|
1045
1089
|
annotation.call = this.finishCall(leftParen, annotation, false);
|
|
1046
1090
|
}
|
|
1047
|
-
//cache the range property so that plugins can't affect it
|
|
1048
|
-
annotation.cacheRange();
|
|
1049
1091
|
return annotation;
|
|
1050
1092
|
}
|
|
1051
1093
|
ternaryExpression(test) {
|
|
@@ -1077,13 +1119,23 @@ class Parser {
|
|
|
1077
1119
|
alternate = this.expression();
|
|
1078
1120
|
}
|
|
1079
1121
|
catch (_b) { }
|
|
1080
|
-
return new Expression_1.TernaryExpression(
|
|
1122
|
+
return new Expression_1.TernaryExpression({
|
|
1123
|
+
test: test,
|
|
1124
|
+
questionMark: questionMarkToken,
|
|
1125
|
+
consequent: consequent,
|
|
1126
|
+
colon: colonToken,
|
|
1127
|
+
alternate: alternate
|
|
1128
|
+
});
|
|
1081
1129
|
}
|
|
1082
1130
|
nullCoalescingExpression(test) {
|
|
1083
1131
|
this.warnIfNotBrighterScriptMode('null coalescing operator');
|
|
1084
1132
|
const questionQuestionToken = this.advance();
|
|
1085
1133
|
const alternate = this.expression();
|
|
1086
|
-
return new Expression_1.NullCoalescingExpression(
|
|
1134
|
+
return new Expression_1.NullCoalescingExpression({
|
|
1135
|
+
consequent: test,
|
|
1136
|
+
questionQuestion: questionQuestionToken,
|
|
1137
|
+
alternate: alternate
|
|
1138
|
+
});
|
|
1087
1139
|
}
|
|
1088
1140
|
regexLiteralExpression() {
|
|
1089
1141
|
this.warnIfNotBrighterScriptMode('regular expression literal');
|
|
@@ -1109,16 +1161,16 @@ class Parser {
|
|
|
1109
1161
|
let next = this.peek();
|
|
1110
1162
|
if (next.kind === TokenKind_1.TokenKind.TemplateStringQuasi) {
|
|
1111
1163
|
//a quasi can actually be made up of multiple quasis when it includes char literals
|
|
1112
|
-
currentQuasiExpressionParts.push(new Expression_1.LiteralExpression(next));
|
|
1164
|
+
currentQuasiExpressionParts.push(new Expression_1.LiteralExpression({ value: next }));
|
|
1113
1165
|
this.advance();
|
|
1114
1166
|
}
|
|
1115
1167
|
else if (next.kind === TokenKind_1.TokenKind.EscapedCharCodeLiteral) {
|
|
1116
|
-
currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression(next));
|
|
1168
|
+
currentQuasiExpressionParts.push(new Expression_1.EscapedCharCodeLiteralExpression({ value: next }));
|
|
1117
1169
|
this.advance();
|
|
1118
1170
|
}
|
|
1119
1171
|
else {
|
|
1120
1172
|
//finish up the current quasi
|
|
1121
|
-
quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
|
|
1173
|
+
quasis.push(new Expression_1.TemplateStringQuasiExpression({ expressions: currentQuasiExpressionParts }));
|
|
1122
1174
|
currentQuasiExpressionParts = [];
|
|
1123
1175
|
if (next.kind === TokenKind_1.TokenKind.TemplateStringExpressionBegin) {
|
|
1124
1176
|
this.advance();
|
|
@@ -1136,7 +1188,7 @@ class Parser {
|
|
|
1136
1188
|
}
|
|
1137
1189
|
}
|
|
1138
1190
|
//store the final set of quasis
|
|
1139
|
-
quasis.push(new Expression_1.TemplateStringQuasiExpression(currentQuasiExpressionParts));
|
|
1191
|
+
quasis.push(new Expression_1.TemplateStringQuasiExpression({ expressions: currentQuasiExpressionParts }));
|
|
1140
1192
|
if (this.isAtEnd()) {
|
|
1141
1193
|
//error - missing backtick
|
|
1142
1194
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unterminatedTemplateStringAtEndOfFile()), { range: util_1.util.getRange(openingBacktick, this.peek()) }));
|
|
@@ -1145,10 +1197,21 @@ class Parser {
|
|
|
1145
1197
|
else {
|
|
1146
1198
|
let closingBacktick = this.advance();
|
|
1147
1199
|
if (isTagged) {
|
|
1148
|
-
return new Expression_1.TaggedTemplateStringExpression(
|
|
1200
|
+
return new Expression_1.TaggedTemplateStringExpression({
|
|
1201
|
+
tagName: tagName,
|
|
1202
|
+
openingBacktick: openingBacktick,
|
|
1203
|
+
quasis: quasis,
|
|
1204
|
+
expressions: expressions,
|
|
1205
|
+
closingBacktick: closingBacktick
|
|
1206
|
+
});
|
|
1149
1207
|
}
|
|
1150
1208
|
else {
|
|
1151
|
-
return new Expression_1.TemplateStringExpression(
|
|
1209
|
+
return new Expression_1.TemplateStringExpression({
|
|
1210
|
+
openingBacktick: openingBacktick,
|
|
1211
|
+
quasis: quasis,
|
|
1212
|
+
expressions: expressions,
|
|
1213
|
+
closingBacktick: closingBacktick
|
|
1214
|
+
});
|
|
1152
1215
|
}
|
|
1153
1216
|
}
|
|
1154
1217
|
}
|
|
@@ -1173,7 +1236,7 @@ class Parser {
|
|
|
1173
1236
|
if (exceptionVarToken) {
|
|
1174
1237
|
// force it into an identifier so the AST makes some sense
|
|
1175
1238
|
exceptionVarToken.kind = TokenKind_1.TokenKind.Identifier;
|
|
1176
|
-
catchStmt.exceptionVariable = exceptionVarToken;
|
|
1239
|
+
catchStmt.tokens.exceptionVariable = exceptionVarToken;
|
|
1177
1240
|
}
|
|
1178
1241
|
//ensure statement sepatator
|
|
1179
1242
|
this.consumeStatementSeparators();
|
|
@@ -1184,9 +1247,6 @@ class Parser {
|
|
|
1184
1247
|
else {
|
|
1185
1248
|
statement.tokens.endTry = this.advance();
|
|
1186
1249
|
}
|
|
1187
|
-
if (exceptionVarToken) {
|
|
1188
|
-
this.currentSymbolTable.addSymbol(exceptionVarToken.text, exceptionVarToken.range, DynamicType_1.DynamicType.instance);
|
|
1189
|
-
}
|
|
1190
1250
|
return statement;
|
|
1191
1251
|
}
|
|
1192
1252
|
throwStatement() {
|
|
@@ -1198,7 +1258,7 @@ class Parser {
|
|
|
1198
1258
|
else {
|
|
1199
1259
|
expression = this.expression();
|
|
1200
1260
|
}
|
|
1201
|
-
return new Statement_1.ThrowStatement(throwToken, expression);
|
|
1261
|
+
return new Statement_1.ThrowStatement({ throw: throwToken, expression: expression });
|
|
1202
1262
|
}
|
|
1203
1263
|
dimStatement() {
|
|
1204
1264
|
const dim = this.advance();
|
|
@@ -1229,10 +1289,13 @@ class Parser {
|
|
|
1229
1289
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
|
|
1230
1290
|
}
|
|
1231
1291
|
let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1292
|
+
return new Statement_1.DimStatement({
|
|
1293
|
+
dim: dim,
|
|
1294
|
+
name: identifier,
|
|
1295
|
+
openingSquare: leftSquareBracket,
|
|
1296
|
+
dimensions: expressions,
|
|
1297
|
+
closingSquare: rightSquareBracket
|
|
1298
|
+
});
|
|
1236
1299
|
}
|
|
1237
1300
|
ifStatement() {
|
|
1238
1301
|
// colon before `if` is usually not allowed, unless it's after `then`
|
|
@@ -1342,8 +1405,12 @@ class Parser {
|
|
|
1342
1405
|
if: ifToken,
|
|
1343
1406
|
then: thenToken,
|
|
1344
1407
|
endIf: endIfToken,
|
|
1345
|
-
else: elseToken
|
|
1346
|
-
|
|
1408
|
+
else: elseToken,
|
|
1409
|
+
condition: condition,
|
|
1410
|
+
thenBranch: thenBranch,
|
|
1411
|
+
elseBranch: elseBranch,
|
|
1412
|
+
isInline: isInlineIfThen
|
|
1413
|
+
});
|
|
1347
1414
|
}
|
|
1348
1415
|
//consume a `then` or `else` branch block of an `if` statement
|
|
1349
1416
|
blockConditionalBranch(ifToken) {
|
|
@@ -1414,7 +1481,7 @@ class Parser {
|
|
|
1414
1481
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(colon.text)), { range: colon.range }));
|
|
1415
1482
|
}
|
|
1416
1483
|
}
|
|
1417
|
-
return new Statement_1.Block(statements, startingRange);
|
|
1484
|
+
return new Statement_1.Block({ statements: statements, startingRange: startingRange });
|
|
1418
1485
|
}
|
|
1419
1486
|
expressionStatement(expr) {
|
|
1420
1487
|
let expressionStart = this.peek();
|
|
@@ -1428,18 +1495,15 @@ class Parser {
|
|
|
1428
1495
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.incrementDecrementOperatorsAreNotAllowedAsResultOfFunctionCall()), { range: expressionStart.range }));
|
|
1429
1496
|
throw this.lastDiagnosticAsError();
|
|
1430
1497
|
}
|
|
1431
|
-
const result = new Statement_1.IncrementStatement(expr, operator);
|
|
1432
|
-
this._references.expressions.add(result);
|
|
1498
|
+
const result = new Statement_1.IncrementStatement({ value: expr, operator: operator });
|
|
1433
1499
|
return result;
|
|
1434
1500
|
}
|
|
1435
1501
|
if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
|
|
1436
|
-
return new Statement_1.ExpressionStatement(expr);
|
|
1502
|
+
return new Statement_1.ExpressionStatement({ expression: expr });
|
|
1437
1503
|
}
|
|
1438
|
-
//at this point, it's probably an error. However, we recover a little more gracefully by creating an
|
|
1504
|
+
//at this point, it's probably an error. However, we recover a little more gracefully by creating an inclosing ExpressionStatement
|
|
1439
1505
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()), { range: expressionStart.range }));
|
|
1440
|
-
|
|
1441
|
-
this._references.expressions.add(expr);
|
|
1442
|
-
throw this.lastDiagnosticAsError();
|
|
1506
|
+
return new Statement_1.ExpressionStatement({ expression: expr });
|
|
1443
1507
|
}
|
|
1444
1508
|
setStatement() {
|
|
1445
1509
|
/**
|
|
@@ -1455,19 +1519,31 @@ class Parser {
|
|
|
1455
1519
|
let right = this.expression();
|
|
1456
1520
|
// Create a dotted or indexed "set" based on the left-hand side's type
|
|
1457
1521
|
if ((0, reflection_1.isIndexedGetExpression)(left)) {
|
|
1458
|
-
return new Statement_1.IndexedSetStatement(
|
|
1459
|
-
|
|
1460
|
-
:
|
|
1522
|
+
return new Statement_1.IndexedSetStatement({
|
|
1523
|
+
obj: left.obj,
|
|
1524
|
+
indexes: left.indexes,
|
|
1525
|
+
value: operator.kind === TokenKind_1.TokenKind.Equal
|
|
1526
|
+
? right
|
|
1527
|
+
: new Expression_1.BinaryExpression({ left: left, operator: operator, right: right }),
|
|
1528
|
+
openingSquare: left.tokens.openingSquare,
|
|
1529
|
+
closingSquare: left.tokens.closingSquare
|
|
1530
|
+
});
|
|
1461
1531
|
}
|
|
1462
1532
|
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1533
|
+
return new Statement_1.DottedSetStatement({
|
|
1534
|
+
obj: left.obj,
|
|
1535
|
+
name: left.tokens.name,
|
|
1536
|
+
value: operator.kind === TokenKind_1.TokenKind.Equal
|
|
1537
|
+
? right
|
|
1538
|
+
: new Expression_1.BinaryExpression({ left: left, operator: operator, right: right }),
|
|
1539
|
+
dot: left.tokens.dot
|
|
1540
|
+
});
|
|
1466
1541
|
}
|
|
1467
1542
|
}
|
|
1468
1543
|
return this.expressionStatement(expr);
|
|
1469
1544
|
}
|
|
1470
1545
|
printStatement() {
|
|
1546
|
+
var _a;
|
|
1471
1547
|
let printKeyword = this.advance();
|
|
1472
1548
|
let values = [];
|
|
1473
1549
|
while (!this.checkEndOfStatement()) {
|
|
@@ -1486,34 +1562,35 @@ class Parser {
|
|
|
1486
1562
|
}
|
|
1487
1563
|
//print statements can be empty, so look for empty print conditions
|
|
1488
1564
|
if (!values.length) {
|
|
1489
|
-
|
|
1565
|
+
const endOfStatementRange = util_1.util.createRangeFromPositions(printKeyword.range.end, (_a = this.peek()) === null || _a === void 0 ? void 0 : _a.range.end);
|
|
1566
|
+
let emptyStringLiteral = (0, creators_1.createStringLiteral)('', endOfStatementRange);
|
|
1490
1567
|
values.push(emptyStringLiteral);
|
|
1491
1568
|
}
|
|
1492
1569
|
let last = values[values.length - 1];
|
|
1493
1570
|
if ((0, Token_1.isToken)(last)) {
|
|
1494
1571
|
// TODO: error, expected value
|
|
1495
1572
|
}
|
|
1496
|
-
return new Statement_1.PrintStatement({ print: printKeyword
|
|
1573
|
+
return new Statement_1.PrintStatement({ print: printKeyword, expressions: values });
|
|
1497
1574
|
}
|
|
1498
1575
|
/**
|
|
1499
1576
|
* Parses a return statement with an optional return value.
|
|
1500
1577
|
* @returns an AST representation of a return statement.
|
|
1501
1578
|
*/
|
|
1502
1579
|
returnStatement() {
|
|
1503
|
-
let
|
|
1580
|
+
let options = { return: this.previous() };
|
|
1504
1581
|
if (this.checkEndOfStatement()) {
|
|
1505
|
-
return new Statement_1.ReturnStatement(
|
|
1582
|
+
return new Statement_1.ReturnStatement(options);
|
|
1506
1583
|
}
|
|
1507
1584
|
let toReturn = this.check(TokenKind_1.TokenKind.Else) ? undefined : this.expression();
|
|
1508
|
-
return new Statement_1.ReturnStatement(
|
|
1585
|
+
return new Statement_1.ReturnStatement(Object.assign(Object.assign({}, options), { value: toReturn }));
|
|
1509
1586
|
}
|
|
1510
1587
|
/**
|
|
1511
1588
|
* Parses a `label` statement
|
|
1512
1589
|
* @returns an AST representation of an `label` statement.
|
|
1513
1590
|
*/
|
|
1514
1591
|
labelStatement() {
|
|
1515
|
-
let
|
|
1516
|
-
|
|
1592
|
+
let options = {
|
|
1593
|
+
name: this.advance(),
|
|
1517
1594
|
colon: this.advance()
|
|
1518
1595
|
};
|
|
1519
1596
|
//label must be alone on its line, this is probably not a label
|
|
@@ -1522,9 +1599,16 @@ class Parser {
|
|
|
1522
1599
|
this.current -= 2;
|
|
1523
1600
|
throw new CancelStatementError();
|
|
1524
1601
|
}
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1602
|
+
return new Statement_1.LabelStatement(options);
|
|
1603
|
+
}
|
|
1604
|
+
/**
|
|
1605
|
+
* Parses a `continue` statement
|
|
1606
|
+
*/
|
|
1607
|
+
continueStatement() {
|
|
1608
|
+
return new Statement_1.ContinueStatement({
|
|
1609
|
+
continue: this.advance(),
|
|
1610
|
+
loopType: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For), TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For)
|
|
1611
|
+
});
|
|
1528
1612
|
}
|
|
1529
1613
|
/**
|
|
1530
1614
|
* Parses a `goto` statement
|
|
@@ -1542,16 +1626,16 @@ class Parser {
|
|
|
1542
1626
|
* @returns an AST representation of an `end` statement.
|
|
1543
1627
|
*/
|
|
1544
1628
|
endStatement() {
|
|
1545
|
-
let
|
|
1546
|
-
return new Statement_1.EndStatement(
|
|
1629
|
+
let options = { end: this.advance() };
|
|
1630
|
+
return new Statement_1.EndStatement(options);
|
|
1547
1631
|
}
|
|
1548
1632
|
/**
|
|
1549
1633
|
* Parses a `stop` statement
|
|
1550
1634
|
* @returns an AST representation of a `stop` statement
|
|
1551
1635
|
*/
|
|
1552
1636
|
stopStatement() {
|
|
1553
|
-
let
|
|
1554
|
-
return new Statement_1.StopStatement(
|
|
1637
|
+
let options = { stop: this.advance() };
|
|
1638
|
+
return new Statement_1.StopStatement(options);
|
|
1555
1639
|
}
|
|
1556
1640
|
/**
|
|
1557
1641
|
* Parses a block, looking for a specific terminating TokenKind to denote completion.
|
|
@@ -1603,7 +1687,7 @@ class Parser {
|
|
|
1603
1687
|
}
|
|
1604
1688
|
}
|
|
1605
1689
|
this.exitAnnotationBlock(parentAnnotations);
|
|
1606
|
-
return new Statement_1.Block(statements, startingToken.range);
|
|
1690
|
+
return new Statement_1.Block({ statements: statements, startingRange: startingToken.range });
|
|
1607
1691
|
}
|
|
1608
1692
|
/**
|
|
1609
1693
|
* Attach pending annotations to the provided statement,
|
|
@@ -1629,14 +1713,32 @@ class Parser {
|
|
|
1629
1713
|
}
|
|
1630
1714
|
this.pendingAnnotations = parentAnnotations;
|
|
1631
1715
|
}
|
|
1632
|
-
expression() {
|
|
1633
|
-
|
|
1634
|
-
|
|
1716
|
+
expression(findTypeCast = true) {
|
|
1717
|
+
let expression = this.anonymousFunction();
|
|
1718
|
+
let asToken;
|
|
1719
|
+
let typeExpression;
|
|
1720
|
+
if (findTypeCast) {
|
|
1721
|
+
do {
|
|
1722
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
1723
|
+
this.warnIfNotBrighterScriptMode('type cast');
|
|
1724
|
+
// Check if this expression is wrapped in any type casts
|
|
1725
|
+
// allows for multiple casts:
|
|
1726
|
+
// myVal = foo() as dynamic as string
|
|
1727
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
1728
|
+
if (asToken && typeExpression) {
|
|
1729
|
+
expression = new Expression_1.TypeCastExpression({ obj: expression, as: asToken, typeExpression: typeExpression });
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
else {
|
|
1733
|
+
break;
|
|
1734
|
+
}
|
|
1735
|
+
} while (asToken && typeExpression);
|
|
1736
|
+
}
|
|
1635
1737
|
return expression;
|
|
1636
1738
|
}
|
|
1637
1739
|
anonymousFunction() {
|
|
1638
1740
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
1639
|
-
const func = this.functionDeclaration(
|
|
1741
|
+
const func = this.functionDeclaration(true);
|
|
1640
1742
|
//if there's an open paren after this, this is an IIFE
|
|
1641
1743
|
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1642
1744
|
return this.finishCall(this.advance(), func);
|
|
@@ -1661,8 +1763,7 @@ class Parser {
|
|
|
1661
1763
|
while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
|
|
1662
1764
|
let operator = this.previous();
|
|
1663
1765
|
let right = this.relational();
|
|
1664
|
-
|
|
1665
|
-
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1766
|
+
expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
|
|
1666
1767
|
}
|
|
1667
1768
|
return expr;
|
|
1668
1769
|
}
|
|
@@ -1671,26 +1772,17 @@ class Parser {
|
|
|
1671
1772
|
while (this.matchAny(TokenKind_1.TokenKind.Equal, TokenKind_1.TokenKind.LessGreater, TokenKind_1.TokenKind.Greater, TokenKind_1.TokenKind.GreaterEqual, TokenKind_1.TokenKind.Less, TokenKind_1.TokenKind.LessEqual)) {
|
|
1672
1773
|
let operator = this.previous();
|
|
1673
1774
|
let right = this.additive();
|
|
1674
|
-
|
|
1675
|
-
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1775
|
+
expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
|
|
1676
1776
|
}
|
|
1677
1777
|
return expr;
|
|
1678
1778
|
}
|
|
1679
|
-
addExpressionsToReferences(...expressions) {
|
|
1680
|
-
for (const expression of expressions) {
|
|
1681
|
-
if (!(0, reflection_1.isBinaryExpression)(expression)) {
|
|
1682
|
-
this.references.expressions.add(expression);
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
}
|
|
1686
1779
|
// TODO: bitshift
|
|
1687
1780
|
additive() {
|
|
1688
1781
|
let expr = this.multiplicative();
|
|
1689
1782
|
while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
|
|
1690
1783
|
let operator = this.previous();
|
|
1691
1784
|
let right = this.multiplicative();
|
|
1692
|
-
|
|
1693
|
-
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1785
|
+
expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
|
|
1694
1786
|
}
|
|
1695
1787
|
return expr;
|
|
1696
1788
|
}
|
|
@@ -1699,8 +1791,7 @@ class Parser {
|
|
|
1699
1791
|
while (this.matchAny(TokenKind_1.TokenKind.Forwardslash, TokenKind_1.TokenKind.Backslash, TokenKind_1.TokenKind.Star, TokenKind_1.TokenKind.Mod, TokenKind_1.TokenKind.LeftShift, TokenKind_1.TokenKind.RightShift)) {
|
|
1700
1792
|
let operator = this.previous();
|
|
1701
1793
|
let right = this.exponential();
|
|
1702
|
-
|
|
1703
|
-
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1794
|
+
expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
|
|
1704
1795
|
}
|
|
1705
1796
|
return expr;
|
|
1706
1797
|
}
|
|
@@ -1709,40 +1800,74 @@ class Parser {
|
|
|
1709
1800
|
while (this.match(TokenKind_1.TokenKind.Caret)) {
|
|
1710
1801
|
let operator = this.previous();
|
|
1711
1802
|
let right = this.prefixUnary();
|
|
1712
|
-
|
|
1713
|
-
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1803
|
+
expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
|
|
1714
1804
|
}
|
|
1715
1805
|
return expr;
|
|
1716
1806
|
}
|
|
1717
1807
|
prefixUnary() {
|
|
1718
1808
|
const nextKind = this.peek().kind;
|
|
1719
|
-
if (nextKind === TokenKind_1.TokenKind.Not
|
|
1809
|
+
if (nextKind === TokenKind_1.TokenKind.Not) {
|
|
1720
1810
|
this.current++; //advance
|
|
1721
1811
|
let operator = this.previous();
|
|
1722
|
-
let right = this.
|
|
1723
|
-
return new Expression_1.UnaryExpression(operator, right);
|
|
1812
|
+
let right = this.relational();
|
|
1813
|
+
return new Expression_1.UnaryExpression({ operator: operator, right: right });
|
|
1814
|
+
}
|
|
1815
|
+
else if (nextKind === TokenKind_1.TokenKind.Minus || nextKind === TokenKind_1.TokenKind.Plus) {
|
|
1816
|
+
this.current++; //advance
|
|
1817
|
+
let operator = this.previous();
|
|
1818
|
+
let right = nextKind === TokenKind_1.TokenKind.Not
|
|
1819
|
+
? this.boolean()
|
|
1820
|
+
: this.prefixUnary();
|
|
1821
|
+
return new Expression_1.UnaryExpression({ operator: operator, right: right });
|
|
1724
1822
|
}
|
|
1725
1823
|
return this.call();
|
|
1726
1824
|
}
|
|
1727
1825
|
indexedGet(expr) {
|
|
1728
1826
|
let openingSquare = this.previous();
|
|
1729
1827
|
let questionDotToken = this.getMatchingTokenAtOffset(-2, TokenKind_1.TokenKind.QuestionDot);
|
|
1828
|
+
let indexes = [];
|
|
1829
|
+
//consume leading newlines
|
|
1730
1830
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1731
|
-
|
|
1831
|
+
try {
|
|
1832
|
+
indexes.push(this.expression());
|
|
1833
|
+
//consume additional indexes separated by commas
|
|
1834
|
+
while (this.check(TokenKind_1.TokenKind.Comma)) {
|
|
1835
|
+
//discard the comma
|
|
1836
|
+
this.advance();
|
|
1837
|
+
indexes.push(this.expression());
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
catch (error) {
|
|
1841
|
+
this.rethrowNonDiagnosticError(error);
|
|
1842
|
+
}
|
|
1843
|
+
//consume trailing newlines
|
|
1732
1844
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1733
|
-
|
|
1734
|
-
return new Expression_1.IndexedGetExpression(
|
|
1845
|
+
const closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1846
|
+
return new Expression_1.IndexedGetExpression({
|
|
1847
|
+
obj: expr,
|
|
1848
|
+
indexes: indexes,
|
|
1849
|
+
openingSquare: openingSquare,
|
|
1850
|
+
closingSquare: closingSquare,
|
|
1851
|
+
questionDot: questionDotToken
|
|
1852
|
+
});
|
|
1735
1853
|
}
|
|
1736
1854
|
newExpression() {
|
|
1855
|
+
var _a;
|
|
1737
1856
|
this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
|
|
1738
1857
|
let newToken = this.advance();
|
|
1739
|
-
let nameExpr = this.
|
|
1740
|
-
let leftParen = this.
|
|
1858
|
+
let nameExpr = this.identifyingExpression();
|
|
1859
|
+
let leftParen = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen);
|
|
1860
|
+
if (!leftParen) {
|
|
1861
|
+
// new expression without a following call expression
|
|
1862
|
+
// wrap the name in an expression
|
|
1863
|
+
const endOfStatementRange = util_1.util.createRangeFromPositions(newToken.range.end, (_a = this.peek()) === null || _a === void 0 ? void 0 : _a.range.end);
|
|
1864
|
+
const exprStmt = nameExpr !== null && nameExpr !== void 0 ? nameExpr : (0, creators_1.createStringLiteral)('', endOfStatementRange);
|
|
1865
|
+
return new Statement_1.ExpressionStatement({ expression: exprStmt });
|
|
1866
|
+
}
|
|
1741
1867
|
let call = this.finishCall(leftParen, nameExpr);
|
|
1742
1868
|
//pop the call from the callExpressions list because this is technically something else
|
|
1743
1869
|
this.callExpressions.pop();
|
|
1744
|
-
let result = new Expression_1.NewExpression(newToken, call);
|
|
1745
|
-
this._references.newExpressions.push(result);
|
|
1870
|
+
let result = new Expression_1.NewExpression({ new: newToken, call: call });
|
|
1746
1871
|
return result;
|
|
1747
1872
|
}
|
|
1748
1873
|
/**
|
|
@@ -1756,28 +1881,29 @@ class Parser {
|
|
|
1756
1881
|
methodName.kind = TokenKind_1.TokenKind.Identifier;
|
|
1757
1882
|
let openParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedOpenParenToFollowCallfuncIdentifier(), TokenKind_1.TokenKind.LeftParen);
|
|
1758
1883
|
let call = this.finishCall(openParen, callee, false);
|
|
1759
|
-
return new Expression_1.CallfuncExpression(
|
|
1884
|
+
return new Expression_1.CallfuncExpression({
|
|
1885
|
+
callee: callee,
|
|
1886
|
+
operator: operator,
|
|
1887
|
+
methodName: methodName,
|
|
1888
|
+
openingParen: openParen,
|
|
1889
|
+
args: call.args,
|
|
1890
|
+
closingParen: call.tokens.closingParen
|
|
1891
|
+
});
|
|
1760
1892
|
}
|
|
1761
1893
|
call() {
|
|
1762
1894
|
if (this.check(TokenKind_1.TokenKind.New) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
|
|
1763
1895
|
return this.newExpression();
|
|
1764
1896
|
}
|
|
1765
1897
|
let expr = this.primary();
|
|
1766
|
-
//an expression to keep for _references
|
|
1767
|
-
let referenceCallExpression;
|
|
1768
1898
|
while (true) {
|
|
1769
1899
|
if (this.matchAny(TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen)) {
|
|
1770
1900
|
expr = this.finishCall(this.previous(), expr);
|
|
1771
|
-
//store this call expression in references
|
|
1772
|
-
referenceCallExpression = expr;
|
|
1773
1901
|
}
|
|
1774
1902
|
else if (this.matchAny(TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.QuestionLeftSquare) || this.matchSequence(TokenKind_1.TokenKind.QuestionDot, TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1775
1903
|
expr = this.indexedGet(expr);
|
|
1776
1904
|
}
|
|
1777
1905
|
else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
|
|
1778
1906
|
expr = this.callfunc(expr);
|
|
1779
|
-
//store this callfunc expression in references
|
|
1780
|
-
referenceCallExpression = expr;
|
|
1781
1907
|
}
|
|
1782
1908
|
else if (this.matchAny(TokenKind_1.TokenKind.Dot, TokenKind_1.TokenKind.QuestionDot)) {
|
|
1783
1909
|
if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
@@ -1785,19 +1911,24 @@ class Parser {
|
|
|
1785
1911
|
}
|
|
1786
1912
|
else {
|
|
1787
1913
|
let dot = this.previous();
|
|
1788
|
-
let name = this.
|
|
1914
|
+
let name = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1915
|
+
if (!name) {
|
|
1916
|
+
break;
|
|
1917
|
+
}
|
|
1789
1918
|
// force it into an identifier so the AST makes some sense
|
|
1790
1919
|
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1791
|
-
expr = new Expression_1.DottedGetExpression(expr, name, dot);
|
|
1792
|
-
this.addPropertyHints(name);
|
|
1920
|
+
expr = new Expression_1.DottedGetExpression({ obj: expr, name: name, dot: dot });
|
|
1793
1921
|
}
|
|
1794
1922
|
}
|
|
1795
1923
|
else if (this.checkAny(TokenKind_1.TokenKind.At, TokenKind_1.TokenKind.QuestionAt)) {
|
|
1796
1924
|
let dot = this.advance();
|
|
1797
|
-
let name = this.
|
|
1925
|
+
let name = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1798
1926
|
// force it into an identifier so the AST makes some sense
|
|
1799
1927
|
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1800
|
-
|
|
1928
|
+
if (!name) {
|
|
1929
|
+
break;
|
|
1930
|
+
}
|
|
1931
|
+
expr = new Expression_1.XmlAttributeGetExpression({ obj: expr, name: name, at: dot });
|
|
1801
1932
|
//only allow a single `@` expression
|
|
1802
1933
|
break;
|
|
1803
1934
|
}
|
|
@@ -1805,10 +1936,6 @@ class Parser {
|
|
|
1805
1936
|
break;
|
|
1806
1937
|
}
|
|
1807
1938
|
}
|
|
1808
|
-
//if we found a callExpression, add it to `expressions` in references
|
|
1809
|
-
if (referenceCallExpression) {
|
|
1810
|
-
this._references.expressions.add(referenceCallExpression);
|
|
1811
|
-
}
|
|
1812
1939
|
return expr;
|
|
1813
1940
|
}
|
|
1814
1941
|
finishCall(openingParen, callee, addToCallExpressionList = true) {
|
|
@@ -1821,68 +1948,109 @@ class Parser {
|
|
|
1821
1948
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
1822
1949
|
throw this.lastDiagnosticAsError();
|
|
1823
1950
|
}
|
|
1824
|
-
|
|
1951
|
+
try {
|
|
1952
|
+
args.push(this.expression());
|
|
1953
|
+
}
|
|
1954
|
+
catch (error) {
|
|
1955
|
+
this.rethrowNonDiagnosticError(error);
|
|
1956
|
+
// we were unable to get an expression, so don't continue
|
|
1957
|
+
break;
|
|
1958
|
+
}
|
|
1825
1959
|
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
1826
1960
|
}
|
|
1827
1961
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1828
|
-
const closingParen = this.
|
|
1829
|
-
let expression = new Expression_1.CallExpression(
|
|
1962
|
+
const closingParen = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
|
|
1963
|
+
let expression = new Expression_1.CallExpression({
|
|
1964
|
+
callee: callee,
|
|
1965
|
+
openingParen: openingParen,
|
|
1966
|
+
args: args,
|
|
1967
|
+
closingParen: closingParen
|
|
1968
|
+
});
|
|
1830
1969
|
if (addToCallExpressionList) {
|
|
1831
1970
|
this.callExpressions.push(expression);
|
|
1832
1971
|
}
|
|
1833
1972
|
return expression;
|
|
1834
1973
|
}
|
|
1835
1974
|
/**
|
|
1836
|
-
*
|
|
1837
|
-
* Allows for built-in types (double, string, etc.) or namespaced custom types in Brighterscript mode
|
|
1838
|
-
* Will return a token of whatever is next to be parsed (unless `advanceIfUnknown` is false, in which case undefined will be returned instead
|
|
1975
|
+
* Creates a TypeExpression, which wraps standard ASTNodes that represent a BscType
|
|
1839
1976
|
*/
|
|
1840
1977
|
typeExpression() {
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1978
|
+
const changedTokens = [];
|
|
1979
|
+
try {
|
|
1980
|
+
let expr = this.getTypeExpressionPart(changedTokens);
|
|
1981
|
+
while (this.options.mode === ParseMode.BrighterScript && this.matchAny(TokenKind_1.TokenKind.Or)) {
|
|
1982
|
+
// If we're in Brighterscript mode, allow union types with "or" between types
|
|
1983
|
+
// TODO: Handle Union types in parens? eg. "(string or integer)"
|
|
1984
|
+
let operator = this.previous();
|
|
1985
|
+
let right = this.getTypeExpressionPart(changedTokens);
|
|
1986
|
+
if (right) {
|
|
1987
|
+
expr = new Expression_1.BinaryExpression({ left: expr, operator: operator, right: right });
|
|
1988
|
+
}
|
|
1989
|
+
else {
|
|
1990
|
+
break;
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
if (expr) {
|
|
1994
|
+
return new Expression_1.TypeExpression({ expression: expr });
|
|
1851
1995
|
}
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1996
|
+
}
|
|
1997
|
+
catch (error) {
|
|
1998
|
+
// Something went wrong - reset the kind to what it was previously
|
|
1999
|
+
for (const changedToken of changedTokens) {
|
|
2000
|
+
changedToken.token.kind = changedToken.oldKind;
|
|
1855
2001
|
}
|
|
2002
|
+
throw error;
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
/**
|
|
2006
|
+
* Gets a single "part" of a type of a potential Union type
|
|
2007
|
+
* Note: this does not NEED to be part of a union type, but the logic is the same
|
|
2008
|
+
*
|
|
2009
|
+
* @param changedTokens an array that is modified with any tokens that have been changed from their default kind to identifiers - eg. when a keyword is used as type
|
|
2010
|
+
* @returns an expression that was successfully parsed
|
|
2011
|
+
*/
|
|
2012
|
+
getTypeExpressionPart(changedTokens) {
|
|
2013
|
+
let expr;
|
|
2014
|
+
if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
|
|
2015
|
+
// if this is just a type, just use directly
|
|
2016
|
+
expr = new Expression_1.VariableExpression({ name: this.advance() });
|
|
1856
2017
|
}
|
|
1857
2018
|
else {
|
|
1858
|
-
|
|
1859
|
-
|
|
2019
|
+
if (this.checkAny(...TokenKind_1.AllowedTypeIdentifiers)) {
|
|
2020
|
+
// Since the next token is allowed as a type identifier, change the kind
|
|
2021
|
+
let nextToken = this.peek();
|
|
2022
|
+
changedTokens.push({ token: nextToken, oldKind: nextToken.kind });
|
|
2023
|
+
nextToken.kind = TokenKind_1.TokenKind.Identifier;
|
|
2024
|
+
}
|
|
2025
|
+
expr = this.identifyingExpression(TokenKind_1.AllowedTypeIdentifiers);
|
|
1860
2026
|
}
|
|
1861
|
-
//
|
|
1862
|
-
|
|
1863
|
-
|
|
2027
|
+
//Check if it has square brackets, thus making it an array
|
|
2028
|
+
if (expr && this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
2029
|
+
if (this.options.mode === ParseMode.BrightScript) {
|
|
2030
|
+
// typed arrays not allowed in Brightscript
|
|
2031
|
+
this.warnIfNotBrighterScriptMode('typed arrays');
|
|
2032
|
+
return expr;
|
|
2033
|
+
}
|
|
1864
2034
|
// Check if it is an array - that is, if it has `[]` after the type
|
|
1865
|
-
// eg. `string[]` or `SomeKlass[]`
|
|
2035
|
+
// eg. `string[]` or `SomeKlass[]`
|
|
2036
|
+
// This is while loop, so it supports multidimensional arrays (eg. integer[][])
|
|
1866
2037
|
while (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1867
2038
|
const leftBracket = this.advance();
|
|
1868
2039
|
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1869
2040
|
const rightBracket = this.advance();
|
|
1870
|
-
|
|
1871
|
-
}
|
|
1872
|
-
else {
|
|
1873
|
-
break;
|
|
2041
|
+
expr = new Expression_1.TypedArrayExpression({ innerType: expr, leftBracket: leftBracket, rightBracket: rightBracket });
|
|
1874
2042
|
}
|
|
1875
2043
|
}
|
|
1876
2044
|
}
|
|
1877
|
-
return
|
|
2045
|
+
return expr;
|
|
1878
2046
|
}
|
|
1879
2047
|
primary() {
|
|
1880
2048
|
switch (true) {
|
|
1881
2049
|
case this.matchAny(TokenKind_1.TokenKind.False, TokenKind_1.TokenKind.True, TokenKind_1.TokenKind.Invalid, TokenKind_1.TokenKind.IntegerLiteral, TokenKind_1.TokenKind.LongIntegerLiteral, TokenKind_1.TokenKind.FloatLiteral, TokenKind_1.TokenKind.DoubleLiteral, TokenKind_1.TokenKind.StringLiteral):
|
|
1882
|
-
return new Expression_1.LiteralExpression(this.previous());
|
|
2050
|
+
return new Expression_1.LiteralExpression({ value: this.previous() });
|
|
1883
2051
|
//capture source literals (LINE_NUM if brightscript, or a bunch of them if brighterscript)
|
|
1884
2052
|
case this.matchAny(TokenKind_1.TokenKind.LineNumLiteral, ...(this.options.mode === ParseMode.BrightScript ? [] : TokenKind_1.BrighterScriptSourceLiterals)):
|
|
1885
|
-
return new Expression_1.SourceLiteralExpression(this.previous());
|
|
2053
|
+
return new Expression_1.SourceLiteralExpression({ value: this.previous() });
|
|
1886
2054
|
//template string
|
|
1887
2055
|
case this.check(TokenKind_1.TokenKind.BackTick):
|
|
1888
2056
|
return this.templateString(false);
|
|
@@ -1890,12 +2058,12 @@ class Parser {
|
|
|
1890
2058
|
case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
|
|
1891
2059
|
return this.templateString(true);
|
|
1892
2060
|
case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
|
|
1893
|
-
return new Expression_1.VariableExpression(this.previous()
|
|
2061
|
+
return new Expression_1.VariableExpression({ name: this.previous() });
|
|
1894
2062
|
case this.match(TokenKind_1.TokenKind.LeftParen):
|
|
1895
2063
|
let left = this.previous();
|
|
1896
2064
|
let expr = this.expression();
|
|
1897
2065
|
let right = this.consume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftParenAfterExpression(), TokenKind_1.TokenKind.RightParen);
|
|
1898
|
-
return new Expression_1.GroupingExpression({
|
|
2066
|
+
return new Expression_1.GroupingExpression({ leftParen: left, rightParen: right, expression: expr });
|
|
1899
2067
|
case this.matchAny(TokenKind_1.TokenKind.LeftSquareBracket):
|
|
1900
2068
|
return this.arrayLiteral();
|
|
1901
2069
|
case this.match(TokenKind_1.TokenKind.LeftCurlyBrace):
|
|
@@ -1904,13 +2072,13 @@ class Parser {
|
|
|
1904
2072
|
let token = Object.assign(this.previous(), {
|
|
1905
2073
|
kind: TokenKind_1.TokenKind.Identifier
|
|
1906
2074
|
});
|
|
1907
|
-
return new Expression_1.VariableExpression(token
|
|
2075
|
+
return new Expression_1.VariableExpression({ name: token });
|
|
1908
2076
|
case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
|
|
1909
2077
|
return this.anonymousFunction();
|
|
1910
2078
|
case this.check(TokenKind_1.TokenKind.RegexLiteral):
|
|
1911
2079
|
return this.regexLiteralExpression();
|
|
1912
2080
|
case this.check(TokenKind_1.TokenKind.Comment):
|
|
1913
|
-
return new Statement_1.CommentStatement([this.advance()]);
|
|
2081
|
+
return new Statement_1.CommentStatement({ comments: [this.advance()] });
|
|
1914
2082
|
default:
|
|
1915
2083
|
//if we found an expected terminator, don't throw a diagnostic...just return undefined
|
|
1916
2084
|
if (this.checkAny(...this.peekGlobalTerminators())) {
|
|
@@ -1928,29 +2096,37 @@ class Parser {
|
|
|
1928
2096
|
let openingSquare = this.previous();
|
|
1929
2097
|
//add any comment found right after the opening square
|
|
1930
2098
|
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1931
|
-
elements.push(new Statement_1.CommentStatement([this.advance()]));
|
|
2099
|
+
elements.push(new Statement_1.CommentStatement({ comments: [this.advance()] }));
|
|
1932
2100
|
}
|
|
1933
2101
|
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1934
2102
|
}
|
|
2103
|
+
let closingSquare;
|
|
1935
2104
|
if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1936
|
-
|
|
1937
|
-
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1938
|
-
if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1939
|
-
let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
|
|
1940
|
-
elements.push(new Statement_1.CommentStatement([comment]));
|
|
1941
|
-
}
|
|
1942
|
-
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1943
|
-
}
|
|
1944
|
-
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1945
|
-
break;
|
|
1946
|
-
}
|
|
2105
|
+
try {
|
|
1947
2106
|
elements.push(this.expression());
|
|
2107
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
2108
|
+
if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
2109
|
+
let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
|
|
2110
|
+
elements.push(new Statement_1.CommentStatement({ comments: [comment] }));
|
|
2111
|
+
}
|
|
2112
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
2113
|
+
}
|
|
2114
|
+
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
2115
|
+
break;
|
|
2116
|
+
}
|
|
2117
|
+
elements.push(this.expression());
|
|
2118
|
+
}
|
|
1948
2119
|
}
|
|
1949
|
-
|
|
2120
|
+
catch (error) {
|
|
2121
|
+
this.rethrowNonDiagnosticError(error);
|
|
2122
|
+
}
|
|
2123
|
+
closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
2124
|
+
}
|
|
2125
|
+
else {
|
|
2126
|
+
closingSquare = this.previous();
|
|
1950
2127
|
}
|
|
1951
|
-
let closingSquare = this.previous();
|
|
1952
2128
|
//this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
|
|
1953
|
-
return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
|
|
2129
|
+
return new Expression_1.ArrayLiteralExpression({ elements: elements, open: openingSquare, close: closingSquare });
|
|
1954
2130
|
}
|
|
1955
2131
|
aaLiteral() {
|
|
1956
2132
|
let openingBrace = this.previous();
|
|
@@ -1976,51 +2152,66 @@ class Parser {
|
|
|
1976
2152
|
return result;
|
|
1977
2153
|
};
|
|
1978
2154
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
2155
|
+
let closingBrace;
|
|
1979
2156
|
if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
1980
2157
|
let lastAAMember;
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
else {
|
|
1986
|
-
let k = key();
|
|
1987
|
-
let expr = this.expression();
|
|
1988
|
-
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
|
|
1989
|
-
members.push(lastAAMember);
|
|
1990
|
-
}
|
|
1991
|
-
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
1992
|
-
// collect comma at end of expression
|
|
1993
|
-
if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
|
|
1994
|
-
lastAAMember.commaToken = this.previous();
|
|
1995
|
-
}
|
|
1996
|
-
//check for comment at the end of the current line
|
|
1997
|
-
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1998
|
-
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1999
|
-
members.push(new Statement_1.CommentStatement([token]));
|
|
2158
|
+
try {
|
|
2159
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
2160
|
+
lastAAMember = null;
|
|
2161
|
+
members.push(new Statement_1.CommentStatement({ comments: [this.advance()] }));
|
|
2000
2162
|
}
|
|
2001
2163
|
else {
|
|
2002
|
-
|
|
2003
|
-
|
|
2164
|
+
let k = key();
|
|
2165
|
+
let expr = this.expression();
|
|
2166
|
+
lastAAMember = new Expression_1.AAMemberExpression({
|
|
2167
|
+
key: k.keyToken,
|
|
2168
|
+
colon: k.colonToken,
|
|
2169
|
+
value: expr
|
|
2170
|
+
});
|
|
2171
|
+
members.push(lastAAMember);
|
|
2172
|
+
}
|
|
2173
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
2174
|
+
// collect comma at end of expression
|
|
2175
|
+
if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
|
|
2176
|
+
lastAAMember.tokens.comma = this.previous();
|
|
2177
|
+
}
|
|
2178
|
+
//check for comment at the end of the current line
|
|
2004
2179
|
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
2005
2180
|
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
2006
|
-
|
|
2007
|
-
members.push(new Statement_1.CommentStatement([token]));
|
|
2008
|
-
continue;
|
|
2181
|
+
members.push(new Statement_1.CommentStatement({ comments: [token] }));
|
|
2009
2182
|
}
|
|
2010
|
-
|
|
2011
|
-
|
|
2183
|
+
else {
|
|
2184
|
+
this.consumeStatementSeparators(true);
|
|
2185
|
+
//check for a comment on its own line
|
|
2186
|
+
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
2187
|
+
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
2188
|
+
lastAAMember = null;
|
|
2189
|
+
members.push(new Statement_1.CommentStatement({ comments: [token] }));
|
|
2190
|
+
continue;
|
|
2191
|
+
}
|
|
2192
|
+
if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
2193
|
+
break;
|
|
2194
|
+
}
|
|
2195
|
+
let k = key();
|
|
2196
|
+
let expr = this.expression();
|
|
2197
|
+
lastAAMember = new Expression_1.AAMemberExpression({
|
|
2198
|
+
key: k.keyToken,
|
|
2199
|
+
colon: k.colonToken,
|
|
2200
|
+
value: expr
|
|
2201
|
+
});
|
|
2202
|
+
members.push(lastAAMember);
|
|
2012
2203
|
}
|
|
2013
|
-
let k = key();
|
|
2014
|
-
let expr = this.expression();
|
|
2015
|
-
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
|
|
2016
|
-
members.push(lastAAMember);
|
|
2017
2204
|
}
|
|
2018
2205
|
}
|
|
2019
|
-
|
|
2206
|
+
catch (error) {
|
|
2207
|
+
this.rethrowNonDiagnosticError(error);
|
|
2208
|
+
}
|
|
2209
|
+
closingBrace = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
|
|
2020
2210
|
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2211
|
+
else {
|
|
2212
|
+
closingBrace = this.previous();
|
|
2213
|
+
}
|
|
2214
|
+
const aaExpr = new Expression_1.AALiteralExpression({ elements: members, open: openingBrace, close: closingBrace });
|
|
2024
2215
|
return aaExpr;
|
|
2025
2216
|
}
|
|
2026
2217
|
/**
|
|
@@ -2035,7 +2226,7 @@ class Parser {
|
|
|
2035
2226
|
}
|
|
2036
2227
|
/**
|
|
2037
2228
|
* Pop token if we encounter a token in the specified list
|
|
2038
|
-
* @param tokenKinds
|
|
2229
|
+
* @param tokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
|
|
2039
2230
|
*/
|
|
2040
2231
|
matchAny(...tokenKinds) {
|
|
2041
2232
|
for (let tokenKind of tokenKinds) {
|
|
@@ -2048,7 +2239,7 @@ class Parser {
|
|
|
2048
2239
|
}
|
|
2049
2240
|
/**
|
|
2050
2241
|
* If the next series of tokens matches the given set of tokens, pop them all
|
|
2051
|
-
* @param tokenKinds
|
|
2242
|
+
* @param tokenKinds a list of tokenKinds used to match the next set of tokens
|
|
2052
2243
|
*/
|
|
2053
2244
|
matchSequence(...tokenKinds) {
|
|
2054
2245
|
var _a;
|
|
@@ -2075,6 +2266,14 @@ class Parser {
|
|
|
2075
2266
|
throw error;
|
|
2076
2267
|
}
|
|
2077
2268
|
}
|
|
2269
|
+
/**
|
|
2270
|
+
* Consume next token IF it matches the specified kind. Otherwise, do nothing and return undefined
|
|
2271
|
+
*/
|
|
2272
|
+
consumeTokenIf(tokenKind) {
|
|
2273
|
+
if (this.match(tokenKind)) {
|
|
2274
|
+
return this.previous();
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2078
2277
|
consumeToken(tokenKind) {
|
|
2079
2278
|
return this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(tokenKind), tokenKind);
|
|
2080
2279
|
}
|
|
@@ -2121,6 +2320,11 @@ class Parser {
|
|
|
2121
2320
|
var _a;
|
|
2122
2321
|
return ((_a = this.previous()) === null || _a === void 0 ? void 0 : _a.kind) === tokenKind;
|
|
2123
2322
|
}
|
|
2323
|
+
/**
|
|
2324
|
+
* Check that the next token kind is the expected kind
|
|
2325
|
+
* @param tokenKind the expected next kind
|
|
2326
|
+
* @returns true if the next tokenKind is the expected value
|
|
2327
|
+
*/
|
|
2124
2328
|
check(tokenKind) {
|
|
2125
2329
|
const nextKind = this.peek().kind;
|
|
2126
2330
|
if (nextKind === TokenKind_1.TokenKind.Eof) {
|
|
@@ -2163,6 +2367,18 @@ class Parser {
|
|
|
2163
2367
|
previous() {
|
|
2164
2368
|
return this.tokens[this.current - 1];
|
|
2165
2369
|
}
|
|
2370
|
+
/**
|
|
2371
|
+
* Sometimes we catch an error that is a diagnostic.
|
|
2372
|
+
* If that's the case, we want to continue parsing.
|
|
2373
|
+
* Otherwise, re-throw the error
|
|
2374
|
+
*
|
|
2375
|
+
* @param error error caught in a try/catch
|
|
2376
|
+
*/
|
|
2377
|
+
rethrowNonDiagnosticError(error) {
|
|
2378
|
+
if (!error.isDiagnostic) {
|
|
2379
|
+
throw error;
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2166
2382
|
/**
|
|
2167
2383
|
* Get the token that is {offset} indexes away from {this.current}
|
|
2168
2384
|
* @param offset the number of index steps away from current index to fetch
|
|
@@ -2203,398 +2419,6 @@ class Parser {
|
|
|
2203
2419
|
this.advance();
|
|
2204
2420
|
}
|
|
2205
2421
|
}
|
|
2206
|
-
/**
|
|
2207
|
-
* Get the token at the specified position
|
|
2208
|
-
* @param position
|
|
2209
|
-
*/
|
|
2210
|
-
getTokenAt(position) {
|
|
2211
|
-
for (let token of this.tokens) {
|
|
2212
|
-
if (util_1.util.rangeContains(token.range, position)) {
|
|
2213
|
-
return token;
|
|
2214
|
-
}
|
|
2215
|
-
}
|
|
2216
|
-
}
|
|
2217
|
-
/**
|
|
2218
|
-
* Get the token closest to the position. if no token is found, the previous token is returned
|
|
2219
|
-
* @param position
|
|
2220
|
-
* @param tokens
|
|
2221
|
-
*/
|
|
2222
|
-
getClosestToken(position) {
|
|
2223
|
-
let tokens = this.tokens;
|
|
2224
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
2225
|
-
let token = tokens[i];
|
|
2226
|
-
if (util_1.util.rangeContains(token.range, position)) {
|
|
2227
|
-
return token;
|
|
2228
|
-
}
|
|
2229
|
-
//if the position less than this token range, then this position touches no token,
|
|
2230
|
-
if (util_1.util.positionIsGreaterThanRange(position, token.range) === false) {
|
|
2231
|
-
let t = tokens[i - 1];
|
|
2232
|
-
//return the token or the first token
|
|
2233
|
-
return t ? t : tokens[0];
|
|
2234
|
-
}
|
|
2235
|
-
}
|
|
2236
|
-
//return the last token
|
|
2237
|
-
return tokens[tokens.length - 1];
|
|
2238
|
-
}
|
|
2239
|
-
isPositionNextToTokenKind(position, tokenKind) {
|
|
2240
|
-
const closestToken = this.getClosestToken(position);
|
|
2241
|
-
const previousToken = this.getPreviousToken(closestToken);
|
|
2242
|
-
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
2243
|
-
//next to matched token
|
|
2244
|
-
if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
|
|
2245
|
-
return false;
|
|
2246
|
-
}
|
|
2247
|
-
else if (closestToken.kind === tokenKind) {
|
|
2248
|
-
return true;
|
|
2249
|
-
}
|
|
2250
|
-
else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
|
|
2251
|
-
return false;
|
|
2252
|
-
//next to an identifier, which is next to token kind
|
|
2253
|
-
}
|
|
2254
|
-
else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
2255
|
-
return true;
|
|
2256
|
-
}
|
|
2257
|
-
else {
|
|
2258
|
-
return false;
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
getTokenBefore(currentToken, tokenKind) {
|
|
2262
|
-
const index = this.tokens.indexOf(currentToken);
|
|
2263
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
2264
|
-
currentToken = this.tokens[i];
|
|
2265
|
-
if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
|
|
2266
|
-
break;
|
|
2267
|
-
}
|
|
2268
|
-
else if (currentToken.kind === tokenKind) {
|
|
2269
|
-
return currentToken;
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
return undefined;
|
|
2273
|
-
}
|
|
2274
|
-
tokenFollows(currentToken, tokenKind) {
|
|
2275
|
-
const index = this.tokens.indexOf(currentToken);
|
|
2276
|
-
if (index > 0) {
|
|
2277
|
-
return this.tokens[index - 1].kind === tokenKind;
|
|
2278
|
-
}
|
|
2279
|
-
return false;
|
|
2280
|
-
}
|
|
2281
|
-
getTokensUntil(currentToken, tokenKind, direction = -1) {
|
|
2282
|
-
let tokens = [];
|
|
2283
|
-
for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
|
|
2284
|
-
currentToken = this.tokens[i];
|
|
2285
|
-
if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
2286
|
-
break;
|
|
2287
|
-
}
|
|
2288
|
-
tokens.push(currentToken);
|
|
2289
|
-
}
|
|
2290
|
-
return tokens;
|
|
2291
|
-
}
|
|
2292
|
-
getPreviousToken(token) {
|
|
2293
|
-
let idx = this.tokens.indexOf(token);
|
|
2294
|
-
return this.tokens[idx - 1];
|
|
2295
|
-
}
|
|
2296
|
-
getPreviousTokenFromIndex(idx) {
|
|
2297
|
-
return { token: this.tokens[idx - 1], index: idx - 1 };
|
|
2298
|
-
}
|
|
2299
|
-
getPreviousTokenIgnoreNests(currentTokenIndex, leftBracketType, rightBracketType) {
|
|
2300
|
-
let currentToken = this.tokens[currentTokenIndex];
|
|
2301
|
-
let previousTokenResult;
|
|
2302
|
-
function isRightBracket(token) {
|
|
2303
|
-
return (token === null || token === void 0 ? void 0 : token.kind) === rightBracketType;
|
|
2304
|
-
}
|
|
2305
|
-
function isLeftBracket(token) {
|
|
2306
|
-
return (token === null || token === void 0 ? void 0 : token.kind) === leftBracketType;
|
|
2307
|
-
}
|
|
2308
|
-
let lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2309
|
-
let lastTokenWasLeftBracket = false;
|
|
2310
|
-
let bracketNestCount = 0;
|
|
2311
|
-
let hasBrackets = false;
|
|
2312
|
-
// check for nested function call
|
|
2313
|
-
if (isRightBracket(currentToken)) {
|
|
2314
|
-
bracketNestCount++;
|
|
2315
|
-
hasBrackets = true;
|
|
2316
|
-
}
|
|
2317
|
-
while (currentToken && bracketNestCount > 0) {
|
|
2318
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2319
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2320
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2321
|
-
lastTokenWasLeftBracket = false;
|
|
2322
|
-
if (isRightBracket(currentToken)) {
|
|
2323
|
-
bracketNestCount++;
|
|
2324
|
-
}
|
|
2325
|
-
while (isLeftBracket(currentToken)) {
|
|
2326
|
-
bracketNestCount--;
|
|
2327
|
-
lastTokenWasLeftBracket = true;
|
|
2328
|
-
lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2329
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2330
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2331
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2332
|
-
}
|
|
2333
|
-
}
|
|
2334
|
-
const isLiteral = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.StringLiteral || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.IntegerLiteral || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.FloatLiteral || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Boolean;
|
|
2335
|
-
// We will not be able to decipher the token type if it was in brackets
|
|
2336
|
-
// e.g (someVar+otherVar).toStr() -- we don't bother trying to decipher what "(someVar+otherVar)" is
|
|
2337
|
-
let isUnknown = isLiteral || (lastTokenWasLeftBracket && (lastTokenHadLeadingWhitespace || !this.isAcceptableChainToken(currentToken)));
|
|
2338
|
-
const tokenWithIndex = { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: isUnknown, hasBrackets: hasBrackets };
|
|
2339
|
-
return tokenWithIndex;
|
|
2340
|
-
}
|
|
2341
|
-
/**
|
|
2342
|
-
* Finds the previous token in a chain (e.g. 'm.obj.func(someFunc()).value'), skipping over any arguments of function calls
|
|
2343
|
-
* If this function was called with the token at 'value' above, the previous identifier in the chain is 'func'
|
|
2344
|
-
* @param currentTokenIndex token index to start from
|
|
2345
|
-
* @param allowCurrent can the current token be the token that's the identifier?
|
|
2346
|
-
* @returns the previous identifer
|
|
2347
|
-
*/
|
|
2348
|
-
getPreviousTokenInChain(currentTokenIndex, allowCurrent = false) {
|
|
2349
|
-
let currentToken = this.tokens[currentTokenIndex];
|
|
2350
|
-
let previousTokenResult;
|
|
2351
|
-
let usage = TokenUsage.Direct;
|
|
2352
|
-
if (!allowCurrent) {
|
|
2353
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2354
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2355
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2356
|
-
}
|
|
2357
|
-
if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Dot || (currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.QuestionDot) {
|
|
2358
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2359
|
-
currentToken = previousTokenResult.token;
|
|
2360
|
-
currentTokenIndex = previousTokenResult.index;
|
|
2361
|
-
}
|
|
2362
|
-
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.RightParen);
|
|
2363
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2364
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2365
|
-
if (previousTokenResult.hasBrackets) {
|
|
2366
|
-
usage = TokenUsage.Call;
|
|
2367
|
-
}
|
|
2368
|
-
let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
|
|
2369
|
-
if (currentTokenIndex) {
|
|
2370
|
-
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.RightSquareBracket);
|
|
2371
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2372
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2373
|
-
if (previousTokenResult.hasBrackets) {
|
|
2374
|
-
usage = TokenUsage.ArrayReference;
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
tokenTypeIsNotKnowable = tokenTypeIsNotKnowable || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2378
|
-
if (tokenTypeIsNotKnowable || this.isAcceptableChainToken(currentToken)) {
|
|
2379
|
-
// either we have a valid chain token, or we can't know what the token type is
|
|
2380
|
-
return { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: tokenTypeIsNotKnowable, usage: usage };
|
|
2381
|
-
}
|
|
2382
|
-
return undefined;
|
|
2383
|
-
}
|
|
2384
|
-
isAcceptableChainToken(currentToken, lastTokenHasWhitespace = false) {
|
|
2385
|
-
if (!currentToken || lastTokenHasWhitespace) {
|
|
2386
|
-
return false;
|
|
2387
|
-
}
|
|
2388
|
-
if (currentToken.kind === TokenKind_1.TokenKind.Identifier) {
|
|
2389
|
-
return true;
|
|
2390
|
-
}
|
|
2391
|
-
if (currentToken.leadingWhitespace.length === 0) {
|
|
2392
|
-
// start of the chain
|
|
2393
|
-
return TokenKind_1.AllowedLocalIdentifiers.includes(currentToken.kind);
|
|
2394
|
-
}
|
|
2395
|
-
// not the start of the chain
|
|
2396
|
-
return TokenKind_1.AllowedProperties.includes(currentToken.kind);
|
|
2397
|
-
}
|
|
2398
|
-
/**
|
|
2399
|
-
* Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
|
|
2400
|
-
* e.g. m.prop.method().field (with 'field' as currentToken) -> ["m", "prop", "method", "field"], with each element as a token
|
|
2401
|
-
* @param currentToken the token that is the end of the chain
|
|
2402
|
-
* @returns array of tokens
|
|
2403
|
-
*/
|
|
2404
|
-
getTokenChain(currentToken) {
|
|
2405
|
-
const tokenChain = [];
|
|
2406
|
-
let currentTokenIndex = this.tokens.indexOf(currentToken);
|
|
2407
|
-
let previousTokenResult;
|
|
2408
|
-
let lastTokenHasWhitespace = false;
|
|
2409
|
-
let includesUnknown = false;
|
|
2410
|
-
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex, true);
|
|
2411
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2412
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2413
|
-
if (this.isAcceptableChainToken(currentToken)) {
|
|
2414
|
-
tokenChain.push(previousTokenResult);
|
|
2415
|
-
lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2416
|
-
}
|
|
2417
|
-
if (!lastTokenHasWhitespace) {
|
|
2418
|
-
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
|
|
2419
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2420
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2421
|
-
includesUnknown = !!(previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2422
|
-
while (!includesUnknown && this.isAcceptableChainToken(currentToken, lastTokenHasWhitespace)) {
|
|
2423
|
-
tokenChain.push(previousTokenResult);
|
|
2424
|
-
lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2425
|
-
if (!lastTokenHasWhitespace) {
|
|
2426
|
-
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
|
|
2427
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2428
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2429
|
-
includesUnknown = includesUnknown || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2430
|
-
}
|
|
2431
|
-
}
|
|
2432
|
-
}
|
|
2433
|
-
tokenChain.reverse();
|
|
2434
|
-
return { chain: tokenChain, includesUnknowableTokenType: !!includesUnknown };
|
|
2435
|
-
}
|
|
2436
|
-
/**
|
|
2437
|
-
* References are found during the initial parse.
|
|
2438
|
-
* However, sometimes plugins can modify the AST, requiring a full walk to re-compute all references.
|
|
2439
|
-
* This does that walk.
|
|
2440
|
-
*/
|
|
2441
|
-
findReferences() {
|
|
2442
|
-
this._references = new References();
|
|
2443
|
-
const excludedExpressions = new Set();
|
|
2444
|
-
const visitCallExpression = (e) => {
|
|
2445
|
-
for (const p of e.args) {
|
|
2446
|
-
this._references.expressions.add(p);
|
|
2447
|
-
}
|
|
2448
|
-
//add calls that were not excluded (from loop below)
|
|
2449
|
-
if (!excludedExpressions.has(e)) {
|
|
2450
|
-
this._references.expressions.add(e);
|
|
2451
|
-
}
|
|
2452
|
-
//if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
|
|
2453
|
-
if (e.callee) {
|
|
2454
|
-
let node = e.callee;
|
|
2455
|
-
while (node) {
|
|
2456
|
-
//the primary goal for this loop. If we found a parent call expression, remove it from `references`
|
|
2457
|
-
if ((0, reflection_1.isCallExpression)(node)) {
|
|
2458
|
-
this.references.expressions.delete(node);
|
|
2459
|
-
excludedExpressions.add(node);
|
|
2460
|
-
//stop here. even if there are multiple calls in the chain, each child will find and remove its closest parent, so that reduces excess walking.
|
|
2461
|
-
break;
|
|
2462
|
-
//when we hit a variable expression, we're definitely at the leftmost expression so stop
|
|
2463
|
-
}
|
|
2464
|
-
else if ((0, reflection_1.isVariableExpression)(node)) {
|
|
2465
|
-
break;
|
|
2466
|
-
//if
|
|
2467
|
-
}
|
|
2468
|
-
else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
|
|
2469
|
-
node = node.obj;
|
|
2470
|
-
}
|
|
2471
|
-
else {
|
|
2472
|
-
//some expression we don't understand. log it and quit the loop
|
|
2473
|
-
this.logger.info('Encountered unknown expression while calculating function expression chain', node);
|
|
2474
|
-
break;
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
2477
|
-
}
|
|
2478
|
-
};
|
|
2479
|
-
//gather up all the top-level statements
|
|
2480
|
-
this.ast.walk((0, visitors_1.createVisitor)({
|
|
2481
|
-
AssignmentStatement: s => {
|
|
2482
|
-
this._references.assignmentStatements.push(s);
|
|
2483
|
-
this.references.expressions.add(s.value);
|
|
2484
|
-
},
|
|
2485
|
-
ClassStatement: s => {
|
|
2486
|
-
this._references.classStatements.push(s);
|
|
2487
|
-
},
|
|
2488
|
-
FieldStatement: s => {
|
|
2489
|
-
if (s.initialValue) {
|
|
2490
|
-
this._references.expressions.add(s.initialValue);
|
|
2491
|
-
}
|
|
2492
|
-
},
|
|
2493
|
-
InterfaceStatement: s => {
|
|
2494
|
-
this._references.interfaceStatements.push(s);
|
|
2495
|
-
},
|
|
2496
|
-
NamespaceStatement: s => {
|
|
2497
|
-
this._references.namespaceStatements.push(s);
|
|
2498
|
-
},
|
|
2499
|
-
FunctionStatement: s => {
|
|
2500
|
-
this._references.functionStatements.push(s);
|
|
2501
|
-
},
|
|
2502
|
-
ImportStatement: s => {
|
|
2503
|
-
this._references.importStatements.push(s);
|
|
2504
|
-
},
|
|
2505
|
-
LibraryStatement: s => {
|
|
2506
|
-
this._references.libraryStatements.push(s);
|
|
2507
|
-
},
|
|
2508
|
-
FunctionExpression: (expression, parent) => {
|
|
2509
|
-
if (!(0, reflection_1.isMethodStatement)(parent) && !(0, reflection_1.isInterfaceMethodStatement)(parent)) {
|
|
2510
|
-
this._references.functionExpressions.push(expression);
|
|
2511
|
-
}
|
|
2512
|
-
},
|
|
2513
|
-
NewExpression: e => {
|
|
2514
|
-
this._references.newExpressions.push(e);
|
|
2515
|
-
for (const p of e.call.args) {
|
|
2516
|
-
this._references.expressions.add(p);
|
|
2517
|
-
}
|
|
2518
|
-
},
|
|
2519
|
-
ExpressionStatement: s => {
|
|
2520
|
-
this._references.expressions.add(s.expression);
|
|
2521
|
-
},
|
|
2522
|
-
CallfuncExpression: e => {
|
|
2523
|
-
visitCallExpression(e);
|
|
2524
|
-
},
|
|
2525
|
-
CallExpression: e => {
|
|
2526
|
-
visitCallExpression(e);
|
|
2527
|
-
},
|
|
2528
|
-
AALiteralExpression: e => {
|
|
2529
|
-
this.addPropertyHints(e);
|
|
2530
|
-
this._references.expressions.add(e);
|
|
2531
|
-
for (const member of e.elements) {
|
|
2532
|
-
if ((0, reflection_1.isAAMemberExpression)(member)) {
|
|
2533
|
-
this._references.expressions.add(member.value);
|
|
2534
|
-
}
|
|
2535
|
-
}
|
|
2536
|
-
},
|
|
2537
|
-
BinaryExpression: (e, parent) => {
|
|
2538
|
-
//walk the chain of binary expressions and add each one to the list of expressions
|
|
2539
|
-
const expressions = [e];
|
|
2540
|
-
let expression;
|
|
2541
|
-
while ((expression = expressions.pop())) {
|
|
2542
|
-
if ((0, reflection_1.isBinaryExpression)(expression)) {
|
|
2543
|
-
expressions.push(expression.left, expression.right);
|
|
2544
|
-
}
|
|
2545
|
-
else {
|
|
2546
|
-
this._references.expressions.add(expression);
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
|
-
},
|
|
2550
|
-
ArrayLiteralExpression: e => {
|
|
2551
|
-
for (const element of e.elements) {
|
|
2552
|
-
//keep everything except comments
|
|
2553
|
-
if (!(0, reflection_1.isCommentStatement)(element)) {
|
|
2554
|
-
this._references.expressions.add(element);
|
|
2555
|
-
}
|
|
2556
|
-
}
|
|
2557
|
-
},
|
|
2558
|
-
DottedGetExpression: e => {
|
|
2559
|
-
this.addPropertyHints(e.name);
|
|
2560
|
-
},
|
|
2561
|
-
DottedSetStatement: e => {
|
|
2562
|
-
this.addPropertyHints(e.name);
|
|
2563
|
-
},
|
|
2564
|
-
EnumStatement: e => {
|
|
2565
|
-
this._references.enumStatements.push(e);
|
|
2566
|
-
},
|
|
2567
|
-
ConstStatement: s => {
|
|
2568
|
-
this._references.constStatements.push(s);
|
|
2569
|
-
},
|
|
2570
|
-
UnaryExpression: e => {
|
|
2571
|
-
this._references.expressions.add(e);
|
|
2572
|
-
},
|
|
2573
|
-
IncrementStatement: e => {
|
|
2574
|
-
this._references.expressions.add(e);
|
|
2575
|
-
}
|
|
2576
|
-
}), {
|
|
2577
|
-
walkMode: visitors_1.WalkMode.visitAllRecursive
|
|
2578
|
-
});
|
|
2579
|
-
}
|
|
2580
|
-
getContainingExpression(currentToken) {
|
|
2581
|
-
return [...this.references.expressions].find((cs) => util_1.util.rangeContainsRange(cs.range, currentToken.range));
|
|
2582
|
-
}
|
|
2583
|
-
getContainingClass(currentToken) {
|
|
2584
|
-
return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
2585
|
-
}
|
|
2586
|
-
getContainingAA(currentToken) {
|
|
2587
|
-
return this.references.aaLiterals.find((aa) => util_1.util.rangeContains(aa.range, currentToken.range.start));
|
|
2588
|
-
}
|
|
2589
|
-
getContainingNamespace(currentToken) {
|
|
2590
|
-
return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
2591
|
-
}
|
|
2592
|
-
getContainingFunctionExpression(currentToken) {
|
|
2593
|
-
return this.getContainingFunctionExpressionByPosition(currentToken.range.start);
|
|
2594
|
-
}
|
|
2595
|
-
getContainingFunctionExpressionByPosition(position) {
|
|
2596
|
-
return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, position));
|
|
2597
|
-
}
|
|
2598
2422
|
dispose() {
|
|
2599
2423
|
}
|
|
2600
2424
|
}
|
|
@@ -2604,154 +2428,9 @@ var ParseMode;
|
|
|
2604
2428
|
ParseMode["BrightScript"] = "BrightScript";
|
|
2605
2429
|
ParseMode["BrighterScript"] = "BrighterScript";
|
|
2606
2430
|
})(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
|
|
2607
|
-
class References {
|
|
2608
|
-
constructor() {
|
|
2609
|
-
this.cache = new Cache_1.Cache();
|
|
2610
|
-
this.assignmentStatements = [];
|
|
2611
|
-
this.classStatements = [];
|
|
2612
|
-
this.dottedSetStatements = [];
|
|
2613
|
-
this.aaLiterals = [];
|
|
2614
|
-
this.functionExpressions = [];
|
|
2615
|
-
this.functionStatements = [];
|
|
2616
|
-
this.interfaceStatements = [];
|
|
2617
|
-
this.enumStatements = [];
|
|
2618
|
-
this.constStatements = [];
|
|
2619
|
-
/**
|
|
2620
|
-
* A collection of full expressions. This excludes intermediary expressions.
|
|
2621
|
-
*
|
|
2622
|
-
* Example 1:
|
|
2623
|
-
* `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
|
|
2624
|
-
* This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
|
|
2625
|
-
*
|
|
2626
|
-
* Example 2:
|
|
2627
|
-
* `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
|
|
2628
|
-
*
|
|
2629
|
-
* Example 3:
|
|
2630
|
-
* `value = SomeEnum.value > 2 or SomeEnum.otherValue < 10` will result in 4 entries. `SomeEnum.value`, `2`, `SomeEnum.otherValue`, `10`
|
|
2631
|
-
*/
|
|
2632
|
-
this.expressions = new Set();
|
|
2633
|
-
this.importStatements = [];
|
|
2634
|
-
this.libraryStatements = [];
|
|
2635
|
-
this.namespaceStatements = [];
|
|
2636
|
-
this.newExpressions = [];
|
|
2637
|
-
this.propertyHints = {};
|
|
2638
|
-
}
|
|
2639
|
-
get classStatementLookup() {
|
|
2640
|
-
if (!this._classStatementLookup) {
|
|
2641
|
-
this._classStatementLookup = new Map();
|
|
2642
|
-
for (const stmt of this.classStatements) {
|
|
2643
|
-
this._classStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2644
|
-
}
|
|
2645
|
-
}
|
|
2646
|
-
return this._classStatementLookup;
|
|
2647
|
-
}
|
|
2648
|
-
/**
|
|
2649
|
-
* A map of function statements, indexed by fully-namespaced lower function name.
|
|
2650
|
-
*/
|
|
2651
|
-
get functionStatementLookup() {
|
|
2652
|
-
if (!this._functionStatementLookup) {
|
|
2653
|
-
this._functionStatementLookup = new Map();
|
|
2654
|
-
for (const stmt of this.functionStatements) {
|
|
2655
|
-
this._functionStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2656
|
-
}
|
|
2657
|
-
}
|
|
2658
|
-
return this._functionStatementLookup;
|
|
2659
|
-
}
|
|
2660
|
-
get interfaceStatementLookup() {
|
|
2661
|
-
if (!this._interfaceStatementLookup) {
|
|
2662
|
-
this._interfaceStatementLookup = new Map();
|
|
2663
|
-
for (const stmt of this.interfaceStatements) {
|
|
2664
|
-
this._interfaceStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2665
|
-
}
|
|
2666
|
-
}
|
|
2667
|
-
return this._interfaceStatementLookup;
|
|
2668
|
-
}
|
|
2669
|
-
get enumStatementLookup() {
|
|
2670
|
-
return this.cache.getOrAdd('enums', () => {
|
|
2671
|
-
const result = new Map();
|
|
2672
|
-
for (const stmt of this.enumStatements) {
|
|
2673
|
-
result.set(stmt.fullName.toLowerCase(), stmt);
|
|
2674
|
-
}
|
|
2675
|
-
return result;
|
|
2676
|
-
});
|
|
2677
|
-
}
|
|
2678
|
-
get constStatementLookup() {
|
|
2679
|
-
return this.cache.getOrAdd('consts', () => {
|
|
2680
|
-
const result = new Map();
|
|
2681
|
-
for (const stmt of this.constStatements) {
|
|
2682
|
-
result.set(stmt.fullName.toLowerCase(), stmt);
|
|
2683
|
-
}
|
|
2684
|
-
return result;
|
|
2685
|
-
});
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
exports.References = References;
|
|
2689
|
-
var TokenUsage;
|
|
2690
|
-
(function (TokenUsage) {
|
|
2691
|
-
TokenUsage[TokenUsage["Direct"] = 1] = "Direct";
|
|
2692
|
-
TokenUsage[TokenUsage["Call"] = 2] = "Call";
|
|
2693
|
-
TokenUsage[TokenUsage["ArrayReference"] = 3] = "ArrayReference";
|
|
2694
|
-
})(TokenUsage = exports.TokenUsage || (exports.TokenUsage = {}));
|
|
2695
2431
|
class CancelStatementError extends Error {
|
|
2696
2432
|
constructor() {
|
|
2697
2433
|
super('CancelStatement');
|
|
2698
2434
|
}
|
|
2699
2435
|
}
|
|
2700
|
-
/**
|
|
2701
|
-
* Gets the type of an expression. If it can not be processed, will return DynamicType
|
|
2702
|
-
*
|
|
2703
|
-
* @param expression the Expression to process
|
|
2704
|
-
* @param functionExpression the wrapping function expression
|
|
2705
|
-
* @return the best guess type of that expression
|
|
2706
|
-
*/
|
|
2707
|
-
function getBscTypeFromExpression(expression, functionExpression) {
|
|
2708
|
-
try {
|
|
2709
|
-
if ((0, reflection_1.isFunctionExpression)(expression)) {
|
|
2710
|
-
return expression.getFunctionType();
|
|
2711
|
-
//literal
|
|
2712
|
-
}
|
|
2713
|
-
else if ((0, reflection_1.isLiteralExpression)(expression)) {
|
|
2714
|
-
return expression.type;
|
|
2715
|
-
//Associative array literal
|
|
2716
|
-
}
|
|
2717
|
-
else if ((0, reflection_1.isAALiteralExpression)(expression)) {
|
|
2718
|
-
return new ObjectType_1.ObjectType('object', expression.memberTable);
|
|
2719
|
-
//Array literal
|
|
2720
|
-
}
|
|
2721
|
-
else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
|
|
2722
|
-
const innerTypes = expression.elements.filter((element) => !(0, reflection_1.isCommentStatement)(element)).map((element) => {
|
|
2723
|
-
return getBscTypeFromExpression(element, functionExpression);
|
|
2724
|
-
});
|
|
2725
|
-
return new ArrayType_1.ArrayType(...innerTypes);
|
|
2726
|
-
//function call
|
|
2727
|
-
}
|
|
2728
|
-
else if (functionExpression) {
|
|
2729
|
-
// These are more precise, and can't be determined without knowing the function expression you're in
|
|
2730
|
-
if ((0, reflection_1.isNewExpression)(expression)) {
|
|
2731
|
-
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
|
|
2732
|
-
}
|
|
2733
|
-
else if ((0, reflection_1.isCallExpression)(expression)) {
|
|
2734
|
-
return (0, helpers_1.getTypeFromCallExpression)(expression, functionExpression);
|
|
2735
|
-
}
|
|
2736
|
-
else if ((0, reflection_1.isVariableExpression)(expression)) {
|
|
2737
|
-
return (0, helpers_1.getTypeFromVariableExpression)(expression, functionExpression);
|
|
2738
|
-
}
|
|
2739
|
-
else if ((0, reflection_1.isDottedGetExpression)(expression)) {
|
|
2740
|
-
return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
|
|
2741
|
-
}
|
|
2742
|
-
else if ((0, reflection_1.isIndexedGetExpression)(expression)) {
|
|
2743
|
-
const source = getBscTypeFromExpression(expression.obj, functionExpression);
|
|
2744
|
-
if ((0, reflection_1.isArrayType)(source)) {
|
|
2745
|
-
return source.getDefaultType();
|
|
2746
|
-
}
|
|
2747
|
-
}
|
|
2748
|
-
}
|
|
2749
|
-
}
|
|
2750
|
-
catch (e) {
|
|
2751
|
-
//do nothing. Just return dynamic
|
|
2752
|
-
}
|
|
2753
|
-
//fallback to dynamic
|
|
2754
|
-
return DynamicType_1.DynamicType.instance;
|
|
2755
|
-
}
|
|
2756
|
-
exports.getBscTypeFromExpression = getBscTypeFromExpression;
|
|
2757
2436
|
//# sourceMappingURL=Parser.js.map
|