brighterscript 1.0.0-alpha.23 → 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 +585 -218
- 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 +79 -15
- package/dist/DiagnosticMessages.js +134 -21
- 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 +222 -87
- 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 +162 -81
- package/dist/Program.js +903 -732
- package/dist/Program.js.map +1 -1
- package/dist/ProgramBuilder.d.ts +22 -12
- package/dist/ProgramBuilder.js +132 -104
- package/dist/ProgramBuilder.js.map +1 -1
- package/dist/Scope.d.ts +95 -134
- package/dist/Scope.js +477 -551
- 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 +95 -29
- package/dist/SymbolTable.js +256 -102
- 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 -68
- 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 -100
- package/dist/astUtils/reflection.js +225 -166
- 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 +54 -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 +12 -2
- package/dist/bscPlugin/BscPlugin.js +41 -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.d.ts +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js +21 -12
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.js.map +1 -1
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js +86 -12
- package/dist/bscPlugin/codeActions/CodeActionsProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/completions/CompletionsProcessor.d.ts +57 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js +544 -0
- package/dist/bscPlugin/completions/CompletionsProcessor.js.map +1 -0
- 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 +17 -0
- package/dist/bscPlugin/hover/HoverProcessor.js +188 -0
- package/dist/bscPlugin/hover/HoverProcessor.js.map +1 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js +513 -0
- package/dist/bscPlugin/hover/HoverProcessor.spec.js.map +1 -0
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.d.ts +3 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js +102 -29
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.js.map +1 -1
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js +167 -6
- package/dist/bscPlugin/semanticTokens/BrsFileSemanticTokensProcessor.spec.js.map +1 -1
- package/dist/bscPlugin/serialize/BslibInjector.spec.d.ts +1 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js +19 -0
- package/dist/bscPlugin/serialize/BslibInjector.spec.js.map +1 -0
- package/dist/bscPlugin/serialize/BslibManager.d.ts +9 -0
- package/dist/bscPlugin/serialize/BslibManager.js +40 -0
- package/dist/bscPlugin/serialize/BslibManager.js.map +1 -0
- package/dist/bscPlugin/serialize/FileSerializer.d.ts +9 -0
- package/dist/bscPlugin/serialize/FileSerializer.js +72 -0
- package/dist/bscPlugin/serialize/FileSerializer.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.d.ts +16 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js +123 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.js.map +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.d.ts +1 -0
- package/dist/bscPlugin/transpile/BrsFileTranspileProcessor.spec.js +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 +22 -1
- package/dist/bscPlugin/validation/BrsFileValidator.js +316 -29
- package/dist/bscPlugin/validation/BrsFileValidator.js.map +1 -1
- package/dist/bscPlugin/validation/BrsFileValidator.spec.d.ts +1 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js +264 -0
- package/dist/bscPlugin/validation/BrsFileValidator.spec.js.map +1 -0
- 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 +56 -8
- package/dist/bscPlugin/validation/ScopeValidator.js +514 -116
- 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 +107 -8
- 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 +529 -486
- package/dist/files/BrsFile.Class.spec.js.map +1 -1
- package/dist/files/BrsFile.d.ts +124 -112
- package/dist/files/BrsFile.js +819 -1131
- package/dist/files/BrsFile.js.map +1 -1
- package/dist/files/BrsFile.spec.js +1869 -1277
- 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 -117
- 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 +49 -41
- package/dist/files/tests/imports.spec.js.map +1 -1
- package/dist/files/tests/optionalChaning.spec.js +104 -40
- package/dist/files/tests/optionalChaning.spec.js.map +1 -1
- package/dist/globalCallables.js +16 -18
- package/dist/globalCallables.js.map +1 -1
- package/dist/index.d.ts +13 -2
- package/dist/index.js +15 -2
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +440 -150
- 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 +187 -134
- 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 +9 -0
- package/dist/lexer/TokenKind.js +30 -5
- 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 -167
- package/dist/parser/Expression.js +524 -394
- package/dist/parser/Expression.js.map +1 -1
- package/dist/parser/Parser.Class.spec.js +152 -146
- package/dist/parser/Parser.Class.spec.js.map +1 -1
- package/dist/parser/Parser.d.ts +45 -196
- package/dist/parser/Parser.js +470 -926
- package/dist/parser/Parser.js.map +1 -1
- package/dist/parser/Parser.spec.d.ts +3 -1
- package/dist/parser/Parser.spec.js +1034 -805
- 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 +208 -122
- package/dist/parser/Statement.js +599 -364
- 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 +123 -81
- 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 +221 -81
- package/dist/parser/tests/expression/TemplateStringExpression.spec.js.map +1 -1
- package/dist/parser/tests/expression/TernaryExpression.spec.js +287 -105
- 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.d.ts +1 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js +262 -0
- package/dist/parser/tests/statement/ConstStatement.spec.js.map +1 -0
- package/dist/parser/tests/statement/Continue.spec.d.ts +1 -0
- package/dist/parser/tests/statement/Continue.spec.js +119 -0
- package/dist/parser/tests/statement/Continue.spec.js.map +1 -0
- package/dist/parser/tests/statement/Declaration.spec.js +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 +111 -300
- 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 +107 -90
- 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 +3 -3
- 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 +15 -11
- 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 +6544 -10519
- package/dist/roku-types/index.d.ts +662 -1934
- 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 +10 -5
- package/dist/types/DynamicType.js +16 -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 +167 -131
- package/dist/util.js +890 -350
- package/dist/util.js.map +1 -1
- package/dist/validators/ClassValidator.d.ts +7 -25
- package/dist/validators/ClassValidator.js +103 -194
- package/dist/validators/ClassValidator.js.map +1 -1
- package/package.json +165 -149
- package/dist/astUtils/AstEditor.js.map +0 -1
- package/dist/astUtils/AstEditor.spec.js.map +0 -1
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.d.ts +0 -8
- package/dist/bscPlugin/transpile/BrsFilePreTranspileProcessor.js +0 -40
- 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/hover/HoverProcessor.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
|
-
const DynamicType_1 = require("../types/DynamicType");
|
|
17
|
-
const ArrayType_1 = require("../types/ArrayType");
|
|
18
|
-
const helpers_1 = require("../types/helpers");
|
|
19
14
|
const SymbolTable_1 = require("../SymbolTable");
|
|
20
|
-
const ObjectType_1 = require("../types/ObjectType");
|
|
21
15
|
class Parser {
|
|
22
16
|
constructor() {
|
|
23
17
|
/**
|
|
@@ -28,8 +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
|
-
this.symbolTable = new SymbolTable_1.SymbolTable();
|
|
32
|
-
this._references = new References();
|
|
33
25
|
this.globalTerminators = [];
|
|
34
26
|
/**
|
|
35
27
|
* An array of CallExpression for the current function body
|
|
@@ -39,48 +31,11 @@ class Parser {
|
|
|
39
31
|
get statements() {
|
|
40
32
|
return this.ast.statements;
|
|
41
33
|
}
|
|
42
|
-
get currentSymbolTable() {
|
|
43
|
-
var _a, _b;
|
|
44
|
-
return (_b = (_a = this.currentFunctionExpression) === null || _a === void 0 ? void 0 : _a.symbolTable) !== null && _b !== void 0 ? _b : this.symbolTable;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* References for significant statements/expressions in the parser.
|
|
48
|
-
* These are initially extracted during parse-time to improve performance, but will also be dynamically regenerated if need be.
|
|
49
|
-
*
|
|
50
|
-
* If a plugin modifies the AST, then the plugin should call Parser#invalidateReferences() to force this object to refresh
|
|
51
|
-
*/
|
|
52
|
-
get references() {
|
|
53
|
-
//build the references object if it's missing.
|
|
54
|
-
if (!this._references) {
|
|
55
|
-
this.findReferences();
|
|
56
|
-
}
|
|
57
|
-
return this._references;
|
|
58
|
-
}
|
|
59
34
|
/**
|
|
60
|
-
*
|
|
35
|
+
* The top-level symbol table for the body of this file.
|
|
61
36
|
*/
|
|
62
|
-
|
|
63
|
-
this.
|
|
64
|
-
}
|
|
65
|
-
addPropertyHints(item) {
|
|
66
|
-
if ((0, Token_1.isToken)(item)) {
|
|
67
|
-
const name = item.text;
|
|
68
|
-
this._references.propertyHints[name.toLowerCase()] = name;
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
for (const member of item.elements) {
|
|
72
|
-
if (!(0, reflection_1.isCommentStatement)(member)) {
|
|
73
|
-
const name = member.keyToken.text;
|
|
74
|
-
if (!name.startsWith('"')) {
|
|
75
|
-
this._references.propertyHints[name.toLowerCase()] = name;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
get currentNamespaceName() {
|
|
82
|
-
var _a;
|
|
83
|
-
return (_a = this.currentNamespace) === null || _a === void 0 ? void 0 : _a.nameExpression;
|
|
37
|
+
get symbolTable() {
|
|
38
|
+
return this.ast.symbolTable;
|
|
84
39
|
}
|
|
85
40
|
/**
|
|
86
41
|
* Get the currently active global terminators
|
|
@@ -93,22 +48,22 @@ class Parser {
|
|
|
93
48
|
* Static wrapper around creating a new parser and parsing a list of tokens
|
|
94
49
|
*/
|
|
95
50
|
static parse(toParse, options) {
|
|
96
|
-
|
|
97
|
-
if (typeof toParse === 'string') {
|
|
98
|
-
tokens = Lexer_1.Lexer.scan(toParse).tokens;
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
tokens = toParse;
|
|
102
|
-
}
|
|
103
|
-
return new Parser().parse(tokens, options);
|
|
51
|
+
return new Parser().parse(toParse, options);
|
|
104
52
|
}
|
|
105
53
|
/**
|
|
106
54
|
* Parses an array of `Token`s into an abstract syntax tree
|
|
107
55
|
* @param toParse the array of tokens to parse. May not contain any whitespace tokens
|
|
108
56
|
* @returns the same instance of the parser which contains the diagnostics and statements
|
|
109
57
|
*/
|
|
110
|
-
parse(
|
|
58
|
+
parse(toParse, options) {
|
|
111
59
|
var _a;
|
|
60
|
+
let tokens;
|
|
61
|
+
if (typeof toParse === 'string') {
|
|
62
|
+
tokens = Lexer_1.Lexer.scan(toParse).tokens;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
tokens = toParse;
|
|
66
|
+
}
|
|
112
67
|
this.logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : new Logger_1.Logger();
|
|
113
68
|
this.tokens = tokens;
|
|
114
69
|
this.options = this.sanitizeParseOptions(options);
|
|
@@ -122,6 +77,8 @@ class Parser {
|
|
|
122
77
|
this.namespaceAndFunctionDepth = 0;
|
|
123
78
|
this.pendingAnnotations = [];
|
|
124
79
|
this.ast = this.body();
|
|
80
|
+
//now that we've built the AST, link every node to its parent
|
|
81
|
+
this.ast.link();
|
|
125
82
|
return this;
|
|
126
83
|
}
|
|
127
84
|
body() {
|
|
@@ -187,11 +144,14 @@ class Parser {
|
|
|
187
144
|
declaration() {
|
|
188
145
|
try {
|
|
189
146
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
190
|
-
return this.
|
|
147
|
+
return this.functionDeclaration(false);
|
|
191
148
|
}
|
|
192
149
|
if (this.checkLibrary()) {
|
|
193
150
|
return this.libraryStatement();
|
|
194
151
|
}
|
|
152
|
+
if (this.check(TokenKind_1.TokenKind.Const) && this.checkAnyNext(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers)) {
|
|
153
|
+
return this.constDeclaration();
|
|
154
|
+
}
|
|
195
155
|
if (this.check(TokenKind_1.TokenKind.At) && this.checkNext(TokenKind_1.TokenKind.Identifier)) {
|
|
196
156
|
return this.annotationExpression();
|
|
197
157
|
}
|
|
@@ -230,75 +190,112 @@ class Parser {
|
|
|
230
190
|
return identifier;
|
|
231
191
|
}
|
|
232
192
|
enumMemberStatement() {
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
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);
|
|
236
195
|
//look for `= SOME_EXPRESSION`
|
|
237
196
|
if (this.check(TokenKind_1.TokenKind.Equal)) {
|
|
238
|
-
tokens.equal = this.advance();
|
|
239
|
-
value = this.expression();
|
|
197
|
+
statement.tokens.equal = this.advance();
|
|
198
|
+
statement.value = this.expression();
|
|
240
199
|
}
|
|
241
|
-
return
|
|
200
|
+
return statement;
|
|
242
201
|
}
|
|
243
202
|
/**
|
|
244
|
-
* Create a new
|
|
203
|
+
* Create a new InterfaceMethodStatement. This should only be called from within `interfaceDeclaration`
|
|
245
204
|
*/
|
|
246
|
-
interfaceFieldStatement() {
|
|
205
|
+
interfaceFieldStatement(optionalKeyword) {
|
|
247
206
|
const name = this.identifier(...TokenKind_1.AllowedProperties);
|
|
248
207
|
let asToken;
|
|
249
|
-
let
|
|
250
|
-
//look for `as SOME_TYPE`
|
|
208
|
+
let typeExpression;
|
|
251
209
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
252
|
-
asToken = this.
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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 }));
|
|
257
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));
|
|
258
248
|
}
|
|
259
|
-
|
|
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);
|
|
260
258
|
}
|
|
261
259
|
interfaceDeclaration() {
|
|
262
260
|
this.warnIfNotBrighterScriptMode('interface declarations');
|
|
263
261
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
264
262
|
const interfaceToken = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Interface), TokenKind_1.TokenKind.Interface);
|
|
265
|
-
|
|
266
|
-
let nameToken = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedIdentifierAfterKeyword('interface'), TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers);
|
|
263
|
+
const nameToken = this.identifier(...this.allowedLocalIdentifiers);
|
|
267
264
|
let extendsToken;
|
|
268
265
|
let parentInterfaceName;
|
|
269
266
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
270
267
|
extendsToken = this.advance();
|
|
271
|
-
|
|
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
|
+
}
|
|
272
274
|
}
|
|
273
275
|
this.consumeStatementSeparators();
|
|
274
276
|
//gather up all interface members (Fields, Methods)
|
|
275
277
|
let body = [];
|
|
276
278
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
277
279
|
try {
|
|
278
|
-
//break out of this loop if we encountered the `EndInterface` token not followed by `as`
|
|
279
|
-
if (this.check(TokenKind_1.TokenKind.EndInterface) && !this.checkNext(TokenKind_1.TokenKind.As)) {
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
280
|
let decl;
|
|
283
281
|
//collect leading annotations
|
|
284
282
|
if (this.check(TokenKind_1.TokenKind.At)) {
|
|
285
283
|
this.annotationExpression();
|
|
286
284
|
}
|
|
285
|
+
const optionalKeyword = this.consumeTokenIf(TokenKind_1.TokenKind.Optional);
|
|
287
286
|
//fields
|
|
288
|
-
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--;
|
|
289
294
|
decl = this.interfaceFieldStatement();
|
|
290
295
|
//methods (function/sub keyword followed by opening paren)
|
|
291
296
|
}
|
|
292
|
-
else if (this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub) && this.
|
|
293
|
-
|
|
294
|
-
hasName: true,
|
|
295
|
-
hasBody: false,
|
|
296
|
-
hasEnd: false,
|
|
297
|
-
onlyCallableAsMember: true
|
|
298
|
-
});
|
|
299
|
-
decl = new Statement_1.InterfaceMethodStatement(functionStatement.name, functionStatement.func);
|
|
300
|
-
//refer to this statement as parent of the expression
|
|
301
|
-
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);
|
|
302
299
|
//comments
|
|
303
300
|
}
|
|
304
301
|
else if (this.check(TokenKind_1.TokenKind.Comment)) {
|
|
@@ -308,6 +305,10 @@ class Parser {
|
|
|
308
305
|
this.consumePendingAnnotations(decl);
|
|
309
306
|
body.push(decl);
|
|
310
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
|
+
}
|
|
311
312
|
}
|
|
312
313
|
catch (e) {
|
|
313
314
|
//throw out any failed members and move on to the next line
|
|
@@ -315,24 +316,23 @@ class Parser {
|
|
|
315
316
|
}
|
|
316
317
|
//ensure statement separator
|
|
317
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
|
+
}
|
|
318
323
|
}
|
|
319
324
|
//consume the final `end interface` token
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('interface')), { range: endingKeyword.range }));
|
|
323
|
-
}
|
|
324
|
-
const statement = new Statement_1.InterfaceStatement(interfaceToken, nameToken, extendsToken, parentInterfaceName, body, endingKeyword, this.currentNamespaceName);
|
|
325
|
-
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);
|
|
326
327
|
this.exitAnnotationBlock(parentAnnotations);
|
|
327
328
|
return statement;
|
|
328
329
|
}
|
|
329
330
|
enumDeclaration() {
|
|
331
|
+
const result = new Statement_1.EnumStatement({}, []);
|
|
330
332
|
this.warnIfNotBrighterScriptMode('enum declarations');
|
|
331
333
|
const parentAnnotations = this.enterAnnotationBlock();
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
tokens.enum = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedKeyword(TokenKind_1.TokenKind.Enum), TokenKind_1.TokenKind.Enum);
|
|
335
|
-
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);
|
|
336
336
|
this.consumeStatementSeparators();
|
|
337
337
|
//gather up all members
|
|
338
338
|
while (this.checkAny(TokenKind_1.TokenKind.Comment, TokenKind_1.TokenKind.Identifier, TokenKind_1.TokenKind.At, ...TokenKind_1.AllowedProperties)) {
|
|
@@ -352,7 +352,7 @@ class Parser {
|
|
|
352
352
|
}
|
|
353
353
|
if (decl) {
|
|
354
354
|
this.consumePendingAnnotations(decl);
|
|
355
|
-
body.push(decl);
|
|
355
|
+
result.body.push(decl);
|
|
356
356
|
}
|
|
357
357
|
else {
|
|
358
358
|
//we didn't find a declaration...flag tokens until next line
|
|
@@ -371,12 +371,7 @@ class Parser {
|
|
|
371
371
|
}
|
|
372
372
|
}
|
|
373
373
|
//consume the final `end interface` token
|
|
374
|
-
tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
|
|
375
|
-
const result = new Statement_1.EnumStatement(tokens, body, this.currentNamespaceName);
|
|
376
|
-
if (tokens.name) {
|
|
377
|
-
this.currentSymbolTable.addSymbol(tokens.name.text, tokens.name.range, result.getThisBscType());
|
|
378
|
-
}
|
|
379
|
-
this._references.enumStatements.push(result);
|
|
374
|
+
result.tokens.endEnum = this.consumeToken(TokenKind_1.TokenKind.EndEnum);
|
|
380
375
|
this.exitAnnotationBlock(parentAnnotations);
|
|
381
376
|
return result;
|
|
382
377
|
}
|
|
@@ -394,7 +389,12 @@ class Parser {
|
|
|
394
389
|
//see if the class inherits from parent
|
|
395
390
|
if (this.peek().text.toLowerCase() === 'extends') {
|
|
396
391
|
extendsKeyword = this.advance();
|
|
397
|
-
|
|
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
|
+
}
|
|
398
398
|
}
|
|
399
399
|
//ensure statement separator
|
|
400
400
|
this.consumeStatementSeparators();
|
|
@@ -417,16 +417,14 @@ class Parser {
|
|
|
417
417
|
}
|
|
418
418
|
//methods (function/sub keyword OR identifier followed by opening paren)
|
|
419
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))) {
|
|
420
|
-
const
|
|
420
|
+
const funcDeclaration = this.functionDeclaration(false, false);
|
|
421
421
|
//if we have an overrides keyword AND this method is called 'new', that's not allowed
|
|
422
|
-
if (overrideKeyword &&
|
|
422
|
+
if (overrideKeyword && funcDeclaration.name.text.toLowerCase() === 'new') {
|
|
423
423
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseOverrideKeywordOnConstructorFunction()), { range: overrideKeyword.range }));
|
|
424
424
|
}
|
|
425
|
-
decl = new Statement_1.MethodStatement(accessModifier,
|
|
425
|
+
decl = new Statement_1.MethodStatement(accessModifier, funcDeclaration.name, funcDeclaration.func, overrideKeyword);
|
|
426
426
|
//refer to this statement as parent of the expression
|
|
427
|
-
|
|
428
|
-
//cache the range property so that plugins can't affect it
|
|
429
|
-
decl.cacheRange();
|
|
427
|
+
funcDeclaration.func.functionStatement = decl;
|
|
430
428
|
//fields
|
|
431
429
|
}
|
|
432
430
|
else if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
@@ -456,26 +454,43 @@ class Parser {
|
|
|
456
454
|
if (endingKeyword.kind !== TokenKind_1.TokenKind.EndClass) {
|
|
457
455
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.couldNotFindMatchingEndKeyword('class')), { range: endingKeyword.range }));
|
|
458
456
|
}
|
|
459
|
-
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName
|
|
460
|
-
if (className) {
|
|
461
|
-
this.currentSymbolTable.addSymbol(className.text, className.range, result.getConstructorFunctionType());
|
|
462
|
-
}
|
|
463
|
-
this._references.classStatements.push(result);
|
|
457
|
+
const result = new Statement_1.ClassStatement(classKeyword, className, body, endingKeyword, extendsKeyword, parentClassName);
|
|
464
458
|
this.exitAnnotationBlock(parentAnnotations);
|
|
465
459
|
return result;
|
|
466
460
|
}
|
|
467
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
|
+
}
|
|
468
488
|
let name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedClassFieldIdentifier(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
469
489
|
let asToken;
|
|
470
|
-
let
|
|
490
|
+
let fieldTypeExpression;
|
|
471
491
|
//look for `as SOME_TYPE`
|
|
472
492
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
473
|
-
asToken = this.
|
|
474
|
-
fieldTypeExpr = this.typeExpression();
|
|
475
|
-
//no field type specified
|
|
476
|
-
if (!fieldTypeExpr.isValidType(this.options.mode)) {
|
|
477
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedValidTypeToFollowAsKeyword()), { range: this.peek().range }));
|
|
478
|
-
}
|
|
493
|
+
[asToken, fieldTypeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
479
494
|
}
|
|
480
495
|
let initialValue;
|
|
481
496
|
let equal;
|
|
@@ -484,34 +499,22 @@ class Parser {
|
|
|
484
499
|
equal = this.advance();
|
|
485
500
|
initialValue = this.expression();
|
|
486
501
|
}
|
|
487
|
-
return new Statement_1.FieldStatement(accessModifier, name, asToken,
|
|
502
|
+
return new Statement_1.FieldStatement(accessModifier, name, asToken, fieldTypeExpression, equal, initialValue, optionalKeyword);
|
|
488
503
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
const funcResult = this.functionDeclaration(options);
|
|
492
|
-
if (funcResult) {
|
|
493
|
-
let result = new Statement_1.FunctionStatement(funcResult.name, funcResult.functionExpression, this.currentNamespaceName);
|
|
494
|
-
funcResult.functionExpression.functionStatement = result;
|
|
495
|
-
if (!options.onlyCallableAsMember) {
|
|
496
|
-
this._references.functionStatements.push(result);
|
|
497
|
-
}
|
|
498
|
-
return result;
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
functionDeclaration(options = {}) {
|
|
502
|
-
var _a, _b, _c, _d;
|
|
504
|
+
functionDeclaration(isAnonymous, checkIdentifier = true, onlyCallableAsMember = false) {
|
|
505
|
+
var _a;
|
|
503
506
|
let previousCallExpressions = this.callExpressions;
|
|
504
507
|
this.callExpressions = [];
|
|
505
508
|
try {
|
|
506
509
|
//track depth to help certain statements need to know if they are contained within a function body
|
|
507
510
|
this.namespaceAndFunctionDepth++;
|
|
508
|
-
let
|
|
511
|
+
let functionType;
|
|
509
512
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
510
|
-
|
|
513
|
+
functionType = this.advance();
|
|
511
514
|
}
|
|
512
515
|
else {
|
|
513
516
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.missingCallableKeyword()), { range: this.peek().range }));
|
|
514
|
-
|
|
517
|
+
functionType = {
|
|
515
518
|
isReserved: true,
|
|
516
519
|
kind: TokenKind_1.TokenKind.Function,
|
|
517
520
|
text: 'function',
|
|
@@ -520,33 +523,34 @@ class Parser {
|
|
|
520
523
|
start: this.peek().range.start,
|
|
521
524
|
end: this.peek().range.start
|
|
522
525
|
},
|
|
523
|
-
leadingWhitespace: ''
|
|
526
|
+
leadingWhitespace: '',
|
|
527
|
+
leadingTrivia: []
|
|
524
528
|
};
|
|
525
529
|
}
|
|
526
|
-
let isSub = (
|
|
527
|
-
let
|
|
530
|
+
let isSub = (functionType === null || functionType === void 0 ? void 0 : functionType.kind) === TokenKind_1.TokenKind.Sub;
|
|
531
|
+
let functionTypeText = isSub ? 'sub' : 'function';
|
|
528
532
|
let name;
|
|
529
533
|
let leftParen;
|
|
530
|
-
if (
|
|
531
|
-
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(
|
|
534
|
+
if (isAnonymous) {
|
|
535
|
+
leftParen = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedLeftParenAfterCallable(functionTypeText), TokenKind_1.TokenKind.LeftParen);
|
|
532
536
|
}
|
|
533
537
|
else {
|
|
534
|
-
name = this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedNameAfterCallableKeyword(
|
|
535
|
-
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);
|
|
536
540
|
//prevent functions from ending with type designators
|
|
537
541
|
let lastChar = name.text[name.text.length - 1];
|
|
538
542
|
if (['$', '%', '!', '#', '&'].includes(lastChar)) {
|
|
539
543
|
//don't throw this error; let the parser continue
|
|
540
|
-
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 }));
|
|
541
545
|
}
|
|
542
|
-
//flag functions with keywords for names (only for standard functions
|
|
543
|
-
if (
|
|
546
|
+
//flag functions with keywords for names (only for standard functions)
|
|
547
|
+
if (checkIdentifier && TokenKind_1.DisallowedFunctionIdentifiersText.has(name.text.toLowerCase())) {
|
|
544
548
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
545
549
|
}
|
|
546
550
|
}
|
|
547
551
|
let params = [];
|
|
548
552
|
let asToken;
|
|
549
|
-
let
|
|
553
|
+
let typeExpression;
|
|
550
554
|
if (!this.check(TokenKind_1.TokenKind.RightParen)) {
|
|
551
555
|
do {
|
|
552
556
|
if (params.length >= Expression_1.CallExpression.MaximumArguments) {
|
|
@@ -557,11 +561,7 @@ class Parser {
|
|
|
557
561
|
}
|
|
558
562
|
let rightParen = this.advance();
|
|
559
563
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
560
|
-
asToken = this.
|
|
561
|
-
typeExpr = this.typeExpression();
|
|
562
|
-
if (!typeExpr.isValidType(this.options.mode)) {
|
|
563
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.invalidFunctionReturnType((_a = typeExpr.getText()) !== null && _a !== void 0 ? _a : '')), { range: typeExpr.range }));
|
|
564
|
-
}
|
|
564
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
565
565
|
}
|
|
566
566
|
params.reduce((haveFoundOptional, param) => {
|
|
567
567
|
if (haveFoundOptional && !param.defaultValue) {
|
|
@@ -569,61 +569,39 @@ class Parser {
|
|
|
569
569
|
}
|
|
570
570
|
return haveFoundOptional || !!param.defaultValue;
|
|
571
571
|
}, false);
|
|
572
|
-
|
|
573
|
-
// do not go to next statement - we don't care about any other statement
|
|
574
|
-
this.consumeStatementSeparators(true);
|
|
575
|
-
}
|
|
572
|
+
this.consumeStatementSeparators(true);
|
|
576
573
|
let func = new Expression_1.FunctionExpression(params, undefined, //body
|
|
577
|
-
|
|
578
|
-
leftParen, rightParen, asToken,
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
if
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
(_d = this.currentNamespace) === null || _d === void 0 ? void 0 : _d.symbolTable.addSymbol(name.text, name.range, funcType);
|
|
590
|
-
let fullyQualifiedName = name.text;
|
|
591
|
-
if (this.currentNamespaceName) {
|
|
592
|
-
// add the "namespaced" name of this function to the parent symbol table
|
|
593
|
-
fullyQualifiedName = this.currentNamespaceName.getName(ParseMode.BrighterScript) + '.' + name.text;
|
|
594
|
-
}
|
|
595
|
-
this.currentSymbolTable.addSymbol(fullyQualifiedName, name.range, funcType);
|
|
596
|
-
}
|
|
597
|
-
this._references.functionExpressions.push(func);
|
|
598
|
-
if (options.hasBody) {
|
|
599
|
-
let previousFunctionExpression = this.currentFunctionExpression;
|
|
600
|
-
this.currentFunctionExpression = func;
|
|
601
|
-
//make sure to restore the currentFunctionExpression even if the body block fails to parse
|
|
602
|
-
try {
|
|
603
|
-
//support ending the function with `end sub` OR `end function`
|
|
604
|
-
func.body = this.block();
|
|
605
|
-
}
|
|
606
|
-
finally {
|
|
607
|
-
this.currentFunctionExpression = previousFunctionExpression;
|
|
608
|
-
}
|
|
609
|
-
if (!func.body) {
|
|
610
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.callableBlockMissingEndKeyword(functionKeywordText)), { range: this.peek().range }));
|
|
611
|
-
throw this.lastDiagnosticAsError();
|
|
612
|
-
}
|
|
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();
|
|
613
586
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.mismatchedEndCallableKeyword(functionKeywordText, func.end.text)), { range: this.peek().range }));
|
|
622
|
-
}
|
|
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 }));
|
|
623
594
|
}
|
|
624
595
|
func.callExpressions = this.callExpressions;
|
|
625
|
-
|
|
626
|
-
|
|
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
|
+
}
|
|
627
605
|
}
|
|
628
606
|
finally {
|
|
629
607
|
this.namespaceAndFunctionDepth--;
|
|
@@ -636,42 +614,25 @@ class Parser {
|
|
|
636
614
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedParameterNameButFound(this.peek().text)), { range: this.peek().range }));
|
|
637
615
|
throw this.lastDiagnosticAsError();
|
|
638
616
|
}
|
|
639
|
-
|
|
640
|
-
|
|
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;
|
|
641
621
|
let defaultValue;
|
|
642
|
-
let
|
|
622
|
+
let equalToken;
|
|
643
623
|
// parse argument default value
|
|
644
|
-
if (this.
|
|
645
|
-
equalsToken = this.previous();
|
|
624
|
+
if ((equalToken = this.consumeTokenIf(TokenKind_1.TokenKind.Equal))) {
|
|
646
625
|
// it seems any expression is allowed here -- including ones that operate on other arguments!
|
|
647
|
-
defaultValue = this.expression();
|
|
626
|
+
defaultValue = this.expression(false);
|
|
648
627
|
}
|
|
649
628
|
let asToken = null;
|
|
650
629
|
if (this.check(TokenKind_1.TokenKind.As)) {
|
|
651
|
-
asToken = this.
|
|
652
|
-
typeExpr = this.typeExpression();
|
|
653
|
-
if (!typeExpr.isValidType(this.options.mode)) {
|
|
654
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.functionParameterTypeIsInvalid(name.text, typeExpr.getText())), { range: typeExpr.range }));
|
|
655
|
-
throw this.lastDiagnosticAsError();
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
let typeInContext;
|
|
659
|
-
if (typeExpr) {
|
|
660
|
-
typeInContext = typeExpr.type;
|
|
661
|
-
}
|
|
662
|
-
else if (defaultValue) {
|
|
663
|
-
typeInContext = getBscTypeFromExpression(defaultValue, this.currentFunctionExpression);
|
|
664
|
-
if ((0, reflection_1.isInvalidType)(typeInContext)) {
|
|
665
|
-
typeInContext = new DynamicType_1.DynamicType();
|
|
666
|
-
}
|
|
630
|
+
[asToken, typeExpression] = this.consumeAsTokenAndTypeExpression();
|
|
667
631
|
}
|
|
668
|
-
|
|
669
|
-
typeInContext = new DynamicType_1.DynamicType();
|
|
670
|
-
}
|
|
671
|
-
return new Expression_1.FunctionParameterExpression(name, typeInContext, equalsToken, defaultValue, asToken, typeExpr, this.currentNamespaceName);
|
|
632
|
+
return new Expression_1.FunctionParameterExpression(name, equalToken, defaultValue, asToken, typeExpression);
|
|
672
633
|
}
|
|
673
634
|
assignment() {
|
|
674
|
-
let name = this.
|
|
635
|
+
let name = this.advance();
|
|
675
636
|
//add diagnostic if name is a reserved word that cannot be used as an identifier
|
|
676
637
|
if (TokenKind_1.DisallowedLocalIdentifiersText.has(name.text.toLowerCase())) {
|
|
677
638
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.cannotUseReservedWordAsIdentifier(name.text)), { range: name.range }));
|
|
@@ -680,19 +641,12 @@ class Parser {
|
|
|
680
641
|
let value = this.expression();
|
|
681
642
|
let result;
|
|
682
643
|
if (operator.kind === TokenKind_1.TokenKind.Equal) {
|
|
683
|
-
result = new Statement_1.AssignmentStatement(
|
|
644
|
+
result = new Statement_1.AssignmentStatement(operator, name, value);
|
|
684
645
|
}
|
|
685
646
|
else {
|
|
686
|
-
const nameExpression = new Expression_1.VariableExpression(name
|
|
687
|
-
result = new Statement_1.AssignmentStatement(
|
|
688
|
-
|
|
689
|
-
//remove the right-hand-side expression from this assignment operator, and replace with the full assignment expression
|
|
690
|
-
this._references.expressions.delete(value);
|
|
691
|
-
this._references.expressions.add(result);
|
|
692
|
-
}
|
|
693
|
-
this._references.assignmentStatements.push(result);
|
|
694
|
-
const assignmentType = getBscTypeFromExpression(result.value, this.currentFunctionExpression);
|
|
695
|
-
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
|
+
}
|
|
696
650
|
return result;
|
|
697
651
|
}
|
|
698
652
|
checkLibrary() {
|
|
@@ -761,6 +715,10 @@ class Parser {
|
|
|
761
715
|
if (this.check(TokenKind_1.TokenKind.Goto)) {
|
|
762
716
|
return this.gotoStatement();
|
|
763
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
|
+
}
|
|
764
722
|
//does this line look like a label? (i.e. `someIdentifier:` )
|
|
765
723
|
if (this.check(TokenKind_1.TokenKind.Identifier) && this.checkNext(TokenKind_1.TokenKind.Colon) && this.checkPrevious(TokenKind_1.TokenKind.Newline)) {
|
|
766
724
|
try {
|
|
@@ -850,7 +808,7 @@ class Parser {
|
|
|
850
808
|
}
|
|
851
809
|
forEachStatement() {
|
|
852
810
|
let forEach = this.advance();
|
|
853
|
-
let name = this.
|
|
811
|
+
let name = this.advance();
|
|
854
812
|
let maybeIn = this.peek();
|
|
855
813
|
if (this.check(TokenKind_1.TokenKind.Identifier) && maybeIn.text.toLowerCase() === 'in') {
|
|
856
814
|
this.advance();
|
|
@@ -864,12 +822,6 @@ class Parser {
|
|
|
864
822
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedExpressionAfterForEachIn()), { range: this.peek().range }));
|
|
865
823
|
throw this.lastDiagnosticAsError();
|
|
866
824
|
}
|
|
867
|
-
let itemType = new DynamicType_1.DynamicType();
|
|
868
|
-
const targetType = getBscTypeFromExpression(target, this.currentFunctionExpression);
|
|
869
|
-
if ((0, reflection_1.isArrayType)(targetType)) {
|
|
870
|
-
itemType = targetType.getDefaultType();
|
|
871
|
-
}
|
|
872
|
-
this.currentSymbolTable.addSymbol(name.text, name.range, itemType);
|
|
873
825
|
this.consumeStatementSeparators();
|
|
874
826
|
let body = this.block(TokenKind_1.TokenKind.EndFor, TokenKind_1.TokenKind.Next);
|
|
875
827
|
if (!body) {
|
|
@@ -877,7 +829,11 @@ class Parser {
|
|
|
877
829
|
throw this.lastDiagnosticAsError();
|
|
878
830
|
}
|
|
879
831
|
let endFor = this.advance();
|
|
880
|
-
return new Statement_1.ForEachStatement(
|
|
832
|
+
return new Statement_1.ForEachStatement({
|
|
833
|
+
forEach: forEach,
|
|
834
|
+
in: maybeIn,
|
|
835
|
+
endFor: endFor
|
|
836
|
+
}, name, target, body);
|
|
881
837
|
}
|
|
882
838
|
exitFor() {
|
|
883
839
|
let keyword = this.advance();
|
|
@@ -902,19 +858,13 @@ class Parser {
|
|
|
902
858
|
namespaceStatement() {
|
|
903
859
|
this.warnIfNotBrighterScriptMode('namespace');
|
|
904
860
|
let keyword = this.advance();
|
|
905
|
-
if (!this.isAtRootLevel()) {
|
|
906
|
-
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.keywordMustBeDeclaredAtRootLevel('namespace')), { range: keyword.range }));
|
|
907
|
-
}
|
|
908
861
|
this.namespaceAndFunctionDepth++;
|
|
909
|
-
let name = this.
|
|
862
|
+
let name = this.identifyingExpression();
|
|
910
863
|
//set the current namespace name
|
|
911
|
-
let result = new Statement_1.NamespaceStatement(keyword, name, null, null
|
|
912
|
-
this.currentNamespace = result;
|
|
864
|
+
let result = new Statement_1.NamespaceStatement(keyword, name, null, null);
|
|
913
865
|
this.globalTerminators.push([TokenKind_1.TokenKind.EndNamespace]);
|
|
914
866
|
let body = this.body();
|
|
915
867
|
this.globalTerminators.pop();
|
|
916
|
-
//unset the current namespace name
|
|
917
|
-
this.currentNamespace = undefined;
|
|
918
868
|
let endKeyword;
|
|
919
869
|
if (this.check(TokenKind_1.TokenKind.EndNamespace)) {
|
|
920
870
|
endKeyword = this.advance();
|
|
@@ -926,21 +876,22 @@ class Parser {
|
|
|
926
876
|
this.namespaceAndFunctionDepth--;
|
|
927
877
|
result.body = body;
|
|
928
878
|
result.endKeyword = endKeyword;
|
|
929
|
-
this._references.namespaceStatements.push(result);
|
|
930
879
|
//cache the range property so that plugins can't affect it
|
|
931
880
|
result.cacheRange();
|
|
881
|
+
result.body.symbolTable.name += `: namespace '${result.name}'`;
|
|
932
882
|
return result;
|
|
933
883
|
}
|
|
934
884
|
/**
|
|
935
885
|
* Get an expression with identifiers separated by periods. Useful for namespaces and class extends
|
|
936
886
|
*/
|
|
937
|
-
|
|
938
|
-
|
|
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);
|
|
939
890
|
let expr;
|
|
940
891
|
if (firstIdentifier) {
|
|
941
892
|
// force it into an identifier so the AST makes some sense
|
|
942
893
|
firstIdentifier.kind = TokenKind_1.TokenKind.Identifier;
|
|
943
|
-
const varExpr = new Expression_1.VariableExpression(firstIdentifier
|
|
894
|
+
const varExpr = new Expression_1.VariableExpression(firstIdentifier);
|
|
944
895
|
expr = varExpr;
|
|
945
896
|
//consume multiple dot identifiers (i.e. `Name.Space.Can.Have.Many.Parts`)
|
|
946
897
|
while (this.check(TokenKind_1.TokenKind.Dot)) {
|
|
@@ -948,7 +899,7 @@ class Parser {
|
|
|
948
899
|
if (!dot) {
|
|
949
900
|
break;
|
|
950
901
|
}
|
|
951
|
-
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);
|
|
952
903
|
if (!identifier) {
|
|
953
904
|
break;
|
|
954
905
|
}
|
|
@@ -957,7 +908,7 @@ class Parser {
|
|
|
957
908
|
expr = new Expression_1.DottedGetExpression(expr, identifier, dot);
|
|
958
909
|
}
|
|
959
910
|
}
|
|
960
|
-
return
|
|
911
|
+
return expr;
|
|
961
912
|
}
|
|
962
913
|
/**
|
|
963
914
|
* Add an 'unexpected token' diagnostic for any token found between current and the first stopToken found.
|
|
@@ -970,8 +921,8 @@ class Parser {
|
|
|
970
921
|
}
|
|
971
922
|
/**
|
|
972
923
|
* Consume tokens until one of the `stopTokenKinds` is encountered
|
|
973
|
-
* @param tokenKinds
|
|
974
|
-
* @
|
|
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)
|
|
975
926
|
*/
|
|
976
927
|
consumeUntil(...stopTokenKinds) {
|
|
977
928
|
let result = [];
|
|
@@ -981,13 +932,25 @@ class Parser {
|
|
|
981
932
|
}
|
|
982
933
|
return result;
|
|
983
934
|
}
|
|
935
|
+
constDeclaration() {
|
|
936
|
+
this.warnIfNotBrighterScriptMode('const declaration');
|
|
937
|
+
const constToken = this.advance();
|
|
938
|
+
const nameToken = this.identifier(...this.allowedLocalIdentifiers);
|
|
939
|
+
const equalToken = this.consumeToken(TokenKind_1.TokenKind.Equal);
|
|
940
|
+
const expression = this.expression();
|
|
941
|
+
const statement = new Statement_1.ConstStatement({
|
|
942
|
+
const: constToken,
|
|
943
|
+
name: nameToken,
|
|
944
|
+
equals: equalToken
|
|
945
|
+
}, expression);
|
|
946
|
+
return statement;
|
|
947
|
+
}
|
|
984
948
|
libraryStatement() {
|
|
985
949
|
let libStatement = new Statement_1.LibraryStatement({
|
|
986
950
|
library: this.advance(),
|
|
987
951
|
//grab the next token only if it's a string
|
|
988
952
|
filePath: this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('library'), TokenKind_1.TokenKind.StringLiteral)
|
|
989
953
|
});
|
|
990
|
-
this._references.libraryStatements.push(libStatement);
|
|
991
954
|
return libStatement;
|
|
992
955
|
}
|
|
993
956
|
importStatement() {
|
|
@@ -995,7 +958,6 @@ class Parser {
|
|
|
995
958
|
let importStatement = new Statement_1.ImportStatement(this.advance(),
|
|
996
959
|
//grab the next token only if it's a string
|
|
997
960
|
this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedStringLiteralAfterKeyword('import'), TokenKind_1.TokenKind.StringLiteral));
|
|
998
|
-
this._references.importStatements.push(importStatement);
|
|
999
961
|
return importStatement;
|
|
1000
962
|
}
|
|
1001
963
|
annotationExpression() {
|
|
@@ -1011,8 +973,6 @@ class Parser {
|
|
|
1011
973
|
let leftParen = this.advance();
|
|
1012
974
|
annotation.call = this.finishCall(leftParen, annotation, false);
|
|
1013
975
|
}
|
|
1014
|
-
//cache the range property so that plugins can't affect it
|
|
1015
|
-
annotation.cacheRange();
|
|
1016
976
|
return annotation;
|
|
1017
977
|
}
|
|
1018
978
|
ternaryExpression(test) {
|
|
@@ -1390,15 +1350,14 @@ class Parser {
|
|
|
1390
1350
|
throw this.lastDiagnosticAsError();
|
|
1391
1351
|
}
|
|
1392
1352
|
const result = new Statement_1.IncrementStatement(expr, operator);
|
|
1393
|
-
this._references.expressions.add(result);
|
|
1394
1353
|
return result;
|
|
1395
1354
|
}
|
|
1396
1355
|
if ((0, reflection_1.isCallExpression)(expr) || (0, reflection_1.isCallfuncExpression)(expr)) {
|
|
1397
1356
|
return new Statement_1.ExpressionStatement(expr);
|
|
1398
1357
|
}
|
|
1399
|
-
//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
|
|
1400
1359
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.expectedStatementOrFunctionCallButReceivedExpression()), { range: expressionStart.range }));
|
|
1401
|
-
|
|
1360
|
+
return new Statement_1.ExpressionStatement(expr);
|
|
1402
1361
|
}
|
|
1403
1362
|
setStatement() {
|
|
1404
1363
|
/**
|
|
@@ -1416,17 +1375,18 @@ class Parser {
|
|
|
1416
1375
|
if ((0, reflection_1.isIndexedGetExpression)(left)) {
|
|
1417
1376
|
return new Statement_1.IndexedSetStatement(left.obj, left.index, operator.kind === TokenKind_1.TokenKind.Equal
|
|
1418
1377
|
? right
|
|
1419
|
-
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare
|
|
1378
|
+
: new Expression_1.BinaryExpression(left, operator, right), left.openingSquare, left.closingSquare);
|
|
1420
1379
|
}
|
|
1421
1380
|
else if ((0, reflection_1.isDottedGetExpression)(left)) {
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
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);
|
|
1425
1384
|
}
|
|
1426
1385
|
}
|
|
1427
1386
|
return this.expressionStatement(expr);
|
|
1428
1387
|
}
|
|
1429
1388
|
printStatement() {
|
|
1389
|
+
var _a;
|
|
1430
1390
|
let printKeyword = this.advance();
|
|
1431
1391
|
let values = [];
|
|
1432
1392
|
while (!this.checkEndOfStatement()) {
|
|
@@ -1445,7 +1405,8 @@ class Parser {
|
|
|
1445
1405
|
}
|
|
1446
1406
|
//print statements can be empty, so look for empty print conditions
|
|
1447
1407
|
if (!values.length) {
|
|
1448
|
-
|
|
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);
|
|
1449
1410
|
values.push(emptyStringLiteral);
|
|
1450
1411
|
}
|
|
1451
1412
|
let last = values[values.length - 1];
|
|
@@ -1481,9 +1442,16 @@ class Parser {
|
|
|
1481
1442
|
this.current -= 2;
|
|
1482
1443
|
throw new CancelStatementError();
|
|
1483
1444
|
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
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
|
+
});
|
|
1487
1455
|
}
|
|
1488
1456
|
/**
|
|
1489
1457
|
* Parses a `goto` statement
|
|
@@ -1588,14 +1556,32 @@ class Parser {
|
|
|
1588
1556
|
}
|
|
1589
1557
|
this.pendingAnnotations = parentAnnotations;
|
|
1590
1558
|
}
|
|
1591
|
-
expression() {
|
|
1592
|
-
|
|
1593
|
-
|
|
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
|
+
}
|
|
1594
1580
|
return expression;
|
|
1595
1581
|
}
|
|
1596
1582
|
anonymousFunction() {
|
|
1597
1583
|
if (this.checkAny(TokenKind_1.TokenKind.Sub, TokenKind_1.TokenKind.Function)) {
|
|
1598
|
-
const func = this.functionDeclaration(
|
|
1584
|
+
const func = this.functionDeclaration(true);
|
|
1599
1585
|
//if there's an open paren after this, this is an IIFE
|
|
1600
1586
|
if (this.check(TokenKind_1.TokenKind.LeftParen)) {
|
|
1601
1587
|
return this.finishCall(this.advance(), func);
|
|
@@ -1620,7 +1606,6 @@ class Parser {
|
|
|
1620
1606
|
while (this.matchAny(TokenKind_1.TokenKind.And, TokenKind_1.TokenKind.Or)) {
|
|
1621
1607
|
let operator = this.previous();
|
|
1622
1608
|
let right = this.relational();
|
|
1623
|
-
this.addExpressionsToReferences(expr, right);
|
|
1624
1609
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1625
1610
|
}
|
|
1626
1611
|
return expr;
|
|
@@ -1630,25 +1615,16 @@ class Parser {
|
|
|
1630
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)) {
|
|
1631
1616
|
let operator = this.previous();
|
|
1632
1617
|
let right = this.additive();
|
|
1633
|
-
this.addExpressionsToReferences(expr, right);
|
|
1634
1618
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1635
1619
|
}
|
|
1636
1620
|
return expr;
|
|
1637
1621
|
}
|
|
1638
|
-
addExpressionsToReferences(...expressions) {
|
|
1639
|
-
for (const expression of expressions) {
|
|
1640
|
-
if (!(0, reflection_1.isBinaryExpression)(expression)) {
|
|
1641
|
-
this.references.expressions.add(expression);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
}
|
|
1645
1622
|
// TODO: bitshift
|
|
1646
1623
|
additive() {
|
|
1647
1624
|
let expr = this.multiplicative();
|
|
1648
1625
|
while (this.matchAny(TokenKind_1.TokenKind.Plus, TokenKind_1.TokenKind.Minus)) {
|
|
1649
1626
|
let operator = this.previous();
|
|
1650
1627
|
let right = this.multiplicative();
|
|
1651
|
-
this.addExpressionsToReferences(expr, right);
|
|
1652
1628
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1653
1629
|
}
|
|
1654
1630
|
return expr;
|
|
@@ -1658,7 +1634,6 @@ class Parser {
|
|
|
1658
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)) {
|
|
1659
1635
|
let operator = this.previous();
|
|
1660
1636
|
let right = this.exponential();
|
|
1661
|
-
this.addExpressionsToReferences(expr, right);
|
|
1662
1637
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1663
1638
|
}
|
|
1664
1639
|
return expr;
|
|
@@ -1668,17 +1643,24 @@ class Parser {
|
|
|
1668
1643
|
while (this.match(TokenKind_1.TokenKind.Caret)) {
|
|
1669
1644
|
let operator = this.previous();
|
|
1670
1645
|
let right = this.prefixUnary();
|
|
1671
|
-
this.addExpressionsToReferences(expr, right);
|
|
1672
1646
|
expr = new Expression_1.BinaryExpression(expr, operator, right);
|
|
1673
1647
|
}
|
|
1674
1648
|
return expr;
|
|
1675
1649
|
}
|
|
1676
1650
|
prefixUnary() {
|
|
1677
1651
|
const nextKind = this.peek().kind;
|
|
1678
|
-
if (nextKind === TokenKind_1.TokenKind.Not
|
|
1652
|
+
if (nextKind === TokenKind_1.TokenKind.Not) {
|
|
1679
1653
|
this.current++; //advance
|
|
1680
1654
|
let operator = this.previous();
|
|
1681
|
-
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();
|
|
1682
1664
|
return new Expression_1.UnaryExpression(operator, right);
|
|
1683
1665
|
}
|
|
1684
1666
|
return this.call();
|
|
@@ -1686,22 +1668,36 @@ class Parser {
|
|
|
1686
1668
|
indexedGet(expr) {
|
|
1687
1669
|
let openingSquare = this.previous();
|
|
1688
1670
|
let questionDotToken = this.getMatchingTokenAtOffset(-2, TokenKind_1.TokenKind.QuestionDot);
|
|
1671
|
+
let index;
|
|
1672
|
+
let closingSquare;
|
|
1689
1673
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1690
|
-
|
|
1674
|
+
try {
|
|
1675
|
+
index = this.expression();
|
|
1676
|
+
}
|
|
1677
|
+
catch (error) {
|
|
1678
|
+
this.rethrowNonDiagnosticError(error);
|
|
1679
|
+
}
|
|
1691
1680
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1692
|
-
|
|
1681
|
+
closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedRightSquareBraceAfterArrayOrObjectIndex(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1693
1682
|
return new Expression_1.IndexedGetExpression(expr, index, openingSquare, closingSquare, questionDotToken);
|
|
1694
1683
|
}
|
|
1695
1684
|
newExpression() {
|
|
1685
|
+
var _a;
|
|
1696
1686
|
this.warnIfNotBrighterScriptMode(`using 'new' keyword to construct a class`);
|
|
1697
1687
|
let newToken = this.advance();
|
|
1698
|
-
let nameExpr = this.
|
|
1699
|
-
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
|
+
}
|
|
1700
1697
|
let call = this.finishCall(leftParen, nameExpr);
|
|
1701
1698
|
//pop the call from the callExpressions list because this is technically something else
|
|
1702
1699
|
this.callExpressions.pop();
|
|
1703
1700
|
let result = new Expression_1.NewExpression(newToken, call);
|
|
1704
|
-
this._references.newExpressions.push(result);
|
|
1705
1701
|
return result;
|
|
1706
1702
|
}
|
|
1707
1703
|
/**
|
|
@@ -1722,21 +1718,15 @@ class Parser {
|
|
|
1722
1718
|
return this.newExpression();
|
|
1723
1719
|
}
|
|
1724
1720
|
let expr = this.primary();
|
|
1725
|
-
//an expression to keep for _references
|
|
1726
|
-
let referenceCallExpression;
|
|
1727
1721
|
while (true) {
|
|
1728
1722
|
if (this.matchAny(TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.QuestionLeftParen)) {
|
|
1729
1723
|
expr = this.finishCall(this.previous(), expr);
|
|
1730
|
-
//store this call expression in references
|
|
1731
|
-
referenceCallExpression = expr;
|
|
1732
1724
|
}
|
|
1733
1725
|
else if (this.matchAny(TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.QuestionLeftSquare) || this.matchSequence(TokenKind_1.TokenKind.QuestionDot, TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1734
1726
|
expr = this.indexedGet(expr);
|
|
1735
1727
|
}
|
|
1736
1728
|
else if (this.match(TokenKind_1.TokenKind.Callfunc)) {
|
|
1737
1729
|
expr = this.callfunc(expr);
|
|
1738
|
-
//store this callfunc expression in references
|
|
1739
|
-
referenceCallExpression = expr;
|
|
1740
1730
|
}
|
|
1741
1731
|
else if (this.matchAny(TokenKind_1.TokenKind.Dot, TokenKind_1.TokenKind.QuestionDot)) {
|
|
1742
1732
|
if (this.match(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
@@ -1744,18 +1734,23 @@ class Parser {
|
|
|
1744
1734
|
}
|
|
1745
1735
|
else {
|
|
1746
1736
|
let dot = this.previous();
|
|
1747
|
-
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
|
+
}
|
|
1748
1741
|
// force it into an identifier so the AST makes some sense
|
|
1749
1742
|
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1750
1743
|
expr = new Expression_1.DottedGetExpression(expr, name, dot);
|
|
1751
|
-
this.addPropertyHints(name);
|
|
1752
1744
|
}
|
|
1753
1745
|
}
|
|
1754
1746
|
else if (this.checkAny(TokenKind_1.TokenKind.At, TokenKind_1.TokenKind.QuestionAt)) {
|
|
1755
1747
|
let dot = this.advance();
|
|
1756
|
-
let name = this.
|
|
1748
|
+
let name = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.expectedAttributeNameAfterAtSymbol(), TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties);
|
|
1757
1749
|
// force it into an identifier so the AST makes some sense
|
|
1758
1750
|
name.kind = TokenKind_1.TokenKind.Identifier;
|
|
1751
|
+
if (!name) {
|
|
1752
|
+
break;
|
|
1753
|
+
}
|
|
1759
1754
|
expr = new Expression_1.XmlAttributeGetExpression(expr, name, dot);
|
|
1760
1755
|
//only allow a single `@` expression
|
|
1761
1756
|
break;
|
|
@@ -1764,10 +1759,6 @@ class Parser {
|
|
|
1764
1759
|
break;
|
|
1765
1760
|
}
|
|
1766
1761
|
}
|
|
1767
|
-
//if we found a callExpression, add it to `expressions` in references
|
|
1768
|
-
if (referenceCallExpression) {
|
|
1769
|
-
this._references.expressions.add(referenceCallExpression);
|
|
1770
|
-
}
|
|
1771
1762
|
return expr;
|
|
1772
1763
|
}
|
|
1773
1764
|
finishCall(openingParen, callee, addToCallExpressionList = true) {
|
|
@@ -1780,60 +1771,96 @@ class Parser {
|
|
|
1780
1771
|
this.diagnostics.push(Object.assign(Object.assign({}, DiagnosticMessages_1.DiagnosticMessages.tooManyCallableArguments(args.length, Expression_1.CallExpression.MaximumArguments)), { range: this.peek().range }));
|
|
1781
1772
|
throw this.lastDiagnosticAsError();
|
|
1782
1773
|
}
|
|
1783
|
-
|
|
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
|
+
}
|
|
1784
1782
|
} while (this.match(TokenKind_1.TokenKind.Comma));
|
|
1785
1783
|
}
|
|
1786
1784
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1787
|
-
const closingParen = this.
|
|
1788
|
-
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);
|
|
1789
1787
|
if (addToCallExpressionList) {
|
|
1790
1788
|
this.callExpressions.push(expression);
|
|
1791
1789
|
}
|
|
1792
1790
|
return expression;
|
|
1793
1791
|
}
|
|
1794
1792
|
/**
|
|
1795
|
-
*
|
|
1796
|
-
* Allows for built-in types (double, string, etc.) or namespaced custom types in Brighterscript mode
|
|
1797
|
-
* 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
|
|
1798
1794
|
*/
|
|
1799
1795
|
typeExpression() {
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
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);
|
|
1810
1813
|
}
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
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;
|
|
1814
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());
|
|
1815
1835
|
}
|
|
1816
1836
|
else {
|
|
1817
|
-
|
|
1818
|
-
|
|
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);
|
|
1819
1844
|
}
|
|
1820
|
-
//
|
|
1821
|
-
|
|
1822
|
-
|
|
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
|
+
}
|
|
1823
1852
|
// Check if it is an array - that is, if it has `[]` after the type
|
|
1824
|
-
// eg. `string[]` or `SomeKlass[]`
|
|
1853
|
+
// eg. `string[]` or `SomeKlass[]`
|
|
1854
|
+
// This is while loop, so it supports multidimensional arrays (eg. integer[][])
|
|
1825
1855
|
while (this.check(TokenKind_1.TokenKind.LeftSquareBracket)) {
|
|
1826
1856
|
const leftBracket = this.advance();
|
|
1827
1857
|
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1828
1858
|
const rightBracket = this.advance();
|
|
1829
|
-
|
|
1830
|
-
}
|
|
1831
|
-
else {
|
|
1832
|
-
break;
|
|
1859
|
+
expr = new Expression_1.TypedArrayExpression(expr, leftBracket, rightBracket);
|
|
1833
1860
|
}
|
|
1834
1861
|
}
|
|
1835
1862
|
}
|
|
1836
|
-
return
|
|
1863
|
+
return expr;
|
|
1837
1864
|
}
|
|
1838
1865
|
primary() {
|
|
1839
1866
|
switch (true) {
|
|
@@ -1849,7 +1876,7 @@ class Parser {
|
|
|
1849
1876
|
case this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedLocalIdentifiers) && this.checkNext(TokenKind_1.TokenKind.BackTick):
|
|
1850
1877
|
return this.templateString(true);
|
|
1851
1878
|
case this.matchAny(TokenKind_1.TokenKind.Identifier, ...this.allowedLocalIdentifiers):
|
|
1852
|
-
return new Expression_1.VariableExpression(this.previous()
|
|
1879
|
+
return new Expression_1.VariableExpression(this.previous());
|
|
1853
1880
|
case this.match(TokenKind_1.TokenKind.LeftParen):
|
|
1854
1881
|
let left = this.previous();
|
|
1855
1882
|
let expr = this.expression();
|
|
@@ -1863,7 +1890,7 @@ class Parser {
|
|
|
1863
1890
|
let token = Object.assign(this.previous(), {
|
|
1864
1891
|
kind: TokenKind_1.TokenKind.Identifier
|
|
1865
1892
|
});
|
|
1866
|
-
return new Expression_1.VariableExpression(token
|
|
1893
|
+
return new Expression_1.VariableExpression(token);
|
|
1867
1894
|
case this.checkAny(TokenKind_1.TokenKind.Function, TokenKind_1.TokenKind.Sub):
|
|
1868
1895
|
return this.anonymousFunction();
|
|
1869
1896
|
case this.check(TokenKind_1.TokenKind.RegexLiteral):
|
|
@@ -1891,23 +1918,31 @@ class Parser {
|
|
|
1891
1918
|
}
|
|
1892
1919
|
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1893
1920
|
}
|
|
1921
|
+
let closingSquare;
|
|
1894
1922
|
if (!this.match(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1895
|
-
|
|
1896
|
-
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Comment)) {
|
|
1897
|
-
if (this.checkPrevious(TokenKind_1.TokenKind.Comment) || this.check(TokenKind_1.TokenKind.Comment)) {
|
|
1898
|
-
let comment = this.check(TokenKind_1.TokenKind.Comment) ? this.advance() : this.previous();
|
|
1899
|
-
elements.push(new Statement_1.CommentStatement([comment]));
|
|
1900
|
-
}
|
|
1901
|
-
while (this.match(TokenKind_1.TokenKind.Newline)) {
|
|
1902
|
-
}
|
|
1903
|
-
if (this.check(TokenKind_1.TokenKind.RightSquareBracket)) {
|
|
1904
|
-
break;
|
|
1905
|
-
}
|
|
1923
|
+
try {
|
|
1906
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
|
+
}
|
|
1907
1937
|
}
|
|
1908
|
-
|
|
1938
|
+
catch (error) {
|
|
1939
|
+
this.rethrowNonDiagnosticError(error);
|
|
1940
|
+
}
|
|
1941
|
+
closingSquare = this.tryConsume(DiagnosticMessages_1.DiagnosticMessages.unmatchedLeftSquareBraceAfterArrayLiteral(), TokenKind_1.TokenKind.RightSquareBracket);
|
|
1942
|
+
}
|
|
1943
|
+
else {
|
|
1944
|
+
closingSquare = this.previous();
|
|
1909
1945
|
}
|
|
1910
|
-
let closingSquare = this.previous();
|
|
1911
1946
|
//this.consume("Expected newline or ':' after array literal", TokenKind.Newline, TokenKind.Colon, TokenKind.Eof);
|
|
1912
1947
|
return new Expression_1.ArrayLiteralExpression(elements, openingSquare, closingSquare);
|
|
1913
1948
|
}
|
|
@@ -1921,7 +1956,7 @@ class Parser {
|
|
|
1921
1956
|
range: null
|
|
1922
1957
|
};
|
|
1923
1958
|
if (this.checkAny(TokenKind_1.TokenKind.Identifier, ...TokenKind_1.AllowedProperties)) {
|
|
1924
|
-
result.keyToken = this.
|
|
1959
|
+
result.keyToken = this.identifier(...TokenKind_1.AllowedProperties);
|
|
1925
1960
|
}
|
|
1926
1961
|
else if (this.check(TokenKind_1.TokenKind.StringLiteral)) {
|
|
1927
1962
|
result.keyToken = this.advance();
|
|
@@ -1935,51 +1970,58 @@ class Parser {
|
|
|
1935
1970
|
return result;
|
|
1936
1971
|
};
|
|
1937
1972
|
while (this.match(TokenKind_1.TokenKind.Newline)) { }
|
|
1973
|
+
let closingBrace;
|
|
1938
1974
|
if (!this.match(TokenKind_1.TokenKind.RightCurlyBrace)) {
|
|
1939
1975
|
let lastAAMember;
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
else {
|
|
1945
|
-
let k = key();
|
|
1946
|
-
let expr = this.expression();
|
|
1947
|
-
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
|
|
1948
|
-
members.push(lastAAMember);
|
|
1949
|
-
}
|
|
1950
|
-
while (this.matchAny(TokenKind_1.TokenKind.Comma, TokenKind_1.TokenKind.Newline, TokenKind_1.TokenKind.Colon, TokenKind_1.TokenKind.Comment)) {
|
|
1951
|
-
// collect comma at end of expression
|
|
1952
|
-
if (lastAAMember && this.checkPrevious(TokenKind_1.TokenKind.Comma)) {
|
|
1953
|
-
lastAAMember.commaToken = this.previous();
|
|
1954
|
-
}
|
|
1955
|
-
//check for comment at the end of the current line
|
|
1956
|
-
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1957
|
-
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1958
|
-
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()]));
|
|
1959
1980
|
}
|
|
1960
1981
|
else {
|
|
1961
|
-
|
|
1962
|
-
|
|
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
|
|
1963
1993
|
if (this.check(TokenKind_1.TokenKind.Comment) || this.checkPrevious(TokenKind_1.TokenKind.Comment)) {
|
|
1964
1994
|
let token = this.checkPrevious(TokenKind_1.TokenKind.Comment) ? this.previous() : this.advance();
|
|
1965
|
-
lastAAMember = null;
|
|
1966
1995
|
members.push(new Statement_1.CommentStatement([token]));
|
|
1967
|
-
continue;
|
|
1968
1996
|
}
|
|
1969
|
-
|
|
1970
|
-
|
|
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);
|
|
1971
2013
|
}
|
|
1972
|
-
let k = key();
|
|
1973
|
-
let expr = this.expression();
|
|
1974
|
-
lastAAMember = new Expression_1.AAMemberExpression(k.keyToken, k.colonToken, expr, getBscTypeFromExpression(expr, this.currentFunctionExpression));
|
|
1975
|
-
members.push(lastAAMember);
|
|
1976
2014
|
}
|
|
1977
2015
|
}
|
|
1978
|
-
|
|
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();
|
|
1979
2023
|
}
|
|
1980
|
-
|
|
1981
|
-
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace, this.currentFunctionExpression);
|
|
1982
|
-
this.addPropertyHints(aaExpr);
|
|
2024
|
+
const aaExpr = new Expression_1.AALiteralExpression(members, openingBrace, closingBrace);
|
|
1983
2025
|
return aaExpr;
|
|
1984
2026
|
}
|
|
1985
2027
|
/**
|
|
@@ -1994,7 +2036,7 @@ class Parser {
|
|
|
1994
2036
|
}
|
|
1995
2037
|
/**
|
|
1996
2038
|
* Pop token if we encounter a token in the specified list
|
|
1997
|
-
* @param tokenKinds
|
|
2039
|
+
* @param tokenKinds a list of tokenKinds where any tokenKind in this list will result in a match
|
|
1998
2040
|
*/
|
|
1999
2041
|
matchAny(...tokenKinds) {
|
|
2000
2042
|
for (let tokenKind of tokenKinds) {
|
|
@@ -2007,7 +2049,7 @@ class Parser {
|
|
|
2007
2049
|
}
|
|
2008
2050
|
/**
|
|
2009
2051
|
* If the next series of tokens matches the given set of tokens, pop them all
|
|
2010
|
-
* @param tokenKinds
|
|
2052
|
+
* @param tokenKinds a list of tokenKinds used to match the next set of tokens
|
|
2011
2053
|
*/
|
|
2012
2054
|
matchSequence(...tokenKinds) {
|
|
2013
2055
|
var _a;
|
|
@@ -2034,6 +2076,14 @@ class Parser {
|
|
|
2034
2076
|
throw error;
|
|
2035
2077
|
}
|
|
2036
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
|
+
}
|
|
2037
2087
|
consumeToken(tokenKind) {
|
|
2038
2088
|
return this.consume(DiagnosticMessages_1.DiagnosticMessages.expectedToken(tokenKind), tokenKind);
|
|
2039
2089
|
}
|
|
@@ -2122,6 +2172,18 @@ class Parser {
|
|
|
2122
2172
|
previous() {
|
|
2123
2173
|
return this.tokens[this.current - 1];
|
|
2124
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
|
+
}
|
|
2125
2187
|
/**
|
|
2126
2188
|
* Get the token that is {offset} indexes away from {this.current}
|
|
2127
2189
|
* @param offset the number of index steps away from current index to fetch
|
|
@@ -2162,391 +2224,6 @@ class Parser {
|
|
|
2162
2224
|
this.advance();
|
|
2163
2225
|
}
|
|
2164
2226
|
}
|
|
2165
|
-
/**
|
|
2166
|
-
* Get the token at the specified position
|
|
2167
|
-
* @param position
|
|
2168
|
-
*/
|
|
2169
|
-
getTokenAt(position) {
|
|
2170
|
-
for (let token of this.tokens) {
|
|
2171
|
-
if (util_1.util.rangeContains(token.range, position)) {
|
|
2172
|
-
return token;
|
|
2173
|
-
}
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2176
|
-
/**
|
|
2177
|
-
* Get the token closest to the position. if no token is found, the previous token is returned
|
|
2178
|
-
* @param position
|
|
2179
|
-
* @param tokens
|
|
2180
|
-
*/
|
|
2181
|
-
getClosestToken(position) {
|
|
2182
|
-
let tokens = this.tokens;
|
|
2183
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
2184
|
-
let token = tokens[i];
|
|
2185
|
-
if (util_1.util.rangeContains(token.range, position)) {
|
|
2186
|
-
return token;
|
|
2187
|
-
}
|
|
2188
|
-
//if the position less than this token range, then this position touches no token,
|
|
2189
|
-
if (util_1.util.positionIsGreaterThanRange(position, token.range) === false) {
|
|
2190
|
-
let t = tokens[i - 1];
|
|
2191
|
-
//return the token or the first token
|
|
2192
|
-
return t ? t : tokens[0];
|
|
2193
|
-
}
|
|
2194
|
-
}
|
|
2195
|
-
//return the last token
|
|
2196
|
-
return tokens[tokens.length - 1];
|
|
2197
|
-
}
|
|
2198
|
-
isPositionNextToTokenKind(position, tokenKind) {
|
|
2199
|
-
const closestToken = this.getClosestToken(position);
|
|
2200
|
-
const previousToken = this.getPreviousToken(closestToken);
|
|
2201
|
-
const previousTokenKind = previousToken === null || previousToken === void 0 ? void 0 : previousToken.kind;
|
|
2202
|
-
//next to matched token
|
|
2203
|
-
if (!closestToken || closestToken.kind === TokenKind_1.TokenKind.Eof) {
|
|
2204
|
-
return false;
|
|
2205
|
-
}
|
|
2206
|
-
else if (closestToken.kind === tokenKind) {
|
|
2207
|
-
return true;
|
|
2208
|
-
}
|
|
2209
|
-
else if (closestToken.kind === TokenKind_1.TokenKind.Newline || previousTokenKind === TokenKind_1.TokenKind.Newline) {
|
|
2210
|
-
return false;
|
|
2211
|
-
//next to an identifier, which is next to token kind
|
|
2212
|
-
}
|
|
2213
|
-
else if (closestToken.kind === TokenKind_1.TokenKind.Identifier && previousTokenKind === tokenKind) {
|
|
2214
|
-
return true;
|
|
2215
|
-
}
|
|
2216
|
-
else {
|
|
2217
|
-
return false;
|
|
2218
|
-
}
|
|
2219
|
-
}
|
|
2220
|
-
getTokenBefore(currentToken, tokenKind) {
|
|
2221
|
-
const index = this.tokens.indexOf(currentToken);
|
|
2222
|
-
for (let i = index - 1; i >= 0; i--) {
|
|
2223
|
-
currentToken = this.tokens[i];
|
|
2224
|
-
if (currentToken.kind === TokenKind_1.TokenKind.Newline) {
|
|
2225
|
-
break;
|
|
2226
|
-
}
|
|
2227
|
-
else if (currentToken.kind === tokenKind) {
|
|
2228
|
-
return currentToken;
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
return undefined;
|
|
2232
|
-
}
|
|
2233
|
-
tokenFollows(currentToken, tokenKind) {
|
|
2234
|
-
const index = this.tokens.indexOf(currentToken);
|
|
2235
|
-
if (index > 0) {
|
|
2236
|
-
return this.tokens[index - 1].kind === tokenKind;
|
|
2237
|
-
}
|
|
2238
|
-
return false;
|
|
2239
|
-
}
|
|
2240
|
-
getTokensUntil(currentToken, tokenKind, direction = -1) {
|
|
2241
|
-
let tokens = [];
|
|
2242
|
-
for (let i = this.tokens.indexOf(currentToken); direction === -1 ? i >= 0 : i === this.tokens.length; i += direction) {
|
|
2243
|
-
currentToken = this.tokens[i];
|
|
2244
|
-
if (currentToken.kind === TokenKind_1.TokenKind.Newline || currentToken.kind === tokenKind) {
|
|
2245
|
-
break;
|
|
2246
|
-
}
|
|
2247
|
-
tokens.push(currentToken);
|
|
2248
|
-
}
|
|
2249
|
-
return tokens;
|
|
2250
|
-
}
|
|
2251
|
-
getPreviousToken(token) {
|
|
2252
|
-
let idx = this.tokens.indexOf(token);
|
|
2253
|
-
return this.tokens[idx - 1];
|
|
2254
|
-
}
|
|
2255
|
-
getPreviousTokenFromIndex(idx) {
|
|
2256
|
-
return { token: this.tokens[idx - 1], index: idx - 1 };
|
|
2257
|
-
}
|
|
2258
|
-
getPreviousTokenIgnoreNests(currentTokenIndex, leftBracketType, rightBracketType) {
|
|
2259
|
-
let currentToken = this.tokens[currentTokenIndex];
|
|
2260
|
-
let previousTokenResult;
|
|
2261
|
-
function isRightBracket(token) {
|
|
2262
|
-
return (token === null || token === void 0 ? void 0 : token.kind) === rightBracketType;
|
|
2263
|
-
}
|
|
2264
|
-
function isLeftBracket(token) {
|
|
2265
|
-
return (token === null || token === void 0 ? void 0 : token.kind) === leftBracketType;
|
|
2266
|
-
}
|
|
2267
|
-
let lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2268
|
-
let lastTokenWasLeftBracket = false;
|
|
2269
|
-
let bracketNestCount = 0;
|
|
2270
|
-
let hasBrackets = false;
|
|
2271
|
-
// check for nested function call
|
|
2272
|
-
if (isRightBracket(currentToken)) {
|
|
2273
|
-
bracketNestCount++;
|
|
2274
|
-
hasBrackets = true;
|
|
2275
|
-
}
|
|
2276
|
-
while (currentToken && bracketNestCount > 0) {
|
|
2277
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2278
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2279
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2280
|
-
lastTokenWasLeftBracket = false;
|
|
2281
|
-
if (isRightBracket(currentToken)) {
|
|
2282
|
-
bracketNestCount++;
|
|
2283
|
-
}
|
|
2284
|
-
while (isLeftBracket(currentToken)) {
|
|
2285
|
-
bracketNestCount--;
|
|
2286
|
-
lastTokenWasLeftBracket = true;
|
|
2287
|
-
lastTokenHadLeadingWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2288
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2289
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2290
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2291
|
-
}
|
|
2292
|
-
}
|
|
2293
|
-
// We will not be able to decipher the token type if it was in brackets
|
|
2294
|
-
// e.g (someVar+otherVar).toStr() -- we don't bother trying to decipher what "(someVar+otherVar)" is
|
|
2295
|
-
let isUnknown = (lastTokenWasLeftBracket && (lastTokenHadLeadingWhitespace || !this.isAcceptableChainToken(currentToken)));
|
|
2296
|
-
const tokenWithIndex = { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: isUnknown, hasBrackets: hasBrackets };
|
|
2297
|
-
return tokenWithIndex;
|
|
2298
|
-
}
|
|
2299
|
-
/**
|
|
2300
|
-
* Finds the previous token in a chain (e.g. 'm.obj.func(someFunc()).value'), skipping over any arguments of function calls
|
|
2301
|
-
* If this function was called with the token at 'value' above, the previous identifier in the chain is 'func'
|
|
2302
|
-
* @param currentTokenIndex token index to start from
|
|
2303
|
-
* @param allowCurrent can the current token be the token that's the identifier?
|
|
2304
|
-
* @returns the previous identifer
|
|
2305
|
-
*/
|
|
2306
|
-
getPreviousTokenInChain(currentTokenIndex, allowCurrent = false) {
|
|
2307
|
-
let currentToken = this.tokens[currentTokenIndex];
|
|
2308
|
-
let previousTokenResult;
|
|
2309
|
-
let usage = TokenUsage.Direct;
|
|
2310
|
-
if (!allowCurrent) {
|
|
2311
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2312
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2313
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2314
|
-
}
|
|
2315
|
-
if ((currentToken === null || currentToken === void 0 ? void 0 : currentToken.kind) === TokenKind_1.TokenKind.Dot) {
|
|
2316
|
-
previousTokenResult = this.getPreviousTokenFromIndex(currentTokenIndex);
|
|
2317
|
-
currentToken = previousTokenResult.token;
|
|
2318
|
-
currentTokenIndex = previousTokenResult.index;
|
|
2319
|
-
}
|
|
2320
|
-
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftParen, TokenKind_1.TokenKind.RightParen);
|
|
2321
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2322
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2323
|
-
if (previousTokenResult.hasBrackets) {
|
|
2324
|
-
usage = TokenUsage.Call;
|
|
2325
|
-
}
|
|
2326
|
-
let tokenTypeIsNotKnowable = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable;
|
|
2327
|
-
if (currentTokenIndex) {
|
|
2328
|
-
previousTokenResult = this.getPreviousTokenIgnoreNests(currentTokenIndex, TokenKind_1.TokenKind.LeftSquareBracket, TokenKind_1.TokenKind.RightSquareBracket);
|
|
2329
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2330
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2331
|
-
if (previousTokenResult.hasBrackets) {
|
|
2332
|
-
usage = TokenUsage.ArrayReference;
|
|
2333
|
-
}
|
|
2334
|
-
}
|
|
2335
|
-
tokenTypeIsNotKnowable = tokenTypeIsNotKnowable || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2336
|
-
if (tokenTypeIsNotKnowable || this.isAcceptableChainToken(currentToken)) {
|
|
2337
|
-
// either we have a valid chain token, or we can't know what the token type is
|
|
2338
|
-
return { token: currentToken, index: currentTokenIndex, tokenTypeIsNotKnowable: tokenTypeIsNotKnowable, usage: usage };
|
|
2339
|
-
}
|
|
2340
|
-
return undefined;
|
|
2341
|
-
}
|
|
2342
|
-
isAcceptableChainToken(currentToken, lastTokenHasWhitespace = false) {
|
|
2343
|
-
if (!currentToken || lastTokenHasWhitespace) {
|
|
2344
|
-
return false;
|
|
2345
|
-
}
|
|
2346
|
-
if (currentToken.kind === TokenKind_1.TokenKind.Identifier) {
|
|
2347
|
-
return true;
|
|
2348
|
-
}
|
|
2349
|
-
if (currentToken.leadingWhitespace.length === 0) {
|
|
2350
|
-
// start of the chain
|
|
2351
|
-
return TokenKind_1.AllowedLocalIdentifiers.includes(currentToken.kind);
|
|
2352
|
-
}
|
|
2353
|
-
// not the start of the chain
|
|
2354
|
-
return TokenKind_1.AllowedProperties.includes(currentToken.kind);
|
|
2355
|
-
}
|
|
2356
|
-
/**
|
|
2357
|
-
* Builds up a chain of tokens, starting with the first in the chain, and ending with currentToken
|
|
2358
|
-
* e.g. m.prop.method().field (with 'field' as currentToken) -> ["m", "prop", "method", "field"], with each element as a token
|
|
2359
|
-
* @param currentToken the token that is the end of the chain
|
|
2360
|
-
* @returns array of tokens
|
|
2361
|
-
*/
|
|
2362
|
-
getTokenChain(currentToken) {
|
|
2363
|
-
const tokenChain = [];
|
|
2364
|
-
let currentTokenIndex = this.tokens.indexOf(currentToken);
|
|
2365
|
-
let previousTokenResult;
|
|
2366
|
-
let lastTokenHasWhitespace = false;
|
|
2367
|
-
let includesUnknown = false;
|
|
2368
|
-
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex, true);
|
|
2369
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2370
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2371
|
-
if (this.isAcceptableChainToken(currentToken)) {
|
|
2372
|
-
tokenChain.push(previousTokenResult);
|
|
2373
|
-
lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2374
|
-
}
|
|
2375
|
-
if (!lastTokenHasWhitespace) {
|
|
2376
|
-
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
|
|
2377
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2378
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2379
|
-
includesUnknown = !!(previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2380
|
-
while (!includesUnknown && this.isAcceptableChainToken(currentToken, lastTokenHasWhitespace)) {
|
|
2381
|
-
tokenChain.push(previousTokenResult);
|
|
2382
|
-
lastTokenHasWhitespace = (currentToken === null || currentToken === void 0 ? void 0 : currentToken.leadingWhitespace.length) > 0;
|
|
2383
|
-
if (!lastTokenHasWhitespace) {
|
|
2384
|
-
previousTokenResult = this.getPreviousTokenInChain(currentTokenIndex);
|
|
2385
|
-
currentToken = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.token;
|
|
2386
|
-
currentTokenIndex = previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.index;
|
|
2387
|
-
includesUnknown = includesUnknown || (previousTokenResult === null || previousTokenResult === void 0 ? void 0 : previousTokenResult.tokenTypeIsNotKnowable);
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
tokenChain.reverse();
|
|
2392
|
-
return { chain: tokenChain, includesUnknowableTokenType: !!includesUnknown };
|
|
2393
|
-
}
|
|
2394
|
-
/**
|
|
2395
|
-
* References are found during the initial parse.
|
|
2396
|
-
* However, sometimes plugins can modify the AST, requiring a full walk to re-compute all references.
|
|
2397
|
-
* This does that walk.
|
|
2398
|
-
*/
|
|
2399
|
-
findReferences() {
|
|
2400
|
-
this._references = new References();
|
|
2401
|
-
const excludedExpressions = new Set();
|
|
2402
|
-
const visitCallExpression = (e) => {
|
|
2403
|
-
for (const p of e.args) {
|
|
2404
|
-
this._references.expressions.add(p);
|
|
2405
|
-
}
|
|
2406
|
-
//add calls that were not excluded (from loop below)
|
|
2407
|
-
if (!excludedExpressions.has(e)) {
|
|
2408
|
-
this._references.expressions.add(e);
|
|
2409
|
-
}
|
|
2410
|
-
//if this call is part of a longer expression that includes a call higher up, find that higher one and remove it
|
|
2411
|
-
if (e.callee) {
|
|
2412
|
-
let node = e.callee;
|
|
2413
|
-
while (node) {
|
|
2414
|
-
//the primary goal for this loop. If we found a parent call expression, remove it from `references`
|
|
2415
|
-
if ((0, reflection_1.isCallExpression)(node)) {
|
|
2416
|
-
this.references.expressions.delete(node);
|
|
2417
|
-
excludedExpressions.add(node);
|
|
2418
|
-
//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.
|
|
2419
|
-
break;
|
|
2420
|
-
//when we hit a variable expression, we're definitely at the leftmost expression so stop
|
|
2421
|
-
}
|
|
2422
|
-
else if ((0, reflection_1.isVariableExpression)(node)) {
|
|
2423
|
-
break;
|
|
2424
|
-
//if
|
|
2425
|
-
}
|
|
2426
|
-
else if ((0, reflection_1.isDottedGetExpression)(node) || (0, reflection_1.isIndexedGetExpression)(node)) {
|
|
2427
|
-
node = node.obj;
|
|
2428
|
-
}
|
|
2429
|
-
else {
|
|
2430
|
-
//some expression we don't understand. log it and quit the loop
|
|
2431
|
-
this.logger.info('Encountered unknown expression while calculating function expression chain', node);
|
|
2432
|
-
break;
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
}
|
|
2436
|
-
};
|
|
2437
|
-
//gather up all the top-level statements
|
|
2438
|
-
this.ast.walk((0, visitors_1.createVisitor)({
|
|
2439
|
-
AssignmentStatement: s => {
|
|
2440
|
-
this._references.assignmentStatements.push(s);
|
|
2441
|
-
this.references.expressions.add(s.value);
|
|
2442
|
-
},
|
|
2443
|
-
ClassStatement: s => {
|
|
2444
|
-
this._references.classStatements.push(s);
|
|
2445
|
-
},
|
|
2446
|
-
FieldStatement: s => {
|
|
2447
|
-
if (s.initialValue) {
|
|
2448
|
-
this._references.expressions.add(s.initialValue);
|
|
2449
|
-
}
|
|
2450
|
-
},
|
|
2451
|
-
InterfaceStatement: s => {
|
|
2452
|
-
this._references.interfaceStatements.push(s);
|
|
2453
|
-
},
|
|
2454
|
-
NamespaceStatement: s => {
|
|
2455
|
-
this._references.namespaceStatements.push(s);
|
|
2456
|
-
},
|
|
2457
|
-
FunctionStatement: s => {
|
|
2458
|
-
this._references.functionStatements.push(s);
|
|
2459
|
-
},
|
|
2460
|
-
ImportStatement: s => {
|
|
2461
|
-
this._references.importStatements.push(s);
|
|
2462
|
-
},
|
|
2463
|
-
LibraryStatement: s => {
|
|
2464
|
-
this._references.libraryStatements.push(s);
|
|
2465
|
-
},
|
|
2466
|
-
FunctionExpression: (expression, parent) => {
|
|
2467
|
-
if (!(0, reflection_1.isMethodStatement)(parent) && !(0, reflection_1.isInterfaceMethodStatement)(parent)) {
|
|
2468
|
-
this._references.functionExpressions.push(expression);
|
|
2469
|
-
}
|
|
2470
|
-
},
|
|
2471
|
-
NewExpression: e => {
|
|
2472
|
-
this._references.newExpressions.push(e);
|
|
2473
|
-
for (const p of e.call.args) {
|
|
2474
|
-
this._references.expressions.add(p);
|
|
2475
|
-
}
|
|
2476
|
-
},
|
|
2477
|
-
ExpressionStatement: s => {
|
|
2478
|
-
this._references.expressions.add(s.expression);
|
|
2479
|
-
},
|
|
2480
|
-
CallfuncExpression: e => {
|
|
2481
|
-
visitCallExpression(e);
|
|
2482
|
-
},
|
|
2483
|
-
CallExpression: e => {
|
|
2484
|
-
visitCallExpression(e);
|
|
2485
|
-
},
|
|
2486
|
-
AALiteralExpression: e => {
|
|
2487
|
-
this.addPropertyHints(e);
|
|
2488
|
-
this._references.expressions.add(e);
|
|
2489
|
-
for (const member of e.elements) {
|
|
2490
|
-
if ((0, reflection_1.isAAMemberExpression)(member)) {
|
|
2491
|
-
this._references.expressions.add(member.value);
|
|
2492
|
-
}
|
|
2493
|
-
}
|
|
2494
|
-
},
|
|
2495
|
-
BinaryExpression: (e, parent) => {
|
|
2496
|
-
//walk the chain of binary expressions and add each one to the list of expressions
|
|
2497
|
-
const expressions = [e];
|
|
2498
|
-
let expression;
|
|
2499
|
-
while ((expression = expressions.pop())) {
|
|
2500
|
-
if ((0, reflection_1.isBinaryExpression)(expression)) {
|
|
2501
|
-
expressions.push(expression.left, expression.right);
|
|
2502
|
-
}
|
|
2503
|
-
else {
|
|
2504
|
-
this._references.expressions.add(expression);
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
},
|
|
2508
|
-
ArrayLiteralExpression: e => {
|
|
2509
|
-
for (const element of e.elements) {
|
|
2510
|
-
//keep everything except comments
|
|
2511
|
-
if (!(0, reflection_1.isCommentStatement)(element)) {
|
|
2512
|
-
this._references.expressions.add(element);
|
|
2513
|
-
}
|
|
2514
|
-
}
|
|
2515
|
-
},
|
|
2516
|
-
DottedGetExpression: e => {
|
|
2517
|
-
this.addPropertyHints(e.name);
|
|
2518
|
-
},
|
|
2519
|
-
DottedSetStatement: e => {
|
|
2520
|
-
this.addPropertyHints(e.name);
|
|
2521
|
-
},
|
|
2522
|
-
EnumStatement: e => {
|
|
2523
|
-
this._references.enumStatements.push(e);
|
|
2524
|
-
},
|
|
2525
|
-
UnaryExpression: e => {
|
|
2526
|
-
this._references.expressions.add(e);
|
|
2527
|
-
},
|
|
2528
|
-
IncrementStatement: e => {
|
|
2529
|
-
this._references.expressions.add(e);
|
|
2530
|
-
}
|
|
2531
|
-
}), {
|
|
2532
|
-
walkMode: visitors_1.WalkMode.visitAllRecursive
|
|
2533
|
-
});
|
|
2534
|
-
}
|
|
2535
|
-
getContainingClass(currentToken) {
|
|
2536
|
-
return this.references.classStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
2537
|
-
}
|
|
2538
|
-
getContainingAA(currentToken) {
|
|
2539
|
-
return this.references.aaLiterals.find((aa) => util_1.util.rangeContains(aa.range, currentToken.range.start));
|
|
2540
|
-
}
|
|
2541
|
-
getContainingNamespace(currentToken) {
|
|
2542
|
-
return this.references.namespaceStatements.find((cs) => util_1.util.rangeContains(cs.range, currentToken.range.start));
|
|
2543
|
-
}
|
|
2544
|
-
getContainingFunctionExpression(currentToken) {
|
|
2545
|
-
return this.getContainingFunctionExpressionByPosition(currentToken.range.start);
|
|
2546
|
-
}
|
|
2547
|
-
getContainingFunctionExpressionByPosition(position) {
|
|
2548
|
-
return this.references.functionExpressions.find((fe) => util_1.util.rangeContains(fe.range, position));
|
|
2549
|
-
}
|
|
2550
2227
|
dispose() {
|
|
2551
2228
|
}
|
|
2552
2229
|
}
|
|
@@ -2556,142 +2233,9 @@ var ParseMode;
|
|
|
2556
2233
|
ParseMode["BrightScript"] = "BrightScript";
|
|
2557
2234
|
ParseMode["BrighterScript"] = "BrighterScript";
|
|
2558
2235
|
})(ParseMode = exports.ParseMode || (exports.ParseMode = {}));
|
|
2559
|
-
class References {
|
|
2560
|
-
constructor() {
|
|
2561
|
-
this.cache = new Cache_1.Cache();
|
|
2562
|
-
this.assignmentStatements = [];
|
|
2563
|
-
this.classStatements = [];
|
|
2564
|
-
this.dottedSetStatements = [];
|
|
2565
|
-
this.aaLiterals = [];
|
|
2566
|
-
this.functionExpressions = [];
|
|
2567
|
-
this.functionStatements = [];
|
|
2568
|
-
this.interfaceStatements = [];
|
|
2569
|
-
this.enumStatements = [];
|
|
2570
|
-
/**
|
|
2571
|
-
* A collection of full expressions. This excludes intermediary expressions.
|
|
2572
|
-
*
|
|
2573
|
-
* Example 1:
|
|
2574
|
-
* `a.b.c` is composed of `a` (variableExpression) `.b` (DottedGetExpression) `.c` (DottedGetExpression)
|
|
2575
|
-
* This will only contain the final `.c` DottedGetExpression because `.b` and `a` can both be derived by walking back from the `.c` DottedGetExpression.
|
|
2576
|
-
*
|
|
2577
|
-
* Example 2:
|
|
2578
|
-
* `name.space.doSomething(a.b.c)` will result in 2 entries in this list. the `CallExpression` for `doSomething`, and the `.c` DottedGetExpression.
|
|
2579
|
-
*
|
|
2580
|
-
* Example 3:
|
|
2581
|
-
* `value = SomeEnum.value > 2 or SomeEnum.otherValue < 10` will result in 4 entries. `SomeEnum.value`, `2`, `SomeEnum.otherValue`, `10`
|
|
2582
|
-
*/
|
|
2583
|
-
this.expressions = new Set();
|
|
2584
|
-
this.importStatements = [];
|
|
2585
|
-
this.libraryStatements = [];
|
|
2586
|
-
this.namespaceStatements = [];
|
|
2587
|
-
this.newExpressions = [];
|
|
2588
|
-
this.propertyHints = {};
|
|
2589
|
-
}
|
|
2590
|
-
get classStatementLookup() {
|
|
2591
|
-
if (!this._classStatementLookup) {
|
|
2592
|
-
this._classStatementLookup = new Map();
|
|
2593
|
-
for (const stmt of this.classStatements) {
|
|
2594
|
-
this._classStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2595
|
-
}
|
|
2596
|
-
}
|
|
2597
|
-
return this._classStatementLookup;
|
|
2598
|
-
}
|
|
2599
|
-
/**
|
|
2600
|
-
* A map of function statements, indexed by fully-namespaced lower function name.
|
|
2601
|
-
*/
|
|
2602
|
-
get functionStatementLookup() {
|
|
2603
|
-
if (!this._functionStatementLookup) {
|
|
2604
|
-
this._functionStatementLookup = new Map();
|
|
2605
|
-
for (const stmt of this.functionStatements) {
|
|
2606
|
-
this._functionStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2607
|
-
}
|
|
2608
|
-
}
|
|
2609
|
-
return this._functionStatementLookup;
|
|
2610
|
-
}
|
|
2611
|
-
get interfaceStatementLookup() {
|
|
2612
|
-
if (!this._interfaceStatementLookup) {
|
|
2613
|
-
this._interfaceStatementLookup = new Map();
|
|
2614
|
-
for (const stmt of this.interfaceStatements) {
|
|
2615
|
-
this._interfaceStatementLookup.set(stmt.getName(ParseMode.BrighterScript).toLowerCase(), stmt);
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
return this._interfaceStatementLookup;
|
|
2619
|
-
}
|
|
2620
|
-
get enumStatementLookup() {
|
|
2621
|
-
return this.cache.getOrAdd('enums', () => {
|
|
2622
|
-
const result = new Map();
|
|
2623
|
-
for (const stmt of this.enumStatements) {
|
|
2624
|
-
result.set(stmt.fullName.toLowerCase(), stmt);
|
|
2625
|
-
}
|
|
2626
|
-
return result;
|
|
2627
|
-
});
|
|
2628
|
-
}
|
|
2629
|
-
}
|
|
2630
|
-
exports.References = References;
|
|
2631
|
-
var TokenUsage;
|
|
2632
|
-
(function (TokenUsage) {
|
|
2633
|
-
TokenUsage[TokenUsage["Direct"] = 1] = "Direct";
|
|
2634
|
-
TokenUsage[TokenUsage["Call"] = 2] = "Call";
|
|
2635
|
-
TokenUsage[TokenUsage["ArrayReference"] = 3] = "ArrayReference";
|
|
2636
|
-
})(TokenUsage = exports.TokenUsage || (exports.TokenUsage = {}));
|
|
2637
2236
|
class CancelStatementError extends Error {
|
|
2638
2237
|
constructor() {
|
|
2639
2238
|
super('CancelStatement');
|
|
2640
2239
|
}
|
|
2641
2240
|
}
|
|
2642
|
-
/**
|
|
2643
|
-
* Gets the type of an expression. If it can not be processed, will return DynamicType
|
|
2644
|
-
*
|
|
2645
|
-
* @param expression the Expression to process
|
|
2646
|
-
* @param functionExpression the wrapping function expression
|
|
2647
|
-
* @return the best guess type of that expression
|
|
2648
|
-
*/
|
|
2649
|
-
function getBscTypeFromExpression(expression, functionExpression) {
|
|
2650
|
-
try {
|
|
2651
|
-
if ((0, reflection_1.isFunctionExpression)(expression)) {
|
|
2652
|
-
return expression.getFunctionType();
|
|
2653
|
-
//literal
|
|
2654
|
-
}
|
|
2655
|
-
else if ((0, reflection_1.isLiteralExpression)(expression)) {
|
|
2656
|
-
return expression.type;
|
|
2657
|
-
//Associative array literal
|
|
2658
|
-
}
|
|
2659
|
-
else if ((0, reflection_1.isAALiteralExpression)(expression)) {
|
|
2660
|
-
return new ObjectType_1.ObjectType('object', expression.memberTable);
|
|
2661
|
-
//Array literal
|
|
2662
|
-
}
|
|
2663
|
-
else if ((0, reflection_1.isArrayLiteralExpression)(expression)) {
|
|
2664
|
-
const innerTypes = expression.elements.filter((element) => !(0, reflection_1.isCommentStatement)(element)).map((element) => {
|
|
2665
|
-
return getBscTypeFromExpression(element, functionExpression);
|
|
2666
|
-
});
|
|
2667
|
-
return new ArrayType_1.ArrayType(...innerTypes);
|
|
2668
|
-
//function call
|
|
2669
|
-
}
|
|
2670
|
-
else if ((0, reflection_1.isNewExpression)(expression)) {
|
|
2671
|
-
return (0, helpers_1.getTypeFromNewExpression)(expression, functionExpression);
|
|
2672
|
-
//Function call
|
|
2673
|
-
}
|
|
2674
|
-
else if ((0, reflection_1.isCallExpression)(expression)) {
|
|
2675
|
-
return (0, helpers_1.getTypeFromCallExpression)(expression, functionExpression);
|
|
2676
|
-
}
|
|
2677
|
-
else if ((0, reflection_1.isVariableExpression)(expression)) {
|
|
2678
|
-
return (0, helpers_1.getTypeFromVariableExpression)(expression, functionExpression);
|
|
2679
|
-
}
|
|
2680
|
-
else if ((0, reflection_1.isDottedGetExpression)(expression)) {
|
|
2681
|
-
return (0, helpers_1.getTypeFromDottedGetExpression)(expression, functionExpression);
|
|
2682
|
-
}
|
|
2683
|
-
else if ((0, reflection_1.isIndexedGetExpression)(expression)) {
|
|
2684
|
-
const source = getBscTypeFromExpression(expression.obj, functionExpression);
|
|
2685
|
-
if ((0, reflection_1.isArrayType)(source)) {
|
|
2686
|
-
return source.getDefaultType();
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
|
-
}
|
|
2690
|
-
catch (e) {
|
|
2691
|
-
//do nothing. Just return dynamic
|
|
2692
|
-
}
|
|
2693
|
-
//fallback to dynamic
|
|
2694
|
-
return new DynamicType_1.DynamicType();
|
|
2695
|
-
}
|
|
2696
|
-
exports.getBscTypeFromExpression = getBscTypeFromExpression;
|
|
2697
2241
|
//# sourceMappingURL=Parser.js.map
|