brighterscript 1.0.0-alpha.24 → 1.0.0-alpha.25
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 +493 -233
- package/README.md +45 -139
- package/bsconfig.schema.json +41 -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 +39 -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 +831 -695
- 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 +87 -133
- package/dist/Scope.js +450 -510
- 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 -6
- package/dist/XmlScope.js +74 -69
- 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} +68 -64
- package/dist/astUtils/Editor.spec.js.map +1 -0
- package/dist/astUtils/creators.d.ts +10 -10
- package/dist/astUtils/creators.js +26 -16
- 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 +208 -126
- 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 +178 -33
- 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 +10 -2
- package/dist/bscPlugin/BscPlugin.js +33 -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 +135 -0
- package/dist/bscPlugin/SignatureHelpUtil.js.map +1 -0
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +14 -11
- 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/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 +85 -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.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} +33 -9
- 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 +259 -49
- 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 +54 -27
- package/dist/bscPlugin/validation/ScopeValidator.js +483 -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 +2454 -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 +112 -111
- package/dist/files/BrsFile.js +741 -1032
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1728 -1232
- 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 +389 -161
- 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 +126 -176
- package/dist/parser/Expression.js +523 -405
- 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 +43 -201
- package/dist/parser/Parser.js +446 -962
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.d.ts +3 -1
- package/dist/parser/Parser.spec.js +1002 -846
- 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 +183 -131
- package/dist/parser/Statement.js +549 -387
- package/dist/parser/Statement.js.map +1 -1
- package/dist/parser/Statement.spec.js +45 -21
- 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 +61 -20
- 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 +67 -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 +35 -33
- 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 +164 -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 +132 -137
- package/dist/util.js +796 -362
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +8 -25
- package/dist/validators/ClassValidator.js +96 -176
- 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/serialize/BslibInjector.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
|
/**
|
|
@@ -28,11 +22,6 @@ class Parser {
|
|
|
28
22
|
* The list of statements for the parsed file
|
|
29
23
|
*/
|
|
30
24
|
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();
|
|
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
34
|
/**
|
|
50
|
-
*
|
|
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
|
|
35
|
+
* The top-level symbol table for the body of this file.
|
|
54
36
|
*/
|
|
55
|
-
get
|
|
56
|
-
|
|
57
|
-
if (!this._references) {
|
|
58
|
-
this.findReferences();
|
|
59
|
-
}
|
|
60
|
-
return this._references;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Invalidates (clears) the references collection. This should be called anytime the AST has been manipulated.
|
|
64
|
-
*/
|
|
65
|
-
invalidateReferences() {
|
|
66
|
-
this._references = undefined;
|
|
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([]);
|
|
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,112 @@ 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.equal = this.advance();
|
|
245
|
-
value = this.expression();
|
|
197
|
+
statement.tokens.equal = 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, asToken, typeExpression, optionalKeyword);
|
|
213
|
+
}
|
|
214
|
+
consumeAsTokenAndTypeExpression() {
|
|
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
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
|
|
221
|
+
//consume the statement separator
|
|
222
|
+
this.consumeStatementSeparators();
|
|
223
|
+
}
|
|
224
|
+
else if (this.peek().kind !== TokenKind_1.TokenKind.Identifier && !this.checkAny(...TokenKind_1.DeclarableTypes, ...TokenKind_1.AllowedTypeIdentifiers)) {
|
|
225
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(asToken.text)), { range: asToken.range }));
|
|
263
226
|
}
|
|
227
|
+
else {
|
|
228
|
+
typeExpression = this.typeExpression();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return [asToken, typeExpression];
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration()`
|
|
235
|
+
*/
|
|
236
|
+
interfaceMethodStatement(optionalKeyword) {
|
|
237
|
+
const functionType = this.advance();
|
|
238
|
+
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
239
|
+
const leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.LeftParen), TokenKind_1.TokenKind.LeftParen);
|
|
240
|
+
let params = [];
|
|
241
|
+
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
242
|
+
do {
|
|
243
|
+
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
244
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableParameters(params.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
245
|
+
}
|
|
246
|
+
params.push(this.functionParameter());
|
|
247
|
+
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
264
248
|
}
|
|
265
|
-
|
|
249
|
+
const rightParen = this.consumeToken(TokenKind_1.TokenKind.RightParen);
|
|
250
|
+
// let asToken = null as Token;
|
|
251
|
+
// let returnTypeExpression: TypeExpression;
|
|
252
|
+
let asToken;
|
|
253
|
+
let returnTypeExpression;
|
|
254
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
255
|
+
[asToken, returnTypeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
256
|
+
}
|
|
257
|
+
return new Statement_1.InterfaceMethodStatement(functionType, name, leftParen, params, rightParen, asToken, returnTypeExpression, optionalKeyword);
|
|
266
258
|
}
|
|
267
259
|
interfaceDeclaration() {
|
|
268
260
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
269
261
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
270
262
|
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);
|
|
263
|
+
const nameToken = this.identifier(...this.allowedLocalIdentifiers);
|
|
273
264
|
let extendsToken;
|
|
274
265
|
let parentInterfaceName;
|
|
275
266
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
276
267
|
extendsToken = this.advance();
|
|
277
|
-
|
|
268
|
+
if (this.checkEndOfStatement()) {
|
|
269
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(extendsToken.text)), { range: extendsToken.range }));
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
parentInterfaceName = this.typeExpression();
|
|
273
|
+
}
|
|
278
274
|
}
|
|
279
275
|
this.consumeStatementSeparators();
|
|
280
276
|
//gather up all interface members (Fields, Methods)
|
|
281
277
|
let body = [];
|
|
282
278
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
283
279
|
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
280
|
let decl;
|
|
289
281
|
//collect leading annotations
|
|
290
282
|
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
291
283
|
this.annotationExpression();
|
|
292
284
|
}
|
|
285
|
+
const optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
|
|
293
286
|
//fields
|
|
294
|
-
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.
|
|
287
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties) && this.checkAnyNext(TokenKind_1.TokenKind.As, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
288
|
+
decl = this.interfaceFieldStatement(optionalKeyword);
|
|
289
|
+
//field with name = 'optional'
|
|
290
|
+
}
|
|
291
|
+
else if (optionalKeyword && this.checkAny(TokenKind_1.TokenKind.As, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
292
|
+
//rewind one place, so that 'optional' is the field name
|
|
293
|
+
this.current--;
|
|
295
294
|
decl = this.interfaceFieldStatement();
|
|
296
295
|
//methods (function/sub keyword followed by opening paren)
|
|
297
296
|
}
|
|
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;
|
|
297
|
+
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
298
|
+
decl = this.interfaceMethodStatement(optionalKeyword);
|
|
308
299
|
//comments
|
|
309
300
|
}
|
|
310
301
|
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
@@ -314,6 +305,10 @@ class Parser {
|
|
|
314
305
|
this.consumePendingAnnotations(decl);
|
|
315
306
|
body.push(decl);
|
|
316
307
|
}
|
|
308
|
+
else {
|
|
309
|
+
//we didn't find a declaration...flag tokens until next line
|
|
310
|
+
this.flagUntil(TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Eof);
|
|
311
|
+
}
|
|
317
312
|
}
|
|
318
313
|
catch (e) {
|
|
319
314
|
//throw out any failed members and move on to the next line
|
|
@@ -321,24 +316,23 @@ class Parser {
|
|
|
321
316
|
}
|
|
322
317
|
//ensure statement separator
|
|
323
318
|
this.consumeStatementSeparators();
|
|
319
|
+
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
320
|
+
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
324
323
|
}
|
|
325
324
|
//consume the final `end interface` token
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('interface')), { range: endingKeyword.range }));
|
|
329
|
-
}
|
|
330
|
-
const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endingKeyword, this.currentNamespaceName);
|
|
331
|
-
this._references.interfaceStatements.push(statement);
|
|
325
|
+
const endInterfaceToken = this.consumeToken(TokenKind_1.TokenKind.EndInterface);
|
|
326
|
+
const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endInterfaceToken);
|
|
332
327
|
this.exitAnnotationBlock(parentAnnotations);
|
|
333
328
|
return statement;
|
|
334
329
|
}
|
|
335
330
|
enumDeclaration() {
|
|
331
|
+
const result = new Statement_1.EnumStatement({}, []);
|
|
336
332
|
this.warnIfNotBrighterScriptMode('enum declarations');
|
|
337
333
|
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();
|
|
334
|
+
result.tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
|
|
335
|
+
result.tokens.name = this.tryIdentifier(...this.allowedLocalIdentifiers);
|
|
342
336
|
this.consumeStatementSeparators();
|
|
343
337
|
//gather up all members
|
|
344
338
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
@@ -358,7 +352,7 @@ class Parser {
|
|
|
358
352
|
}
|
|
359
353
|
if (decl) {
|
|
360
354
|
this.consumePendingAnnotations(decl);
|
|
361
|
-
body.push(decl);
|
|
355
|
+
result.body.push(decl);
|
|
362
356
|
}
|
|
363
357
|
else {
|
|
364
358
|
//we didn't find a declaration...flag tokens until next line
|
|
@@ -377,12 +371,7 @@ class Parser {
|
|
|
377
371
|
}
|
|
378
372
|
}
|
|
379
373
|
//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);
|
|
374
|
+
result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
|
|
386
375
|
this.exitAnnotationBlock(parentAnnotations);
|
|
387
376
|
return result;
|
|
388
377
|
}
|
|
@@ -400,7 +389,12 @@ class Parser {
|
|
|
400
389
|
//see if the class inherits from parent
|
|
401
390
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
402
391
|
extendsKeyword = this.advance();
|
|
403
|
-
|
|
392
|
+
if (this.checkEndOfStatement()) {
|
|
393
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(extendsKeyword.text)), { range: extendsKeyword.range }));
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
parentClassName = this.typeExpression();
|
|
397
|
+
}
|
|
404
398
|
}
|
|
405
399
|
//ensure statement separator
|
|
406
400
|
this.consumeStatementSeparators();
|
|
@@ -423,16 +417,14 @@ class Parser {
|
|
|
423
417
|
}
|
|
424
418
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
425
419
|
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
|
|
420
|
+
const funcDeclaration = this.functionDeclaration(false, false);
|
|
427
421
|
//if we have an overrides keyword AND this method is called 'new', that's not allowed
|
|
428
|
-
if (overrideKeyword &&
|
|
422
|
+
if (overrideKeyword && funcDeclaration.name.text.toLowerCase() === 'new') {
|
|
429
423
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
|
|
430
424
|
}
|
|
431
|
-
decl = new Statement_1.MethodStatement(accessModifier,
|
|
425
|
+
decl = new Statement_1.MethodStatement(accessModifier, funcDeclaration.name, funcDeclaration.func, overrideKeyword);
|
|
432
426
|
//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();
|
|
427
|
+
funcDeclaration.func.functionStatement = decl;
|
|
436
428
|
//fields
|
|
437
429
|
}
|
|
438
430
|
else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
@@ -462,26 +454,43 @@ class Parser {
|
|
|
462
454
|
if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
|
|
463
455
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
|
|
464
456
|
}
|
|
465
|
-
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName
|
|
466
|
-
if (className) {
|
|
467
|
-
this.currentSymbolTable.addSymbol(className.text, className.range, result.getConstructorFunctionType());
|
|
468
|
-
}
|
|
469
|
-
this._references.classStatements.push(result);
|
|
457
|
+
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName);
|
|
470
458
|
this.exitAnnotationBlock(parentAnnotations);
|
|
471
459
|
return result;
|
|
472
460
|
}
|
|
473
461
|
fieldDeclaration(accessModifier) {
|
|
462
|
+
let optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
|
|
463
|
+
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
464
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
465
|
+
if (this.checkAnyNext(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Newline)) {
|
|
466
|
+
// as <EOL>
|
|
467
|
+
// `as` is the field name
|
|
468
|
+
}
|
|
469
|
+
else if (this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
470
|
+
// as as ____
|
|
471
|
+
// first `as` is the field name
|
|
472
|
+
}
|
|
473
|
+
else if (optionalKeyword) {
|
|
474
|
+
// optional as ____
|
|
475
|
+
// optional is the field name, `as` starts type
|
|
476
|
+
// rewind current token
|
|
477
|
+
optionalKeyword = null;
|
|
478
|
+
this.current--;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
// no name after `optional` ... optional is the name
|
|
484
|
+
// rewind current token
|
|
485
|
+
optionalKeyword = null;
|
|
486
|
+
this.current--;
|
|
487
|
+
}
|
|
474
488
|
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
475
489
|
let asToken;
|
|
476
|
-
let
|
|
490
|
+
let fieldTypeExpression;
|
|
477
491
|
//look for `as SOME_TYPE`
|
|
478
492
|
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
|
-
}
|
|
493
|
+
[asToken, fieldTypeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
485
494
|
}
|
|
486
495
|
let initialValue;
|
|
487
496
|
let equal;
|
|
@@ -490,43 +499,22 @@ class Parser {
|
|
|
490
499
|
equal = this.advance();
|
|
491
500
|
initialValue = this.expression();
|
|
492
501
|
}
|
|
493
|
-
return new Statement_1.FieldStatement(accessModifier, name, asToken,
|
|
494
|
-
}
|
|
495
|
-
functionStatement(options) {
|
|
496
|
-
options.hasName = true;
|
|
497
|
-
const funcResult = this.functionDeclaration(options);
|
|
498
|
-
if (funcResult) {
|
|
499
|
-
let result = new Statement_1.FunctionStatement(funcResult.name, funcResult.functionExpression, this.currentNamespaceName);
|
|
500
|
-
funcResult.functionExpression.functionStatement = result;
|
|
501
|
-
if (!options.onlyCallableAsMember) {
|
|
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
|
-
}
|
|
502
|
+
return new Statement_1.FieldStatement(accessModifier, name, asToken, fieldTypeExpression, equal, initialValue, optionalKeyword);
|
|
515
503
|
}
|
|
516
|
-
functionDeclaration(
|
|
517
|
-
var _a
|
|
504
|
+
functionDeclaration(isAnonymous, checkIdentifier = true, onlyCallableAsMember = false) {
|
|
505
|
+
var _a;
|
|
518
506
|
let previousCallExpressions = this.callExpressions;
|
|
519
507
|
this.callExpressions = [];
|
|
520
508
|
try {
|
|
521
509
|
//track depth to help certain statements need to know if they are contained within a function body
|
|
522
510
|
this.namespaceAndFunctionDepth++;
|
|
523
|
-
let
|
|
511
|
+
let functionType;
|
|
524
512
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
525
|
-
|
|
513
|
+
functionType = this.advance();
|
|
526
514
|
}
|
|
527
515
|
else {
|
|
528
516
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
|
|
529
|
-
|
|
517
|
+
functionType = {
|
|
530
518
|
isReserved: true,
|
|
531
519
|
kind: TokenKind_1.TokenKind.Function,
|
|
532
520
|
text: 'function',
|
|
@@ -535,33 +523,34 @@ class Parser {
|
|
|
535
523
|
start: this.peek().range.start,
|
|
536
524
|
end: this.peek().range.start
|
|
537
525
|
},
|
|
538
|
-
leadingWhitespace: ''
|
|
526
|
+
leadingWhitespace: '',
|
|
527
|
+
leadingTrivia: []
|
|
539
528
|
};
|
|
540
529
|
}
|
|
541
|
-
let isSub = (
|
|
542
|
-
let
|
|
530
|
+
let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
|
|
531
|
+
let functionTypeText = isSub ? 'sub' : 'function';
|
|
543
532
|
let name;
|
|
544
533
|
let leftParen;
|
|
545
|
-
if (
|
|
546
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(
|
|
534
|
+
if (isAnonymous) {
|
|
535
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
547
536
|
}
|
|
548
537
|
else {
|
|
549
|
-
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(
|
|
550
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(
|
|
538
|
+
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(functionTypeText), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
539
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallableName(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
551
540
|
//prevent functions from ending with type designators
|
|
552
541
|
let lastChar = name.text[name.text.length - 1];
|
|
553
542
|
if (['$', '%', '!', '#', '&'].includes(lastChar)) {
|
|
554
543
|
//don't throw this error; let the parser continue
|
|
555
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(
|
|
544
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionNameCannotEndWithTypeDesignator(functionTypeText, name.text, lastChar)), { range: name.range }));
|
|
556
545
|
}
|
|
557
|
-
//flag functions with keywords for names (only for standard functions
|
|
558
|
-
if (
|
|
546
|
+
//flag functions with keywords for names (only for standard functions)
|
|
547
|
+
if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
|
|
559
548
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
560
549
|
}
|
|
561
550
|
}
|
|
562
551
|
let params = [];
|
|
563
552
|
let asToken;
|
|
564
|
-
let
|
|
553
|
+
let typeExpression;
|
|
565
554
|
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
566
555
|
do {
|
|
567
556
|
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
@@ -572,11 +561,7 @@ class Parser {
|
|
|
572
561
|
}
|
|
573
562
|
let rightParen = this.advance();
|
|
574
563
|
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
|
-
}
|
|
564
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
580
565
|
}
|
|
581
566
|
params.reduce((haveFoundOptional, param) => {
|
|
582
567
|
if (haveFoundOptional && !param.defaultValue) {
|
|
@@ -584,57 +569,39 @@ class Parser {
|
|
|
584
569
|
}
|
|
585
570
|
return haveFoundOptional || !!param.defaultValue;
|
|
586
571
|
}, false);
|
|
587
|
-
|
|
588
|
-
// do not go to next statement - we don't care about any other statement
|
|
589
|
-
this.consumeStatementSeparators(true);
|
|
590
|
-
}
|
|
591
|
-
// Can Not use the current function expression symbol table for a function expression inside of itself
|
|
592
|
-
const funcExprParentSymbolTable = (_c = (_b = this.currentNamespace) === null || _b === void 0 ? void 0 : _b.symbolTable) !== null && _c !== void 0 ? _c : this.symbolTable;
|
|
572
|
+
this.consumeStatementSeparators(true);
|
|
593
573
|
let func = new Expression_1.FunctionExpression(params, undefined, //body
|
|
594
|
-
|
|
595
|
-
leftParen, rightParen, asToken,
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
if
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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
|
-
}
|
|
574
|
+
functionType, undefined, //ending keyword
|
|
575
|
+
leftParen, rightParen, asToken, typeExpression);
|
|
576
|
+
//support ending the function with `end sub` OR `end function`
|
|
577
|
+
func.body = this.block();
|
|
578
|
+
//if the parser was unable to produce a block, make an empty one so the AST makes some sense...
|
|
579
|
+
if (!func.body) {
|
|
580
|
+
func.body = new Statement_1.Block([], util_1.util.createRangeFromPositions(func.range.start, func.range.start));
|
|
581
|
+
}
|
|
582
|
+
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());
|
|
583
|
+
if (!func.body) {
|
|
584
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionTypeText)), { range: this.peek().range }));
|
|
585
|
+
throw this.lastDiagnosticAsError();
|
|
624
586
|
}
|
|
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
|
-
}
|
|
587
|
+
// consume 'end sub' or 'end function'
|
|
588
|
+
func.end = this.advance();
|
|
589
|
+
let expectedEndKind = isSub ? TokenKind_1.TokenKind.EndSub : TokenKind_1.TokenKind.EndFunction;
|
|
590
|
+
//if `function` is ended with `end sub`, or `sub` is ended with `end function`, then
|
|
591
|
+
//add an error but don't hard-fail so the AST can continue more gracefully
|
|
592
|
+
if (func.end.kind !== expectedEndKind) {
|
|
593
|
+
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionTypeText, func.end.text)), { range: func.end.range }));
|
|
634
594
|
}
|
|
635
595
|
func.callExpressions = this.callExpressions;
|
|
636
|
-
|
|
637
|
-
|
|
596
|
+
if (isAnonymous) {
|
|
597
|
+
return func;
|
|
598
|
+
}
|
|
599
|
+
else {
|
|
600
|
+
let result = new Statement_1.FunctionStatement(name, func);
|
|
601
|
+
func.symbolTable.name += `: '${name === null || name === void 0 ? void 0 : name.text}'`;
|
|
602
|
+
func.functionStatement = result;
|
|
603
|
+
return result;
|
|
604
|
+
}
|
|
638
605
|
}
|
|
639
606
|
finally {
|
|
640
607
|
this.namespaceAndFunctionDepth--;
|
|
@@ -647,42 +614,25 @@ class Parser {
|
|
|
647
614
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
|
|
648
615
|
throw this.lastDiagnosticAsError();
|
|
649
616
|
}
|
|
650
|
-
|
|
651
|
-
|
|
617
|
+
let name = this.advance();
|
|
618
|
+
// force the name into an identifier so the AST makes some sense
|
|
619
|
+
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
620
|
+
let typeExpression;
|
|
652
621
|
let defaultValue;
|
|
653
|
-
let
|
|
622
|
+
let equalToken;
|
|
654
623
|
// parse argument default value
|
|
655
|
-
if (this.
|
|
656
|
-
equalsToken = this.previous();
|
|
624
|
+
if ((equalToken = this.consumeTokenIf(TokenKind_1.TokenKind.Equal))) {
|
|
657
625
|
// it seems any expression is allowed here -- including ones that operate on other arguments!
|
|
658
|
-
defaultValue = this.expression();
|
|
626
|
+
defaultValue = this.expression(false);
|
|
659
627
|
}
|
|
660
628
|
let asToken = null;
|
|
661
629
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
662
|
-
asToken = this.
|
|
663
|
-
typeExpr = this.typeExpression();
|
|
664
|
-
if (!typeExpr.isValidType(this.options.mode)) {
|
|
665
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
|
|
666
|
-
throw this.lastDiagnosticAsError();
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
let typeInContext;
|
|
670
|
-
if (typeExpr) {
|
|
671
|
-
typeInContext = typeExpr.type;
|
|
630
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
672
631
|
}
|
|
673
|
-
|
|
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);
|
|
632
|
+
return new Expression_1.FunctionParameterExpression(name, equalToken, defaultValue, asToken, typeExpression);
|
|
683
633
|
}
|
|
684
634
|
assignment() {
|
|
685
|
-
let name = this.
|
|
635
|
+
let name = this.advance();
|
|
686
636
|
//add diagnostic if name is a reserved word that cannot be used as an identifier
|
|
687
637
|
if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
|
|
688
638
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
@@ -691,21 +641,12 @@ class Parser {
|
|
|
691
641
|
let value = this.expression();
|
|
692
642
|
let result;
|
|
693
643
|
if (operator.kind === TokenKind_1.TokenKind.Equal) {
|
|
694
|
-
result = new Statement_1.AssignmentStatement(
|
|
644
|
+
result = new Statement_1.AssignmentStatement(operator, name, value);
|
|
695
645
|
}
|
|
696
646
|
else {
|
|
697
|
-
const nameExpression = new Expression_1.VariableExpression(name
|
|
698
|
-
result = new Statement_1.AssignmentStatement(
|
|
699
|
-
|
|
700
|
-
if ((0, reflection_1.isBinaryExpression)(value)) {
|
|
701
|
-
//remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
|
|
702
|
-
this._references.expressions.delete(value);
|
|
703
|
-
}
|
|
704
|
-
this._references.expressions.add(result);
|
|
705
|
-
}
|
|
706
|
-
this._references.assignmentStatements.push(result);
|
|
707
|
-
const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
|
|
708
|
-
this.currentSymbolTable.addSymbol(name.text, name.range, assignmentType);
|
|
647
|
+
const nameExpression = new Expression_1.VariableExpression(name);
|
|
648
|
+
result = new Statement_1.AssignmentStatement(operator, name, new Expression_1.BinaryExpression(nameExpression, operator, value));
|
|
649
|
+
}
|
|
709
650
|
return result;
|
|
710
651
|
}
|
|
711
652
|
checkLibrary() {
|
|
@@ -774,6 +715,10 @@ class Parser {
|
|
|
774
715
|
if (this.check(TokenKind_1.TokenKind.Goto)) {
|
|
775
716
|
return this.gotoStatement();
|
|
776
717
|
}
|
|
718
|
+
//the continue keyword (followed by `for`, `while`, or a statement separator)
|
|
719
|
+
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)) {
|
|
720
|
+
return this.continueStatement();
|
|
721
|
+
}
|
|
777
722
|
//does this line look like a label? (i.e. `someIdentifier:` )
|
|
778
723
|
if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
|
|
779
724
|
try {
|
|
@@ -863,7 +808,7 @@ class Parser {
|
|
|
863
808
|
}
|
|
864
809
|
forEachStatement() {
|
|
865
810
|
let forEach = this.advance();
|
|
866
|
-
let name = this.
|
|
811
|
+
let name = this.advance();
|
|
867
812
|
let maybeIn = this.peek();
|
|
868
813
|
if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
|
|
869
814
|
this.advance();
|
|
@@ -877,12 +822,6 @@ class Parser {
|
|
|
877
822
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
|
|
878
823
|
throw this.lastDiagnosticAsError();
|
|
879
824
|
}
|
|
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
825
|
this.consumeStatementSeparators();
|
|
887
826
|
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
888
827
|
if (!body) {
|
|
@@ -890,7 +829,11 @@ class Parser {
|
|
|
890
829
|
throw this.lastDiagnosticAsError();
|
|
891
830
|
}
|
|
892
831
|
let endFor = this.advance();
|
|
893
|
-
return new Statement_1.ForEachStatement(
|
|
832
|
+
return new Statement_1.ForEachStatement({
|
|
833
|
+
forEach: forEach,
|
|
834
|
+
in: maybeIn,
|
|
835
|
+
endFor: endFor
|
|
836
|
+
}, name, target, body);
|
|
894
837
|
}
|
|
895
838
|
exitFor() {
|
|
896
839
|
let keyword = this.advance();
|
|
@@ -915,19 +858,13 @@ class Parser {
|
|
|
915
858
|
namespaceStatement() {
|
|
916
859
|
this.warnIfNotBrighterScriptMode('namespace');
|
|
917
860
|
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
861
|
this.namespaceAndFunctionDepth++;
|
|
922
|
-
let name = this.
|
|
862
|
+
let name = this.identifyingExpression();
|
|
923
863
|
//set the current namespace name
|
|
924
|
-
let result = new Statement_1.NamespaceStatement(keyword, name, null, null
|
|
925
|
-
this.currentNamespace = result;
|
|
864
|
+
let result = new Statement_1.NamespaceStatement(keyword, name, null, null);
|
|
926
865
|
this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
|
|
927
866
|
let body = this.body();
|
|
928
867
|
this.globalTerminators.pop();
|
|
929
|
-
//unset the current namespace name
|
|
930
|
-
this.currentNamespace = undefined;
|
|
931
868
|
let endKeyword;
|
|
932
869
|
if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
|
|
933
870
|
endKeyword = this.advance();
|
|
@@ -939,24 +876,22 @@ class Parser {
|
|
|
939
876
|
this.namespaceAndFunctionDepth--;
|
|
940
877
|
result.body = body;
|
|
941
878
|
result.endKeyword = endKeyword;
|
|
942
|
-
this._references.namespaceStatements.push(result);
|
|
943
879
|
//cache the range property so that plugins can't affect it
|
|
944
880
|
result.cacheRange();
|
|
945
|
-
|
|
946
|
-
this.symbolTable.addSymbol(result.name.split('.')[0], result.nameExpression.range, DynamicType_1.DynamicType.instance);
|
|
947
|
-
}
|
|
881
|
+
result.body.symbolTable.name += `: namespace '${result.name}'`;
|
|
948
882
|
return result;
|
|
949
883
|
}
|
|
950
884
|
/**
|
|
951
885
|
* Get an expression with identifiers separated by periods. Useful for namespaces and class extends
|
|
952
886
|
*/
|
|
953
|
-
|
|
954
|
-
|
|
887
|
+
identifyingExpression(allowedTokenKinds) {
|
|
888
|
+
allowedTokenKinds = allowedTokenKinds !== null && allowedTokenKinds !== void 0 ? allowedTokenKinds : this.allowedLocalIdentifiers;
|
|
889
|
+
let firstIdentifier = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword(this.previous().text), TokenKind_1.TokenKind.Identifier, ...allowedTokenKinds);
|
|
955
890
|
let expr;
|
|
956
891
|
if (firstIdentifier) {
|
|
957
892
|
// force it into an identifier so the AST makes some sense
|
|
958
893
|
firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
959
|
-
const varExpr = new Expression_1.VariableExpression(firstIdentifier
|
|
894
|
+
const varExpr = new Expression_1.VariableExpression(firstIdentifier);
|
|
960
895
|
expr = varExpr;
|
|
961
896
|
//consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
|
|
962
897
|
while (this.check(TokenKind_1.TokenKind.Dot)) {
|
|
@@ -964,7 +899,7 @@ class Parser {
|
|
|
964
899
|
if (!dot) {
|
|
965
900
|
break;
|
|
966
901
|
}
|
|
967
|
-
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...
|
|
902
|
+
let identifier = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifier(), TokenKind_1.TokenKind.Identifier, ...allowedTokenKinds, ...TokenKind_1.AllowedProperties);
|
|
968
903
|
if (!identifier) {
|
|
969
904
|
break;
|
|
970
905
|
}
|
|
@@ -973,7 +908,7 @@ class Parser {
|
|
|
973
908
|
expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
|
|
974
909
|
}
|
|
975
910
|
}
|
|
976
|
-
return
|
|
911
|
+
return expr;
|
|
977
912
|
}
|
|
978
913
|
/**
|
|
979
914
|
* Add an 'unexpected token' diagnostic for any token found between current and the first stopToken found.
|
|
@@ -986,8 +921,8 @@ class Parser {
|
|
|
986
921
|
}
|
|
987
922
|
/**
|
|
988
923
|
* Consume tokens until one of the `stopTokenKinds` is encountered
|
|
989
|
-
* @param tokenKinds
|
|
990
|
-
* @
|
|
924
|
+
* @param stopTokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
|
|
925
|
+
* @returns - the list of tokens consumed, EXCLUDING the `stopTokenKind` (you can use `this.peek()` to see which one it was)
|
|
991
926
|
*/
|
|
992
927
|
consumeUntil(...stopTokenKinds) {
|
|
993
928
|
let result = [];
|
|
@@ -1007,11 +942,7 @@ class Parser {
|
|
|
1007
942
|
const: constToken,
|
|
1008
943
|
name: nameToken,
|
|
1009
944
|
equals: equalToken
|
|
1010
|
-
}, expression
|
|
1011
|
-
if (nameToken) {
|
|
1012
|
-
this.currentSymbolTable.addSymbol(nameToken.text, nameToken.range, getBscTypeFromExpression(expression));
|
|
1013
|
-
}
|
|
1014
|
-
this._references.constStatements.push(statement);
|
|
945
|
+
}, expression);
|
|
1015
946
|
return statement;
|
|
1016
947
|
}
|
|
1017
948
|
libraryStatement() {
|
|
@@ -1020,7 +951,6 @@ class Parser {
|
|
|
1020
951
|
//grab the next token only if it's a string
|
|
1021
952
|
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
|
|
1022
953
|
});
|
|
1023
|
-
this._references.libraryStatements.push(libStatement);
|
|
1024
954
|
return libStatement;
|
|
1025
955
|
}
|
|
1026
956
|
importStatement() {
|
|
@@ -1028,7 +958,6 @@ class Parser {
|
|
|
1028
958
|
let importStatement = new Statement_1.ImportStatement(this.advance(),
|
|
1029
959
|
//grab the next token only if it's a string
|
|
1030
960
|
this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
|
|
1031
|
-
this._references.importStatements.push(importStatement);
|
|
1032
961
|
return importStatement;
|
|
1033
962
|
}
|
|
1034
963
|
annotationExpression() {
|
|
@@ -1044,8 +973,6 @@ class Parser {
|
|
|
1044
973
|
let leftParen = this.advance();
|
|
1045
974
|
annotation.call = this.finishCall(leftParen, annotation, false);
|
|
1046
975
|
}
|
|
1047
|
-
//cache the range property so that plugins can't affect it
|
|
1048
|
-
annotation.cacheRange();
|
|
1049
976
|
return annotation;
|
|
1050
977
|
}
|
|
1051
978
|
ternaryExpression(test) {
|
|
@@ -1184,9 +1111,6 @@ class Parser {
|
|
|
1184
1111
|
else {
|
|
1185
1112
|
statement.tokens.endTry = this.advance();
|
|
1186
1113
|
}
|
|
1187
|
-
if (exceptionVarToken) {
|
|
1188
|
-
this.currentSymbolTable.addSymbol(exceptionVarToken.text, exceptionVarToken.range, DynamicType_1.DynamicType.instance);
|
|
1189
|
-
}
|
|
1190
1114
|
return statement;
|
|
1191
1115
|
}
|
|
1192
1116
|
throwStatement() {
|
|
@@ -1229,9 +1153,6 @@ class Parser {
|
|
|
1229
1153
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingExpressionsInDimStatement()), { range: this.peek().range }));
|
|
1230
1154
|
}
|
|
1231
1155
|
let rightSquareBracket = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.missingRightSquareBracketAfterDimIdentifier(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1232
|
-
if (identifier) {
|
|
1233
|
-
this.currentSymbolTable.addSymbol(identifier.text, identifier.range, new ArrayType_1.ArrayType(DynamicType_1.DynamicType.instance));
|
|
1234
|
-
}
|
|
1235
1156
|
return new Statement_1.DimStatement(dim, identifier, leftSquareBracket, expressions, rightSquareBracket);
|
|
1236
1157
|
}
|
|
1237
1158
|
ifStatement() {
|
|
@@ -1429,17 +1350,14 @@ class Parser {
|
|
|
1429
1350
|
throw this.lastDiagnosticAsError();
|
|
1430
1351
|
}
|
|
1431
1352
|
const result = new Statement_1.IncrementStatement(expr, operator);
|
|
1432
|
-
this._references.expressions.add(result);
|
|
1433
1353
|
return result;
|
|
1434
1354
|
}
|
|
1435
1355
|
if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
|
|
1436
1356
|
return new Statement_1.ExpressionStatement(expr);
|
|
1437
1357
|
}
|
|
1438
|
-
//at this point, it's probably an error. However, we recover a little more gracefully by creating an
|
|
1358
|
+
//at this point, it's probably an error. However, we recover a little more gracefully by creating an inclosing ExpressionStatement
|
|
1439
1359
|
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();
|
|
1360
|
+
return new Statement_1.ExpressionStatement(expr);
|
|
1443
1361
|
}
|
|
1444
1362
|
setStatement() {
|
|
1445
1363
|
/**
|
|
@@ -1457,17 +1375,18 @@ class Parser {
|
|
|
1457
1375
|
if ((0, reflection_1.isIndexedGetExpression)(left)) {
|
|
1458
1376
|
return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1459
1377
|
? right
|
|
1460
|
-
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare
|
|
1378
|
+
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
|
|
1461
1379
|
}
|
|
1462
1380
|
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1381
|
+
return new Statement_1.DottedSetStatement(left.obj, left.name, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1382
|
+
? right
|
|
1383
|
+
: new Expression_1.BinaryExpression(left, operator, right), left.dot);
|
|
1466
1384
|
}
|
|
1467
1385
|
}
|
|
1468
1386
|
return this.expressionStatement(expr);
|
|
1469
1387
|
}
|
|
1470
1388
|
printStatement() {
|
|
1389
|
+
var _a;
|
|
1471
1390
|
let printKeyword = this.advance();
|
|
1472
1391
|
let values = [];
|
|
1473
1392
|
while (!this.checkEndOfStatement()) {
|
|
@@ -1486,7 +1405,8 @@ class Parser {
|
|
|
1486
1405
|
}
|
|
1487
1406
|
//print statements can be empty, so look for empty print conditions
|
|
1488
1407
|
if (!values.length) {
|
|
1489
|
-
|
|
1408
|
+
const endOfStatementRange = util_1.util.createRangeFromPositions(printKeyword.range.end, (_a = this.peek()) === null || _a === void 0 ? void 0 : _a.range.end);
|
|
1409
|
+
let emptyStringLiteral = (0, creators_1.createStringLiteral)('', endOfStatementRange);
|
|
1490
1410
|
values.push(emptyStringLiteral);
|
|
1491
1411
|
}
|
|
1492
1412
|
let last = values[values.length - 1];
|
|
@@ -1522,9 +1442,16 @@ class Parser {
|
|
|
1522
1442
|
this.current -= 2;
|
|
1523
1443
|
throw new CancelStatementError();
|
|
1524
1444
|
}
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1445
|
+
return new Statement_1.LabelStatement(tokens);
|
|
1446
|
+
}
|
|
1447
|
+
/**
|
|
1448
|
+
* Parses a `continue` statement
|
|
1449
|
+
*/
|
|
1450
|
+
continueStatement() {
|
|
1451
|
+
return new Statement_1.ContinueStatement({
|
|
1452
|
+
continue: this.advance(),
|
|
1453
|
+
loopType: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For), TokenKind_1.TokenKind.While, TokenKind_1.TokenKind.For)
|
|
1454
|
+
});
|
|
1528
1455
|
}
|
|
1529
1456
|
/**
|
|
1530
1457
|
* Parses a `goto` statement
|
|
@@ -1629,14 +1556,32 @@ class Parser {
|
|
|
1629
1556
|
}
|
|
1630
1557
|
this.pendingAnnotations = parentAnnotations;
|
|
1631
1558
|
}
|
|
1632
|
-
expression() {
|
|
1633
|
-
|
|
1634
|
-
|
|
1559
|
+
expression(findTypeCast = true) {
|
|
1560
|
+
let expression = this.anonymousFunction();
|
|
1561
|
+
let asToken;
|
|
1562
|
+
let typeExpression;
|
|
1563
|
+
if (findTypeCast) {
|
|
1564
|
+
do {
|
|
1565
|
+
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
1566
|
+
this.warnIfNotBrighterScriptMode('type cast');
|
|
1567
|
+
// Check if this expression is wrapped in any type casts
|
|
1568
|
+
// allows for multiple casts:
|
|
1569
|
+
// myVal = foo() as dynamic as string
|
|
1570
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
1571
|
+
if (asToken && typeExpression) {
|
|
1572
|
+
expression = new Expression_1.TypeCastExpression(expression, asToken, typeExpression);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
else {
|
|
1576
|
+
break;
|
|
1577
|
+
}
|
|
1578
|
+
} while (asToken && typeExpression);
|
|
1579
|
+
}
|
|
1635
1580
|
return expression;
|
|
1636
1581
|
}
|
|
1637
1582
|
anonymousFunction() {
|
|
1638
1583
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
1639
|
-
const func = this.functionDeclaration(
|
|
1584
|
+
const func = this.functionDeclaration(true);
|
|
1640
1585
|
//if there's an open paren after this, this is an IIFE
|
|
1641
1586
|
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1642
1587
|
return this.finishCall(this.advance(), func);
|
|
@@ -1661,7 +1606,6 @@ class Parser {
|
|
|
1661
1606
|
while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
|
|
1662
1607
|
let operator = this.previous();
|
|
1663
1608
|
let right = this.relational();
|
|
1664
|
-
this.addExpressionsToReferences(expr, right);
|
|
1665
1609
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1666
1610
|
}
|
|
1667
1611
|
return expr;
|
|
@@ -1671,25 +1615,16 @@ class Parser {
|
|
|
1671
1615
|
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
1616
|
let operator = this.previous();
|
|
1673
1617
|
let right = this.additive();
|
|
1674
|
-
this.addExpressionsToReferences(expr, right);
|
|
1675
1618
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1676
1619
|
}
|
|
1677
1620
|
return expr;
|
|
1678
1621
|
}
|
|
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
1622
|
// TODO: bitshift
|
|
1687
1623
|
additive() {
|
|
1688
1624
|
let expr = this.multiplicative();
|
|
1689
1625
|
while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
|
|
1690
1626
|
let operator = this.previous();
|
|
1691
1627
|
let right = this.multiplicative();
|
|
1692
|
-
this.addExpressionsToReferences(expr, right);
|
|
1693
1628
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1694
1629
|
}
|
|
1695
1630
|
return expr;
|
|
@@ -1699,7 +1634,6 @@ class Parser {
|
|
|
1699
1634
|
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
1635
|
let operator = this.previous();
|
|
1701
1636
|
let right = this.exponential();
|
|
1702
|
-
this.addExpressionsToReferences(expr, right);
|
|
1703
1637
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1704
1638
|
}
|
|
1705
1639
|
return expr;
|
|
@@ -1709,17 +1643,24 @@ class Parser {
|
|
|
1709
1643
|
while (this.match(TokenKind_1.TokenKind.Caret)) {
|
|
1710
1644
|
let operator = this.previous();
|
|
1711
1645
|
let right = this.prefixUnary();
|
|
1712
|
-
this.addExpressionsToReferences(expr, right);
|
|
1713
1646
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1714
1647
|
}
|
|
1715
1648
|
return expr;
|
|
1716
1649
|
}
|
|
1717
1650
|
prefixUnary() {
|
|
1718
1651
|
const nextKind = this.peek().kind;
|
|
1719
|
-
if (nextKind === TokenKind_1.TokenKind.Not
|
|
1652
|
+
if (nextKind === TokenKind_1.TokenKind.Not) {
|
|
1720
1653
|
this.current++; //advance
|
|
1721
1654
|
let operator = this.previous();
|
|
1722
|
-
let right = this.
|
|
1655
|
+
let right = this.relational();
|
|
1656
|
+
return new Expression_1.UnaryExpression(operator, right);
|
|
1657
|
+
}
|
|
1658
|
+
else if (nextKind === TokenKind_1.TokenKind.Minus || nextKind === TokenKind_1.TokenKind.Plus) {
|
|
1659
|
+
this.current++; //advance
|
|
1660
|
+
let operator = this.previous();
|
|
1661
|
+
let right = nextKind === TokenKind_1.TokenKind.Not
|
|
1662
|
+
? this.boolean()
|
|
1663
|
+
: this.prefixUnary();
|
|
1723
1664
|
return new Expression_1.UnaryExpression(operator, right);
|
|
1724
1665
|
}
|
|
1725
1666
|
return this.call();
|
|
@@ -1727,22 +1668,36 @@ class Parser {
|
|
|
1727
1668
|
indexedGet(expr) {
|
|
1728
1669
|
let openingSquare = this.previous();
|
|
1729
1670
|
let questionDotToken = this.getMatchingTokenAtOffset(-2, TokenKind_1.TokenKind.QuestionDot);
|
|
1671
|
+
let index;
|
|
1672
|
+
let closingSquare;
|
|
1730
1673
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1731
|
-
|
|
1674
|
+
try {
|
|
1675
|
+
index = this.expression();
|
|
1676
|
+
}
|
|
1677
|
+
catch (error) {
|
|
1678
|
+
this.rethrowNonDiagnosticError(error);
|
|
1679
|
+
}
|
|
1732
1680
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1733
|
-
|
|
1681
|
+
closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1734
1682
|
return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare, questionDotToken);
|
|
1735
1683
|
}
|
|
1736
1684
|
newExpression() {
|
|
1685
|
+
var _a;
|
|
1737
1686
|
this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
|
|
1738
1687
|
let newToken = this.advance();
|
|
1739
|
-
let nameExpr = this.
|
|
1740
|
-
let leftParen = this.
|
|
1688
|
+
let nameExpr = this.identifyingExpression();
|
|
1689
|
+
let leftParen = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unexpectedToken(this.peek().text), TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen);
|
|
1690
|
+
if (!leftParen) {
|
|
1691
|
+
// new expression without a following call expression
|
|
1692
|
+
// wrap the name in an expression
|
|
1693
|
+
const endOfStatementRange = util_1.util.createRangeFromPositions(newToken.range.end, (_a = this.peek()) === null || _a === void 0 ? void 0 : _a.range.end);
|
|
1694
|
+
const exprStmt = nameExpr !== null && nameExpr !== void 0 ? nameExpr : (0, creators_1.createStringLiteral)('', endOfStatementRange);
|
|
1695
|
+
return new Statement_1.ExpressionStatement(exprStmt);
|
|
1696
|
+
}
|
|
1741
1697
|
let call = this.finishCall(leftParen, nameExpr);
|
|
1742
1698
|
//pop the call from the callExpressions list because this is technically something else
|
|
1743
1699
|
this.callExpressions.pop();
|
|
1744
1700
|
let result = new Expression_1.NewExpression(newToken, call);
|
|
1745
|
-
this._references.newExpressions.push(result);
|
|
1746
1701
|
return result;
|
|
1747
1702
|
}
|
|
1748
1703
|
/**
|
|
@@ -1763,21 +1718,15 @@ class Parser {
|
|
|
1763
1718
|
return this.newExpression();
|
|
1764
1719
|
}
|
|
1765
1720
|
let expr = this.primary();
|
|
1766
|
-
//an expression to keep for _references
|
|
1767
|
-
let referenceCallExpression;
|
|
1768
1721
|
while (true) {
|
|
1769
1722
|
if (this.matchAny(TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen)) {
|
|
1770
1723
|
expr = this.finishCall(this.previous(), expr);
|
|
1771
|
-
//store this call expression in references
|
|
1772
|
-
referenceCallExpression = expr;
|
|
1773
1724
|
}
|
|
1774
1725
|
else if (this.matchAny(TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.QuestionLeftSquare) || this.matchSequence(TokenKind_1.TokenKind.QuestionDot, TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1775
1726
|
expr = this.indexedGet(expr);
|
|
1776
1727
|
}
|
|
1777
1728
|
else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
|
|
1778
1729
|
expr = this.callfunc(expr);
|
|
1779
|
-
//store this callfunc expression in references
|
|
1780
|
-
referenceCallExpression = expr;
|
|
1781
1730
|
}
|
|
1782
1731
|
else if (this.matchAny(TokenKind_1.TokenKind.Dot, TokenKind_1.TokenKind.QuestionDot)) {
|
|
1783
1732
|
if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
@@ -1785,18 +1734,23 @@ class Parser {
|
|
|
1785
1734
|
}
|
|
1786
1735
|
else {
|
|
1787
1736
|
let dot = this.previous();
|
|
1788
|
-
let name = this.
|
|
1737
|
+
let name = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedPropertyNameAfterPeriod(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1738
|
+
if (!name) {
|
|
1739
|
+
break;
|
|
1740
|
+
}
|
|
1789
1741
|
// force it into an identifier so the AST makes some sense
|
|
1790
1742
|
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1791
1743
|
expr = new Expression_1.DottedGetExpression(expr, name, dot);
|
|
1792
|
-
this.addPropertyHints(name);
|
|
1793
1744
|
}
|
|
1794
1745
|
}
|
|
1795
1746
|
else if (this.checkAny(TokenKind_1.TokenKind.At, TokenKind_1.TokenKind.QuestionAt)) {
|
|
1796
1747
|
let dot = this.advance();
|
|
1797
|
-
let name = this.
|
|
1748
|
+
let name = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1798
1749
|
// force it into an identifier so the AST makes some sense
|
|
1799
1750
|
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1751
|
+
if (!name) {
|
|
1752
|
+
break;
|
|
1753
|
+
}
|
|
1800
1754
|
expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
|
|
1801
1755
|
//only allow a single `@` expression
|
|
1802
1756
|
break;
|
|
@@ -1805,10 +1759,6 @@ class Parser {
|
|
|
1805
1759
|
break;
|
|
1806
1760
|
}
|
|
1807
1761
|
}
|
|
1808
|
-
//if we found a callExpression, add it to `expressions` in references
|
|
1809
|
-
if (referenceCallExpression) {
|
|
1810
|
-
this._references.expressions.add(referenceCallExpression);
|
|
1811
|
-
}
|
|
1812
1762
|
return expr;
|
|
1813
1763
|
}
|
|
1814
1764
|
finishCall(openingParen, callee, addToCallExpressionList = true) {
|
|
@@ -1821,60 +1771,96 @@ class Parser {
|
|
|
1821
1771
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
1822
1772
|
throw this.lastDiagnosticAsError();
|
|
1823
1773
|
}
|
|
1824
|
-
|
|
1774
|
+
try {
|
|
1775
|
+
args.push(this.expression());
|
|
1776
|
+
}
|
|
1777
|
+
catch (error) {
|
|
1778
|
+
this.rethrowNonDiagnosticError(error);
|
|
1779
|
+
// we were unable to get an expression, so don't continue
|
|
1780
|
+
break;
|
|
1781
|
+
}
|
|
1825
1782
|
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
1826
1783
|
}
|
|
1827
1784
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1828
|
-
const closingParen = this.
|
|
1829
|
-
let expression = new Expression_1.CallExpression(callee, openingParen, closingParen, args
|
|
1785
|
+
const closingParen = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightParenAfterFunctionCallArguments(), TokenKind_1.TokenKind.RightParen);
|
|
1786
|
+
let expression = new Expression_1.CallExpression(callee, openingParen, closingParen, args);
|
|
1830
1787
|
if (addToCallExpressionList) {
|
|
1831
1788
|
this.callExpressions.push(expression);
|
|
1832
1789
|
}
|
|
1833
1790
|
return expression;
|
|
1834
1791
|
}
|
|
1835
1792
|
/**
|
|
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
|
|
1793
|
+
* Creates a TypeExpression, which wraps standard ASTNodes that represent a BscType
|
|
1839
1794
|
*/
|
|
1840
1795
|
typeExpression() {
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1796
|
+
const changedTokens = [];
|
|
1797
|
+
try {
|
|
1798
|
+
let expr = this.getTypeExpressionPart(changedTokens);
|
|
1799
|
+
while (this.options.mode === ParseMode.BrighterScript && this.matchAny(TokenKind_1.TokenKind.Or)) {
|
|
1800
|
+
// If we're in Brighterscript mode, allow union types with "or" between types
|
|
1801
|
+
// TODO: Handle Union types in parens? eg. "(string or integer)"
|
|
1802
|
+
let operator = this.previous();
|
|
1803
|
+
let right = this.getTypeExpressionPart(changedTokens);
|
|
1804
|
+
if (right) {
|
|
1805
|
+
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1806
|
+
}
|
|
1807
|
+
else {
|
|
1808
|
+
break;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
if (expr) {
|
|
1812
|
+
return new Expression_1.TypeExpression(expr);
|
|
1851
1813
|
}
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1814
|
+
}
|
|
1815
|
+
catch (error) {
|
|
1816
|
+
// Something went wrong - reset the kind to what it was previously
|
|
1817
|
+
for (const changedToken of changedTokens) {
|
|
1818
|
+
changedToken.token.kind = changedToken.oldKind;
|
|
1855
1819
|
}
|
|
1820
|
+
throw error;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
/**
|
|
1824
|
+
* Gets a single "part" of a type of a potential Union type
|
|
1825
|
+
* Note: this does not NEED to be part of a union type, but the logic is the same
|
|
1826
|
+
*
|
|
1827
|
+
* @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
|
|
1828
|
+
* @returns an expression that was successfully parsed
|
|
1829
|
+
*/
|
|
1830
|
+
getTypeExpressionPart(changedTokens) {
|
|
1831
|
+
let expr;
|
|
1832
|
+
if (this.checkAny(...TokenKind_1.DeclarableTypes)) {
|
|
1833
|
+
// if this is just a type, just use directly
|
|
1834
|
+
expr = new Expression_1.VariableExpression(this.advance());
|
|
1856
1835
|
}
|
|
1857
1836
|
else {
|
|
1858
|
-
|
|
1859
|
-
|
|
1837
|
+
if (this.checkAny(...TokenKind_1.AllowedTypeIdentifiers)) {
|
|
1838
|
+
// Since the next token is allowed as a type identifier, change the kind
|
|
1839
|
+
let nextToken = this.peek();
|
|
1840
|
+
changedTokens.push({ token: nextToken, oldKind: nextToken.kind });
|
|
1841
|
+
nextToken.kind = TokenKind_1.TokenKind.Identifier;
|
|
1842
|
+
}
|
|
1843
|
+
expr = this.identifyingExpression(TokenKind_1.AllowedTypeIdentifiers);
|
|
1860
1844
|
}
|
|
1861
|
-
//
|
|
1862
|
-
|
|
1863
|
-
|
|
1845
|
+
//Check if it has square brackets, thus making it an array
|
|
1846
|
+
if (expr && this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1847
|
+
if (this.options.mode === ParseMode.BrightScript) {
|
|
1848
|
+
// typed arrays not allowed in Brightscript
|
|
1849
|
+
this.warnIfNotBrighterScriptMode('typed arrays');
|
|
1850
|
+
return expr;
|
|
1851
|
+
}
|
|
1864
1852
|
// Check if it is an array - that is, if it has `[]` after the type
|
|
1865
|
-
// eg. `string[]` or `SomeKlass[]`
|
|
1853
|
+
// eg. `string[]` or `SomeKlass[]`
|
|
1854
|
+
// This is while loop, so it supports multidimensional arrays (eg. integer[][])
|
|
1866
1855
|
while (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1867
1856
|
const leftBracket = this.advance();
|
|
1868
1857
|
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1869
1858
|
const rightBracket = this.advance();
|
|
1870
|
-
|
|
1871
|
-
}
|
|
1872
|
-
else {
|
|
1873
|
-
break;
|
|
1859
|
+
expr = new Expression_1.TypedArrayExpression(expr, leftBracket, rightBracket);
|
|
1874
1860
|
}
|
|
1875
1861
|
}
|
|
1876
1862
|
}
|
|
1877
|
-
return
|
|
1863
|
+
return expr;
|
|
1878
1864
|
}
|
|
1879
1865
|
primary() {
|
|
1880
1866
|
switch (true) {
|
|
@@ -1890,7 +1876,7 @@ class Parser {
|
|
|
1890
1876
|
case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
|
|
1891
1877
|
return this.templateString(true);
|
|
1892
1878
|
case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
|
|
1893
|
-
return new Expression_1.VariableExpression(this.previous()
|
|
1879
|
+
return new Expression_1.VariableExpression(this.previous());
|
|
1894
1880
|
case this.match(TokenKind_1.TokenKind.LeftParen):
|
|
1895
1881
|
let left = this.previous();
|
|
1896
1882
|
let expr = this.expression();
|
|
@@ -1904,7 +1890,7 @@ class Parser {
|
|
|
1904
1890
|
let token = Object.assign(this.previous(), {
|
|
1905
1891
|
kind: TokenKind_1.TokenKind.Identifier
|
|
1906
1892
|
});
|
|
1907
|
-
return new Expression_1.VariableExpression(token
|
|
1893
|
+
return new Expression_1.VariableExpression(token);
|
|
1908
1894
|
case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
|
|
1909
1895
|
return this.anonymousFunction();
|
|
1910
1896
|
case this.check(TokenKind_1.TokenKind.RegexLiteral):
|
|
@@ -1932,23 +1918,31 @@ class Parser {
|
|
|
1932
1918
|
}
|
|
1933
1919
|
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1934
1920
|
}
|
|
1921
|
+
let closingSquare;
|
|
1935
1922
|
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
|
-
}
|
|
1923
|
+
try {
|
|
1947
1924
|
elements.push(this.expression());
|
|
1925
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1926
|
+
if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1927
|
+
let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
|
|
1928
|
+
elements.push(new Statement_1.CommentStatement([comment]));
|
|
1929
|
+
}
|
|
1930
|
+
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1931
|
+
}
|
|
1932
|
+
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1933
|
+
break;
|
|
1934
|
+
}
|
|
1935
|
+
elements.push(this.expression());
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
catch (error) {
|
|
1939
|
+
this.rethrowNonDiagnosticError(error);
|
|
1948
1940
|
}
|
|
1949
|
-
this.
|
|
1941
|
+
closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1942
|
+
}
|
|
1943
|
+
else {
|
|
1944
|
+
closingSquare = this.previous();
|
|
1950
1945
|
}
|
|
1951
|
-
let closingSquare = this.previous();
|
|
1952
1946
|
//this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
|
|
1953
1947
|
return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
|
|
1954
1948
|
}
|
|
@@ -1976,51 +1970,58 @@ class Parser {
|
|
|
1976
1970
|
return result;
|
|
1977
1971
|
};
|
|
1978
1972
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1973
|
+
let closingBrace;
|
|
1979
1974
|
if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
1980
1975
|
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]));
|
|
1976
|
+
try {
|
|
1977
|
+
if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1978
|
+
lastAAMember = null;
|
|
1979
|
+
members.push(new Statement_1.CommentStatement([this.advance()]));
|
|
2000
1980
|
}
|
|
2001
1981
|
else {
|
|
2002
|
-
|
|
2003
|
-
|
|
1982
|
+
let k = key();
|
|
1983
|
+
let expr = this.expression();
|
|
1984
|
+
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
|
|
1985
|
+
members.push(lastAAMember);
|
|
1986
|
+
}
|
|
1987
|
+
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
1988
|
+
// collect comma at end of expression
|
|
1989
|
+
if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
|
|
1990
|
+
lastAAMember.commaToken = this.previous();
|
|
1991
|
+
}
|
|
1992
|
+
//check for comment at the end of the current line
|
|
2004
1993
|
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
2005
1994
|
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
2006
|
-
lastAAMember = null;
|
|
2007
1995
|
members.push(new Statement_1.CommentStatement([token]));
|
|
2008
|
-
continue;
|
|
2009
1996
|
}
|
|
2010
|
-
|
|
2011
|
-
|
|
1997
|
+
else {
|
|
1998
|
+
this.consumeStatementSeparators(true);
|
|
1999
|
+
//check for a comment on its own line
|
|
2000
|
+
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
2001
|
+
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
2002
|
+
lastAAMember = null;
|
|
2003
|
+
members.push(new Statement_1.CommentStatement([token]));
|
|
2004
|
+
continue;
|
|
2005
|
+
}
|
|
2006
|
+
if (this.check(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
2007
|
+
break;
|
|
2008
|
+
}
|
|
2009
|
+
let k = key();
|
|
2010
|
+
let expr = this.expression();
|
|
2011
|
+
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr);
|
|
2012
|
+
members.push(lastAAMember);
|
|
2012
2013
|
}
|
|
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
2014
|
}
|
|
2018
2015
|
}
|
|
2019
|
-
|
|
2016
|
+
catch (error) {
|
|
2017
|
+
this.rethrowNonDiagnosticError(error);
|
|
2018
|
+
}
|
|
2019
|
+
closingBrace = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftCurlyAfterAALiteral(), TokenKind_1.TokenKind.RightCurlyBrace);
|
|
2020
|
+
}
|
|
2021
|
+
else {
|
|
2022
|
+
closingBrace = this.previous();
|
|
2020
2023
|
}
|
|
2021
|
-
|
|
2022
|
-
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
|
|
2023
|
-
this.addPropertyHints(aaExpr);
|
|
2024
|
+
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
|
|
2024
2025
|
return aaExpr;
|
|
2025
2026
|
}
|
|
2026
2027
|
/**
|
|
@@ -2035,7 +2036,7 @@ class Parser {
|
|
|
2035
2036
|
}
|
|
2036
2037
|
/**
|
|
2037
2038
|
* Pop token if we encounter a token in the specified list
|
|
2038
|
-
* @param tokenKinds
|
|
2039
|
+
* @param tokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
|
|
2039
2040
|
*/
|
|
2040
2041
|
matchAny(...tokenKinds) {
|
|
2041
2042
|
for (let tokenKind of tokenKinds) {
|
|
@@ -2048,7 +2049,7 @@ class Parser {
|
|
|
2048
2049
|
}
|
|
2049
2050
|
/**
|
|
2050
2051
|
* If the next series of tokens matches the given set of tokens, pop them all
|
|
2051
|
-
* @param tokenKinds
|
|
2052
|
+
* @param tokenKinds a list of tokenKinds used to match the next set of tokens
|
|
2052
2053
|
*/
|
|
2053
2054
|
matchSequence(...tokenKinds) {
|
|
2054
2055
|
var _a;
|
|
@@ -2075,6 +2076,14 @@ class Parser {
|
|
|
2075
2076
|
throw error;
|
|
2076
2077
|
}
|
|
2077
2078
|
}
|
|
2079
|
+
/**
|
|
2080
|
+
* Consume next token IF it matches the specified kind. Otherwise, do nothing and return undefined
|
|
2081
|
+
*/
|
|
2082
|
+
consumeTokenIf(tokenKind) {
|
|
2083
|
+
if (this.match(tokenKind)) {
|
|
2084
|
+
return this.previous();
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2078
2087
|
consumeToken(tokenKind) {
|
|
2079
2088
|
return this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(tokenKind), tokenKind);
|
|
2080
2089
|
}
|
|
@@ -2163,6 +2172,18 @@ class Parser {
|
|
|
2163
2172
|
previous() {
|
|
2164
2173
|
return this.tokens[this.current - 1];
|
|
2165
2174
|
}
|
|
2175
|
+
/**
|
|
2176
|
+
* Sometimes we catch an error that is a diagnostic.
|
|
2177
|
+
* If that's the case, we want to continue parsing.
|
|
2178
|
+
* Otherwise, re-throw the error
|
|
2179
|
+
*
|
|
2180
|
+
* @param error error caught in a try/catch
|
|
2181
|
+
*/
|
|
2182
|
+
rethrowNonDiagnosticError(error) {
|
|
2183
|
+
if (!error.isDiagnostic) {
|
|
2184
|
+
throw error;
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2166
2187
|
/**
|
|
2167
2188
|
* Get the token that is {offset} indexes away from {this.current}
|
|
2168
2189
|
* @param offset the number of index steps away from current index to fetch
|
|
@@ -2203,398 +2224,6 @@ class Parser {
|
|
|
2203
2224
|
this.advance();
|
|
2204
2225
|
}
|
|
2205
2226
|
}
|
|
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
2227
|
dispose() {
|
|
2599
2228
|
}
|
|
2600
2229
|
}
|
|
@@ -2604,154 +2233,9 @@ var ParseMode;
|
|
|
2604
2233
|
ParseMode["BrightScript"] = "BrightScript";
|
|
2605
2234
|
ParseMode["BrighterScript"] = "BrighterScript";
|
|
2606
2235
|
})(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
2236
|
class CancelStatementError extends Error {
|
|
2696
2237
|
constructor() {
|
|
2697
2238
|
super('CancelStatement');
|
|
2698
2239
|
}
|
|
2699
2240
|
}
|
|
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
2241
|
//# sourceMappingURL=Parser.js.map
|